如何在Android溢出按钮上更改弹出菜单的位置?

15

我想要实现与 Gmail 应用程序中弹出菜单相同的一些功能,可以将其锚定到右上方的溢出按钮。为此,我使用了与 Google Android 弹出菜单 教程相同的代码,但是我的菜单显示在操作栏顶部而非其下方。如果您留意 Gmail 溢出菜单上的弹出菜单,您会发现该菜单位于操作栏边缘。

这是我用于弹出菜单的 XML:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/item1"
        android:title="lablab"/>
    <item
        android:id="@+id/item2"
        android:title="lablab"/>

</menu>

以下是我的活动内容:

public void showFontSetting(View view) {
    PopupMenu popup = new PopupMenu(this, view);
    MenuInflater inflater = popup.getMenuInflater();
    inflater.inflate(R.menu.menu, popup.getMenu());
    popup.show();

    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(MenuItem item) {
        // TODO Auto-generated method stub

            switch (item.getItemId()) {
                case R.id.item1:
                    Toast.makeText(Index.this,
                        "You Clicked : " + item.getTitle(),
                    Toast.LENGTH_SHORT).show();
                    break;
                case R.id.item2:
                    break;
            }
            return true;
        }
    });
}

你有检查过任何答案吗? - Sanket Kachhela
是的,我正在我的代码中尝试这个答案。谢谢。 - user3266062
5个回答

58

仅限重叠,使用此方法:

PopupMenu popupMenu = new PopupMenu(getContext(), this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0);

要获得带有明亮背景和详细控制偏移量的PopupMenu,请使用以下方法:

styles.xml

<style name="PopupMenuOverlapAnchor" parent="@style/Theme.AppCompat.Light">
   <item name="android:overlapAnchor">true</item>
   <item name="android:dropDownVerticalOffset">0dp</item>
   <item name="android:dropDownHorizontalOffset">0dp</item>
</style>

代码:

ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(getContext(), R.style.PopupMenuOverlapAnchor);
PopupMenu popupMenu = new PopupMenu(contextThemeWrapper, this);

你知道为什么popupMenu.getDragToOpenListener()对我来说是一个android.widget.PopupMenu吗? - danijar
我认为你分析了调试输出并检测到类似这样的内容:mDragListener = {android.support.v7.widget.PopupMenu$1@7128}。详细查看输出:@之前的最后两个符号是1和$,这意味着该对象是一个内部匿名类实例。PopupMenu的真实实例看起来像这样:this = {android.support.v7.widget.PopupMenu@7123},没有$1。PopupMenu的源代码也揭示了这一事实:mDragListener = new ListPopupWindow.ForwardingListener(mAnchor) {...}; - user1185087
这个不起作用。也许过去它能工作,但现在不行了。 类ListPopupWindow没有定义/声明ForwardingListener。 ForwardingListener位于android.support.v7.widget中,其listener.getPopup()没有setVerticalOffset()方法。 - M.Paunov
android:dropDownVerticalOffsetandroid:dropDownHorizontalOffset 对我不起作用,但明亮的背景有效。 - SeaJelly
@user1185087:请分享来自R.attr.actionOverflowMenuStyle的actionOverflowMenuStyle。 - Jayesh
如果将Gravity设置为Gravity.END,则它确实复制了溢出弹出菜单。 - Rajarshi

13

运用重力在我的情况下有所帮助

PopupMenu popup = new PopupMenu(this, v, Gravity.RIGHT);

1
抱歉,我忘了提到,这已经添加在Api 19中。https://developer.android.com/reference/android/widget/PopupMenu.html#PopupMenu(android.content.Context,%20android.view.View,%20int) - Neeraj
2
但它是适用于所有版本的支持库。 - Frank

6
将以下代码片段添加到您的活动中:
PopupWindow popupwindow_obj; // create object

popupwindow_obj=popupDisplay();  // initialize in onCreate()

popupwindow_obj.showAsDropDown(clickbtn,-40, 18); // where u want show on view click event

public PopupWindow popupDisplay() { // disply designing your popoup window
    final PopupWindow popupWindow = new PopupWindow(this); // inflet your layout or diynamic add view

    View view; 

    LayoutInflater inflater = (LayoutInflater)   getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    view = inflater.inflate(R.layout.mylayout, null);

    Button item = (LinearLayout) view.findViewById(R.id.button1);

    popupWindow.setFocusable(true);
    popupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
    popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
    popupWindow.setContentView(view);

    return popupWindow;
}

res/layout目录中创建一个名为mylayout.xml的XML文件。
<LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Window test" />
</LinearLayout>

我是Android的新手,我已经搜索了但是找不到任何关于如何填充我的布局的解决方案。 - user3266062
View视图; LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.mylayout, null);RelativeLayout item = (RelativeLayout) view.findViewById(R.id.item); - SuN
我在inflate中应该放什么代替mylayout?我得到了很多错误。 - user3266062
您需要编写您自己的layout.xml文件。 - SuN
你看到我添加代码的编辑了吗?关于它,我添加了你的代码并将view = inflater.inflate(R.menu.menu, null); RelativeLayout item = (RelativeLayout) view.findViewById(R.id.item1);放入我的代码中的showFontSetting方法中。但是我收到了很多异常。 - user3266062

3

我尝试了找到的每种方法后,我认为放置一个锚定视图可能仍然是一种更简单更容易的方法,特别是当您正在使用更灵活的布局,例如ConstraintLayout时。

只需将一个不可见视图放在您想要弹出菜单锚定的位置:

<View
    android:id="@+id/anchor_menu"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginTop="10dp"
    app:layout_constraintStart_toStartOf="@+id/button_menu"
    app:layout_constraintTop_toBottomOf="@+id/button_menu"
    />

然后将其用作锚定视图:
    mPopupMenu = new PopupMenu(getActivity(), mPopupMenuAnchor);

完成了,真是太棒了。


0
也许你可以考虑使用 PopupWindow
popupwindow.showAsDropDown(view,x,y);

这里的xy 是弹出窗口相对于您的视图的位置


2
这个问题是关于PopupMenu而不是PopupWindow的。 - mhenry
1
@mhenry 负面评价是可以接受的,但被接受的答案也建议使用弹出窗口。 - Sanket Kachhela

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