实现带边距的弹出菜单

28

我正在使用默认的弹出菜单,并期望拥有相同的行为。一切都运作得很好。我的关注点在于弹出菜单的渲染方式。我的弹出菜单粘附在屏幕的右侧。

我希望它的行为与Android上的Youtube应用程序相同。enter image description here

我主要无法为我的弹出菜单提供正确的右边距。请帮忙。 我尝试为 PopUp 菜单提供重力,但是它仍粘附在屏幕的右侧。

PopupMenu popupMenu = new PopupMenu(mContext, anchor, Gravity.LEFT);
popupMenu.getMenuInflater().inflate(R.menu.menu_edit_accessory, popupMenu.getMenu());

基本上,它不能粘附到屏幕的右边,但它会粘住你在构造函数中设置为锚点的锚定视图。我不知道Youtube如何呈现弹出菜单,但您可以尝试使用不同的锚定位置,例如设置一个仅用于将您的PopupMenu附加到其上的无形视图。 - Benjamin Scharbau
我尝试了相同的方法,但它仍然停留在右边。我已经尝试创建虚假的锚视图,但行为仍然相同。 - Anchit Mittal
哦,你说得对,我已经自己确认过了。我不确定YouTube是否是这样做的,但我建议尝试使用PopupWindow而不是PopupMenuPopupWindow更好地锚定在视图上,但您必须自己进行布局。 - Benjamin Scharbau
5个回答

56

您可以通过使用以下属性来更改PopupMenu的位置: gravity, dropDownHorizontalOffsetdropDownVerticalOffset

首先将 gravity 设置为 Gravity.END

popup.setGravity(Gravity.END);

然后通过创建样式来更改您的下拉偏移量

<style name="MyPopupMenu" parent="@style/Widget.AppCompat.PopupMenu">
    <item name="android:dropDownHorizontalOffset">-4dp</item>
    <item name="android:dropDownVerticalOffset">4dp</item>
</style>
如果想要重叠锚点视图,请使用以下代码:

parent="@style/Widget.AppCompat.PopupMenu.Overflow"

最后将 MyPopupMenu 应用到您的主题上

<item name="popupMenuStyle">@style/MyPopupMenu</item>

3
谢谢,将重力设置为Gravity.END对我有用。默认的NO_GRAVITY值似乎是忽略与锚点的对齐。 - somedev
  1. 在我的主题中,我不得不添加 <item name="android:popupMenuStyle">...,如果没有 android: 命名空间,它就不会应用菜单样式。
  2. 它应用了父样式,但偏移校正没有任何效果。
- quezak
4
更新上面的评论:在我纠正了一个愚蠢的错误后,偏移量终于发挥作用了 :)如果您不想全局启用弹出样式,您可以使用指定的样式进行实例化:new PopupMenu(context, anchor, Gravity.END, 0, R.style.PopupMenuStyle) - quezak
@quezak 像这样设置样式 new PopupMenu(context, anchor, Gravity.END, 0, R.style.PopupMenuStyle) 是不起作用的。 - Syed Arsalan Kazmi
1
@syed-arsalan-kazmi 我在5年前评论过这个,我相信现在已经过时了 :) 自那以后我就没有从事Android方面的工作了,所以无法再提供帮助。 - quezak

8
这可能有点晚了,但我希望能帮到某个人。
我也试着使用弹出菜单 PopupMenu,但直到我了解了 ListPopupWindow 才找到正确的方法。 它是一种更好的选择,在我看来更加灵活,而且你可以实现你所询问的边距间隔。
这是代码:
public class MainActivity extends AppCompatActivity
{
    private ImageButton mMoreOptionsButton;
    private ArrayAdapter<String> mPopupAdapter;
    private ArrayList<String> mOptionsArray = 
            new ArrayList<>(Arrays.asList("Option1", "Option2", "Option3"));
    private ListPopupWindow mPopupWindow;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMoreOptionsButton = (ImageButton) view.findViewById(R.id.more_options_button);
        setupPopupWindow();
    }

    private void setupPopupWindow()
    {
        mPopupAdapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_spinner_dropdown_item, mOptionsArray);
        mPopupWindow = new ListPopupWindow(MainActivity.this);
        mPopupWindow.setAdapter(mPopupAdapter);
        mPopupWindow.setAnchorView(mMoreOptionsButton);
        mPopupWindow.setWidth(500);
        mPopupWindow.setHorizontalOffset(-380); //<--this provides the margin you need
        //if you need a custom background color for the popup window, use this line:
        mPopupWindow.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(MainActivity.this, R.color.gray)));

        mPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                //do something with item by referring to it using the "position" parameter
            }
        });

        mMoreOptionsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)
            {
                mPopupWindow.show();
            }
        });
    }
}

重点是调用mPopupWindow.setHorizontalOffset()方法。请注意,这个方法比较棘手。根据你在mPopupWindow.setWidth()中设置的值,你需要相应地调整setHorizontalOffset()中的值。碰巧对于我的应用程序,-380是我需要的完美间距。因此,您可能需要稍微调整这个值。
我认为如果您想要弹出窗口顶部有一些间距,同样适用于使用setHeight()setVerticalOffset()
希望这可以帮到您:]

3
  PopupMenu popup = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
            popup = new PopupMenu(context, anchorView, Gravity.END, 0, R.style.MyPopupMenu);
        }else{
            popup = new PopupMenu(context, anchorView);
        }

样式

<style name="MyPopupMenu" parent="@style/Widget.AppCompat.PopupMenu">
    <item name="android:dropDownHorizontalOffset">-4dp</item>
    <item name="android:dropDownVerticalOffset">4dp</item>
</style>

1

您可以在特定位置设置弹出窗口

popupWindow .showAtLocation(popupView, Gravity.CENTER, 0, 0);

public void showAtLocation(View parent, int gravity, int x, int y) {
        showAtLocation(parent.getWindowToken(), gravity, x, y);
    }

如果您希望将其显示为下拉菜单,则可以尝试。
public void showAsDropDown(View anchor, int xoff, int yoff) {
        showAsDropDown(anchor, xoff, yoff, DEFAULT_ANCHORED_GRAVITY);
    }

请查看PopupWindow文档http://developer.android.com/intl/es/reference/android/widget/PopupWindow.html


-1
只需像这样声明您的弹出菜单 var popup = PopupMenu(this.requireContext(), isw_settings_icon, Gravity.END, 0, R.style.yourmenustyle)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接