Now I'll show how to create options menu that will look
like iPhone's Action Sheet.
Preparings.
First let's create animations for the menu. The menu will
show from the bottom of the device screen. So the "in" animation
will look like:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%"
android:toXDelta="100%"
android:fromYDelta="0%"
android:toYDelta="100%"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:anim/linear_interpolator"
>
</translate>
</set>
As you can see it's the "translate" animation. The animated view
will be always 100% screen width and will grow from 0% to 100%
it's height.
Vice versa the "out" we'll define as following:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%"
android:toXDelta="100%"
android:fromYDelta="100%"
android:toYDelta="0%"
android:duration="@android:integer/config_shortAnimTime"
android:interpolator="@android:anim/linear_interpolator"
>
</translate>
</set>
It will shrink from 100% to 0% height.
And to apply the animation to a view:
<style name="Animations.MenuAnimation">
<item name="android:windowEnterAnimation">
@anim/menu_animation_in</item>
<item name="android:windowExitAnimation">
@anim/menu_animation_out</item>
</style>
The menu items will be the same as in Dialog demo, but with gray colors.
And at last to complete XML stuff there are the menu item layout and the menu layout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#224c4c4c"
android:gravity="center"
android:orientation="vertical"
android:padding="4dip" >
<Button
android:id="@+id/custom_menu_item_caption"
style="@style/button_black"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Add from URL" >
</Button>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#00000000"
android:orientation="vertical"
android:padding="0dip" >
<View
android:layout_width="fill_parent"
android:layout_height="0.5dip"
android:background="#ff4f4f4f" />
<ImageView
android:layout_width="fill_parent"
android:layout_height="20dip"
android:gravity="center"
android:scaleType="fitXY"
android:src="@drawable/menu_header" />
<View
android:layout_width="fill_parent"
android:layout_height="0.5dip"
android:background="#ff4f4f4f" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#aa000000"
android:orientation="vertical"
android:padding="0dip" >
<TableLayout
android:id="@+id/custom_menu_table"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:stretchColumns="*" >
</TableLayout>
</LinearLayout>
</LinearLayout>
Menu Header:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="270"
android:type="linear"
android:endColor="#444c4c4c"
android:startColor="#44ffffff"
/>
</shape>
The code
The code is quite clear. On base of the PopupWindow we form our menu.
The layout for the popup window is the table layout. And each item
of the menu we add to the layout. And to complete the menu we add
a listener to each item.
/**
* Opened menu
*/
private static volatile CustomMenu mMenu = null;
private ArrayList<CustomMenuItem> mMenuItems;
private OnMenuItemSelectedListener mListener = null;
private Activity mContext = null;
private static volatile PopupWindow mPopupWindow = null;
private static boolean mIsShowing = false;
/**
* Menu item selected listener
*/
public interface OnMenuItemSelectedListener {
public void MenuItemSelectedEvent(Integer selection);
}
/**
* Is the menu opened
*
* @return boolean isShowing
*/
public static boolean isShowing() {
return mIsShowing;
}
/**
* Constructor
*
* @param activity
* Activity where the menu will be shown
* @param OnMenuItemSelectedListener
* listener Listener
* @param LayoutInflater
* items Items list
* @return void
*/
public CustomMenu(Activity activity,
OnMenuItemSelectedListener listener,
HashMap<Integer, String> items) {
mListener = listener;
mMenuItems = new ArrayList<CustomMenuItem>();
mContext = activity;
// Add items to the menu
for (Integer id : items.keySet()) {
String name = items.get(id);
CustomMenuItem cmi = new CustomMenuItem();
cmi.setCaption(name);
cmi.setId(id);
mMenuItems.add(cmi);
}
}
public void show(View v) {
// The menu is shown
mIsShowing = true;
int itemCount = mMenuItems.size();
if (itemCount < 1)
return; // Nothing to show
if (mPopupWindow != null)
return; // The menu is opened
// Display settings
Display display = ((WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
// The view to show
View mView = ((Activity) mContext).getLayoutInflater().inflate(
R.layout.custom_menu, null);
// Create popup window to show
mPopupWindow = new PopupWindow(mView, LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT, false);
mPopupWindow.setAnimationStyle(R.style.Animations_MenuAnimation);
mPopupWindow.setWidth(display.getWidth());
mPopupWindow.showAtLocation(v, Gravity.BOTTOM, 0, 0);
// Add menu items
TableLayout table = (TableLayout) mView
.findViewById(R.id.custom_menu_table);
table.removeAllViews();
for (int i = 0; i < itemCount; i++) {
TableRow row = null;
Button btn = null;
// create headers
row = new TableRow(mContext);
row.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
final CustomMenuItem cmi = mMenuItems.get(i);
View itemLayout = ((Activity) mContext).getLayoutInflater()
.inflate(R.layout.custom_menu_item, null);
btn = (Button) itemLayout
.findViewById(R.id.custom_menu_item_caption);
btn.setText(cmi.getCaption());
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.MenuItemSelectedEvent(cmi.getId());
hide();
}
});
row.addView(itemLayout);
table.addView(row);
}
}
And we have: