Ale*_*lex 50 android popupmenu
当然,我们在这里处理SDK 11及更高版本.
我打算做类似的事情:

旁边的每个项目在PopupMenu,我想将一个图标.
我创建了一个XML文件并将其放入/menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_one"
android:title="Sync"
android:icon="@android:drawable/ic_popup_sync"
/>
<item
android:id="@+id/action_two"
android:title="About"
android:icon="@android:drawable/ic_dialog_info"
/>
</menu>
Run Code Online (Sandbox Code Playgroud)
正如您所注意到的,在xml文件中我定义了我想要的图标,但是,当弹出菜单显示时,它显示的是没有图标的图标.我应该怎么做才能出现这两个图标?
Ste*_*son 86
这种方式适用于您使用AppCompat v7.它有点hacky但比使用反射明显更好,让你仍然使用核心Android PopupMenu:
PopupMenu menu = new PopupMenu(getContext(), overflowImageView);
menu.inflate(R.menu.popup);
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { ... });
MenuPopupHelper menuHelper = new MenuPopupHelper(getContext(), (MenuBuilder) menu.getMenu(), overflowImageView);
menuHelper.setForceShowIcon(true);
menuHelper.show();
Run Code Online (Sandbox Code Playgroud)
RES /菜单/ popup.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_share_location"
android:title="@string/share_location"
android:icon="@drawable/ic_share_black_24dp"/>
</menu>
Run Code Online (Sandbox Code Playgroud)
这会导致弹出菜单使用菜单资源文件中定义的图标:
Emi*_*Adz 38
否则我会实现它:
创建PopUpWindow布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llSortChangePopup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/sort_popup_background"
android:orientation="vertical" >
<TextView
android:id="@+id/tvDistance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/distance"
android:layout_weight="1.0"
android:layout_marginLeft="20dp"
android:paddingTop="5dp"
android:gravity="center_vertical"
android:textColor="@color/my_darker_gray" />
<ImageView
android:layout_marginLeft="11dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sort_popup_devider"
android:contentDescription="@drawable/sort_popup_devider"/>
<TextView
android:id="@+id/tvPriority"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/priority"
android:layout_weight="1.0"
android:layout_marginLeft="20dp"
android:gravity="center_vertical"
android:clickable="true"
android:onClick="popupSortOnClick"
android:textColor="@color/my_black" />
<ImageView
android:layout_marginLeft="11dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sort_popup_devider"
android:contentDescription="@drawable/sort_popup_devider"/>
<TextView
android:id="@+id/tvTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/time"
android:layout_weight="1.0"
android:layout_marginLeft="20dp"
android:gravity="center_vertical"
android:clickable="true"
android:onClick="popupSortOnClick"
android:textColor="@color/my_black" />
<ImageView
android:layout_marginLeft="11dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sort_popup_devider"
android:contentDescription="@drawable/sort_popup_devider"/>
<TextView
android:id="@+id/tvStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/status"
android:layout_weight="1.0"
android:layout_marginLeft="20dp"
android:gravity="center_vertical"
android:textColor="@color/my_black"
android:clickable="true"
android:onClick="popupSortOnClick"
android:paddingBottom="10dp"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
然后PopUpWindow在你的Activity:创建:
// The method that displays the popup.
private void showStatusPopup(final Activity context, Point p) {
// Inflate the popup_layout.xml
LinearLayout viewGroup = (LinearLayout) context.findViewById(R.id.llStatusChangePopup);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.status_popup_layout, null);
// Creating the PopupWindow
changeStatusPopUp = new PopupWindow(context);
changeStatusPopUp.setContentView(layout);
changeStatusPopUp.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
changeStatusPopUp.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
changeStatusPopUp.setFocusable(true);
// Some offset to align the popup a bit to the left, and a bit down, relative to button's position.
int OFFSET_X = -20;
int OFFSET_Y = 50;
//Clear the default translucent background
changeStatusPopUp.setBackgroundDrawable(new BitmapDrawable());
// Displaying the popup at the specified location, + offsets.
changeStatusPopUp.showAtLocation(layout, Gravity.NO_GRAVITY, p.x + OFFSET_X, p.y + OFFSET_Y);
}
Run Code Online (Sandbox Code Playgroud)
最后弹出onClick一个按钮或其他任何东西:
imTaskStatusButton.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
int[] location = new int[2];
currentRowId = position;
currentRow = v;
// Get the x, y location and store it in the location[] array
// location[0] = x, location[1] = y.
v.getLocationOnScreen(location);
//Initialize the Point with x, and y positions
point = new Point();
point.x = location[0];
point.y = location[1];
showStatusPopup(TasksListActivity.this, point);
}
});
Run Code Online (Sandbox Code Playgroud)
很好的例子PopUpWindow:
http://androidresearch.wordpress.com/2012/05/06/how-to-create-popups-in-android/
Bao*_* Le 24
Android弹出菜单有一个隐藏方法来显示菜单图标.使用Java反射将其启用如下面的代码段.
public static void setForceShowIcon(PopupMenu popupMenu) {
try {
Field[] fields = popupMenu.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popupMenu);
Class<?> classPopupHelper = Class.forName(menuPopupHelper
.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod(
"setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
Aja*_*van 18
弹出菜单与图标使用MenuBuilder和MenuPopupHelper
MenuBuilder menuBuilder =new MenuBuilder(this);
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.menu, menuBuilder);
MenuPopupHelper optionsMenu = new MenuPopupHelper(this, menuBuilder, view);
optionsMenu.setForceShowIcon(true);
// Set Item Click Listener
menuBuilder.setCallback(new MenuBuilder.Callback() {
@Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
switch (item.getItemId()) {
case R.id.opt1: // Handle option1 Click
return true;
case R.id.opt2: // Handle option2 Click
return true;
default:
return false;
}
}
@Override
public void onMenuModeChange(MenuBuilder menu) {}
});
// Display the menu
optionsMenu.show();
Run Code Online (Sandbox Code Playgroud)
menu.xml文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/opt1"
android:icon="@mipmap/ic_launcher"
android:title="option 1" />
<item
android:id="@+id/opt2"
android:icon="@mipmap/ic_launcher"
android:title="option 2" />
</menu>
Run Code Online (Sandbox Code Playgroud)
Car*_*men 16
将MenuPopupHelper在程序兼容性类有@hide注释.如果这是一个问题,或者由于某种原因你不能使用AppCompat,那么Spannable在MenuItem标题中使用包含图标和标题文本的另一个解决方案.
主要步骤是:
PopupMenu使用menuxml文件充气SpannableStringBuilder包含图标和标题SpannableStringBuilder优点:没有反思.不使用任何隐藏的api.可以使用框架PopupMenu.
缺点:更多代码.如果你有一个没有图标的子菜单,它会在小屏幕上有不需要的左边填充.
细节:
首先,为dimens.xml文件中的图标定义大小:
<dimen name="menu_item_icon_size">24dp</dimen>
Run Code Online (Sandbox Code Playgroud)
然后,一些方法将xml中定义的图标移动到标题中:
/**
* Moves icons from the PopupMenu's MenuItems' icon fields into the menu title as a Spannable with the icon and title text.
*/
public static void insertMenuItemIcons(Context context, PopupMenu popupMenu) {
Menu menu = popupMenu.getMenu();
if (hasIcon(menu)) {
for (int i = 0; i < menu.size(); i++) {
insertMenuItemIcon(context, menu.getItem(i));
}
}
}
/**
* @return true if the menu has at least one MenuItem with an icon.
*/
private static boolean hasIcon(Menu menu) {
for (int i = 0; i < menu.size(); i++) {
if (menu.getItem(i).getIcon() != null) return true;
}
return false;
}
/**
* Converts the given MenuItem's title into a Spannable containing both its icon and title.
*/
private static void insertMenuItemIcon(Context context, MenuItem menuItem) {
Drawable icon = menuItem.getIcon();
// If there's no icon, we insert a transparent one to keep the title aligned with the items
// which do have icons.
if (icon == null) icon = new ColorDrawable(Color.TRANSPARENT);
int iconSize = context.getResources().getDimensionPixelSize(R.dimen.menu_item_icon_size);
icon.setBounds(0, 0, iconSize, iconSize);
ImageSpan imageSpan = new ImageSpan(icon);
// Add a space placeholder for the icon, before the title.
SpannableStringBuilder ssb = new SpannableStringBuilder(" " + menuItem.getTitle());
// Replace the space placeholder with the icon.
ssb.setSpan(imageSpan, 1, 2, 0);
menuItem.setTitle(ssb);
// Set the icon to null just in case, on some weird devices, they've customized Android to display
// the icon in the menu... we don't want two icons to appear.
menuItem.setIcon(null);
}
Run Code Online (Sandbox Code Playgroud)
最后,创建PopupMenu并在显示之前使用上述方法:
PopupMenu popupMenu = new PopupMenu(view.getContext(), view);
popupMenu.inflate(R.menu.popup_menu);
insertMenuItemIcons(textView.getContext(), popupMenu);
popupMenu.show();
Run Code Online (Sandbox Code Playgroud)
Moh*_*yed 10
您可以通过使用Reflection来实现此功能,如果您不喜欢此出色的java高级功能,则可以修改在JVM中运行的应用程序的运行时行为,您可以查看对象并在运行时执行其方法在我们的例子中,我们需要在运行时修改popupMenu的行为,而不是扩展核心类并对其进行修改;)希望有所帮助
private void showPopupMenu(View view) {
// inflate menu
PopupMenu popup = new PopupMenu(mcontext, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.main, popup.getMenu());
Object menuHelper;
Class[] argTypes;
try {
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popup);
argTypes = new Class[]{boolean.class};
menuHelper.getClass().getDeclaredMethod("setForceShowIcon", argTypes).invoke(menuHelper, true);
} catch (Exception e) {
}
popup.show();
}
Run Code Online (Sandbox Code Playgroud)
阅读PopupMenu源代码.我们可以通过以下代码显示图标:
Field field = popupMenu.getClass().getDeclaredField("mPopup");
field.setAccessible(true);
MenuPopupHelper menuPopupHelper = (MenuPopupHelper) field.get(popupMenu);
menuPopupHelper.setForceShowIcon(true);
Run Code Online (Sandbox Code Playgroud)
但MenuPopupHelper.java是在android内部包中.所以我们应该使用Reflection:
PopupMenu popupMenu = new PopupMenu(this, anchor);
popupMenu.getMenuInflater().inflate(R.menu.process, popupMenu.getMenu());
try {
Field field = popupMenu.getClass().getDeclaredField("mPopup");
field.setAccessible(true);
Object menuPopupHelper = field.get(popupMenu);
Class<?> cls = Class.forName("com.android.internal.view.menu.MenuPopupHelper");
Method method = cls.getDeclaredMethod("setForceShowIcon", new Class[]{boolean.class});
method.setAccessible(true);
method.invoke(menuPopupHelper, new Object[]{true});
} catch (Exception e) {
e.printStackTrace();
}
popupMenu.show();
Run Code Online (Sandbox Code Playgroud)
/ res/menu目录中的list_item_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/locale"
android:title="Localizar"
android:icon="@mipmap/ic_en_farmacia_ico"
app:showAsAction="always">
</item>
<item android:id="@+id/delete"
android:title="Eliminar"
android:icon="@mipmap/ic_eliminar_ico"
app:showAsAction="always">
</item>
</menu>
Run Code Online (Sandbox Code Playgroud)
在我的活动中
private void showPopupOption(View v){
PopupMenu popup = new PopupMenu(getContext(), v);
popup.getMenuInflater().inflate(R.menu.list_item_menu, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem menu_item) {
switch (menu_item.getItemId()) {
case R.id.locale:
break;
case R.id.delete:
break;
}
return true;
}
});
MenuPopupHelper menuHelper = new MenuPopupHelper(getContext(), (MenuBuilder) popup.getMenu(), v);
menuHelper.setForceShowIcon(true);
menuHelper.setGravity(Gravity.END);
menuHelper.show();
}
Run Code Online (Sandbox Code Playgroud)
结果

我用尽可能简单的方式解决了我的问题,从未期待过如此简单:
在main.xml中:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_more"
android:icon="@android:drawable/ic_menu_more"
android:orderInCategory="1"
android:showAsAction="always"
android:title="More">
<menu>
<item
android:id="@+id/action_one"
android:icon="@android:drawable/ic_popup_sync"
android:title="Sync"/>
<item
android:id="@+id/action_two"
android:icon="@android:drawable/ic_dialog_info"
android:title="About"/>
</menu>
</item>
Run Code Online (Sandbox Code Playgroud)
在MainActivity.java中
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
Run Code Online (Sandbox Code Playgroud)
这是一个使用子菜单的技巧
| 归档时间: |
|
| 查看次数: |
69585 次 |
| 最近记录: |