Reputation: 702
How to customize popupmenu to change color/font/style for each option in every popupmenu?
Upvotes: 1
Views: 3684
Reputation: 541
I had the same problem to customize PopupMenu font and text size. Finally i used reflection. It can be used for any customization of popup menu items. The resource layout of menu item in android support is defined in android.support.v7.internal.view.menu.MenuPopupHelper and it 's field name is "ITEM_LAYOUT" that declared as static final; It 's value equals to "R.layout.abc_popup_menu_item_layout" I find the layout file in Grepcode and copy it to my project layout directory. I named it popup_menu_item_layout.xml. My popup menu item layout comes here
<?xml version="1.0" encoding="utf-8"?>
<mypackage.PopupMenuItemView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?attr/dropdownListPreferredItemHeight"
android:minWidth="196dip"
android:paddingRight="16dip">
<!-- Icon will be inserted here. -->
<!-- The title and summary have some gap between them, and this 'group' should be centered vertically. -->
<RelativeLayout
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dip"
android:duplicateParentState="true">
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:textAppearance="?attr/textAppearanceLargePopupMenu"
android:singleLine="true"
android:duplicateParentState="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<TextView
android:id="@+id/shortcut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_alignParentLeft="true"
android:textAppearance="?attr/textAppearanceSmallPopupMenu"
android:singleLine="true"
android:duplicateParentState="true"/>
</RelativeLayout>
<!-- Checkbox, and/or radio button will be inserted here. -->
Then create custom class PopupMenuItemView:
public class PopupMenuItemView extends android.support.v7.internal.view.menu.ListMenuItemView {
public PopupMenuItemView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PopupMenuItemView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
applyTypefaceToAll(this, your_typeface);
TypefaceUtils.applyTextSizeToAll(this, your_textsize);
}
public static void applyTypefaceToAll(View view, Typeface typeface) {
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int childIndex = 0; childIndex < viewGroup.getChildCount(); childIndex++)
applyTypefaceToAll(viewGroup.getChildAt(childIndex), typeface);
} else if (view instanceof TextView) {
TextView textView = (TextView) view;
textView.setTypeface(typeface);
textView.setPaintFlags(textView.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
}
}
public static void applyTextSizeToAll(View view, float size) {
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int childIndex = 0; childIndex < viewGroup.getChildCount(); childIndex++)
applyTextSizeToAll(viewGroup.getChildAt(childIndex), size);
} else if (view instanceof TextView) {
TextView textView = (TextView) view;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
textView.setPaintFlags(textView.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
}
}
}
Finally replace layout resource id for menu items by reflection; some where like in your main activity onCreate method or in your app onCreate method:
try {
setFinalStatic(MenuPopupHelper.class.getDeclaredField("ITEM_LAYOUT"),
R.layout.popup_menu_item_layout);
} catch (Exception e) {
e.printStackTrace();
}
public static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
try {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
}catch (Exception e) {
e.printStackTrace();
}
field.set(null, newValue);
}
Upvotes: 1
Reputation: 574
You can treat a popup as a view, or as a saperate activity even (with transparent backgound, look at the themes options on android)
then , when you want to show the popup, you can start it from any activity in the app, it will always have the same styling for bg and buttons, you will only feed it the actual data.
For exmaple:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:background="@drawable/bg_popup"
android:layout_gravity="center"
android:alpha="0.8"
android:visibility="visible"
android:id="@+id/generic_popup2_container"
android:layout_height="300dp">
<TextView
android:id="@+id/generic_popup2_tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:layout_alignParentTop="true"
android:text="header"
android:gravity="center"
android:textSize="28sp" />
<TextView
android:id="@+id/generic_popup2_tv_inner_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:text="content"
android:textSize="16sp"
android:gravity="center"
android:layout_marginTop="20dp"
android:layout_below="@id/generic_popup2_tv_title"
android:layout_centerHorizontal="true" />
<LinearLayout
android:id="@+id/generic_popup_2_buttons_layout"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:orientation="horizontal">
<Button
android:id="@+id/layout_2_generic_popup_btn_action1"
android:layout_width="115dp"
android:layout_height="35dp"
android:textColor="@color/white"
android:layout_marginBottom="10dp"
android:textSize="12sp"
android:layout_marginRight="10dp"
android:background="@drawable/popup_btn_blue" />
<Button
android:id="@+id/layout_2_generic_popup_btn_action2"
android:layout_width="115dp"
android:layout_height="35dp"
android:textColor="@color/white"
android:textSize="12sp"
android:background="@drawable/popup_btn_blue" />
</LinearLayout>
Upvotes: 0