Agoeng Liu
Agoeng Liu

Reputation: 702

How to customize popup menu for each option in Android?

How to customize popupmenu to change color/font/style for each option in every popupmenu?

Upvotes: 1

Views: 3684

Answers (2)

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

Israel Tabadi
Israel Tabadi

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

Related Questions