【问题标题】:How to customize popup menu for each option in Android?如何为 Android 中的每个选项自定义弹出菜单?
【发布时间】:2013-08-27 10:30:19
【问题描述】:

如何自定义弹出菜单以更改每个弹出菜单中每个选项的颜色/字体/样式?

【问题讨论】:

    标签: android customization popupmenu


    【解决方案1】:

    我在自定义 PopupMenu 字体和文本大小时遇到​​了同样的问题。最后我使用了反射。它可用于任何弹出菜单项的自定义。 android支持中菜单项的资源布局在android.support.v7.internal.view.menu.MenuPopupHelper中定义,其字段名称为“ITEM_LAYOUT”,声明为static final;它的值等于“R.layout.abc_popup_menu_item_layout” 我在 Grepcode 中找到布局文件并将其复制到我的项目布局目录中。我将其命名为 popup_menu_item_layout.xml。我的弹出菜单项布局来了

    <?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. -->
    

    然后创建自定义类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);
        }
    }
    }
    

    最后通过反射替换菜单项的布局资源id;一些在您的主要活动 onCreate 方法或您的应用程序 onCreate 方法中:

        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);
    }
    

    【讨论】:

      【解决方案2】:

      您可以将弹出窗口视为视图,甚至可以视为单独的活动(具有透明背景,请查看 android 上的主题选项)

      然后,当您想要显示弹出窗口时,您可以从应用程序中的任何活动启动它,它将始终具有相同的背景和按钮样式,您只会向其提供实际数据。

      例如:

      <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>
      

      【讨论】:

      • 实际上我无法预测 textview 的计数,不知何故 3、4、5 和 >5,所以我可以在我的情况下使用这种方式吗?
      • 这就是通用性可能是一个陷阱,就图形而言,以及您如何通过代码实际构建它以保持通用性并能够维护它。我建议为每个弹出文件构建不同的布局,只是为了维护。
      【解决方案3】:

      创建一个弹出窗口并根据需要对其进行自定义。
      以下是一些有用的链接:
      how-to-create-popup-window-in-android
      你也可以看看quickaction dialog

      【讨论】:

        猜你喜欢
        • 2011-11-07
        • 2023-03-24
        • 1970-01-01
        • 2014-02-15
        • 1970-01-01
        • 1970-01-01
        • 2015-07-15
        • 1970-01-01
        相关资源
        最近更新 更多