Android自定义下拉/弹出菜单

Posted

技术标签:

【中文标题】Android自定义下拉/弹出菜单【英文标题】:Android custom dropdown/popup menu 【发布时间】:2014-02-15 05:43:01 【问题描述】:

如何将自定义下拉/弹出菜单锚定到按钮?

我需要它像弹出菜单(锚定到视图)一样工作,并在我单击菜单中的项目时执行某些操作。

如何通过代码将项目添加到菜单中,保持菜单的高度并在超过 5 个项目时使其可滚动。我不需要添加任何图像,只需添加文本。

【问题讨论】:

【参考方案1】:

更新:要使用 Kotlin 在 android 中创建弹出菜单,请参阅我的回答 here。

使用 Java 在 android 中创建弹出菜单:

res/layout目录下创建一个布局文件activity_main.xml,只包含一个按钮。

文件名:activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_  
    android:layout_  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    tools:context=".MainActivity" >  

    <Button  
        android:id="@+id/button1"  
        android:layout_  
        android:layout_  
        android:layout_alignParentLeft="true"  
        android:layout_alignParentTop="true"  
        android:layout_marginLeft="62dp"  
        android:layout_marginTop="50dp"  
        android:text="Show Popup" />  

</RelativeLayout>  

res/menu目录下创建文件popup_menu.xml

它包含三个项目,如下所示。

文件名:poupup_menu.xml

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

    <item  
        android:id="@+id/one"  
        android:title="One"/>  

    <item  
        android:id="@+id/two"  
        android:title="Two"/>  

    <item  
        android:id="@+id/three"  
        android:title="Three"/>  

</menu>  

MainActivity 类,在单击按钮时显示弹出菜单。

文件名:MainActivity.java

public class MainActivity extends Activity   
    private Button button1;  

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() 
            @Override
            public void onClick(View v) 
                //Creating the instance of PopupMenu
                PopupMenu popup = new PopupMenu(MainActivity.this, button1);
                //Inflating the Popup using xml file
                popup.getMenuInflater()
                    .inflate(R.menu.popup_menu, popup.getMenu());

                //registering popup with OnMenuItemClickListener
                popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() 
                    public boolean onMenuItemClick(MenuItem item) 
                        Toast.makeText(
                            MainActivity.this,
                            "You Clicked : " + item.getTitle(),
                            Toast.LENGTH_SHORT
                        ).show();
                        return true;
                    
                );

                popup.show(); //showing popup menu
            
        ); //closing the setOnClickListener method
    

以编程方式添加:

PopupMenu menu = new PopupMenu(this, view);

menu.getMenu().add("One");
menu.getMenu().add("Two");
menu.getMenu().add("Three");

menu.show();

按照this 链接以编程方式创建菜单。

【讨论】:

嘿,谢谢!如果我想在菜单中添加更多项目怎么办?我可以通过代码做到这一点吗? 好的,我知道了如何添加项目:menu.getMenu().add("item");但是如何自定义菜单呢? 我指的是宽度、背景等 现在它也可以通过使用 v7 兼容支持库在较低版本中使用,即低于 3.0(honeycomb).. 这就是我添加的方式,但我看不到带文字的图像【参考方案2】:

我知道这是一个老问题,但我找到了另一个更适合我的答案,而且似乎没有出现在任何答案中。

创建布局xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:paddingTop="5dip"
    android:paddingBottom="5dip"
    android:paddingStart="10dip"
    android:paddingEnd="10dip">

<ImageView
    android:id="@+id/shoe_select_icon"
    android:layout_
    android:layout_
    android:layout_gravity="center_vertical"
    android:scaleType="fitXY" />

<TextView
    android:id="@+id/shoe_select_text"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:textSize="20sp"
    android:paddingStart="10dp"
    android:paddingEnd="10dp"/>

</LinearLayout>

创建一个 ListPopupWindow 和一个包含内容的地图:

ListPopupWindow popupWindow;
List<HashMap<String, Object>> data = new ArrayList<>();
HashMap<String, Object> map = new HashMap<>();
    map.put(TITLE, getString(R.string.left));
    map.put(ICON, R.drawable.left);
    data.add(map);
    map = new HashMap<>();
    map.put(TITLE, getString(R.string.right));
    map.put(ICON, R.drawable.right);
    data.add(map);

然后在点击时,使用此功能显示菜单:

private void showListMenu(final View anchor) 
    popupWindow = new ListPopupWindow(this);

    ListAdapter adapter = new SimpleAdapter(
            this,
            data,
            R.layout.shoe_select,
            new String[] TITLE, ICON, // These are just the keys that the data uses (constant strings)
            new int[] R.id.shoe_select_text, R.id.shoe_select_icon); // The view ids to map the data to

    popupWindow.setAnchorView(anchor);
    popupWindow.setAdapter(adapter);
    popupWindow.setWidth(400);
    popupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() 
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
            switch (position)
                case 0:
                    devicesAdapter.setSelectedLeftPosition(devicesList.getChildAdapterPosition(anchor));
                    break;
                case 1:
                    devicesAdapter.setSelectedRightPosition(devicesList.getChildAdapterPosition(anchor));
                    break;
                default:
                    break;
            
            runOnUiThread(new Runnable() 
                @Override
                public void run() 
                    devicesAdapter.notifyDataSetChanged();
                
            );
            popupWindow.dismiss();
        
    );
    popupWindow.show();

【讨论】:

【参考方案3】:

Kotlin 方式

fun showPopupMenu(view: View) 
    PopupMenu(view.context, view).apply 
                menuInflater.inflate(R.menu.popup_men, menu)
                setOnMenuItemClickListener  item ->
                    Toast.makeText(view.context, "You Clicked : " + item.title, Toast.LENGTH_SHORT).show()
                    true
                
            .show()

更新: 在上面的代码中,apply 函数返回this,这不是必需的,所以我们可以使用不返回任何内容的run,为了更简单,我们可以同时删除 showPopupMenu 方法的花括号。

更简单:

fun showPopupMenu(view: View) = PopupMenu(view.context, view).run 
            menuInflater.inflate(R.menu.popup_men, menu)
            setOnMenuItemClickListener  item ->
                Toast.makeText(view.context, "You Clicked : $item.title", Toast.LENGTH_SHORT).show()
                true
            
            show()
        

【讨论】:

【参考方案4】:

首先,在“res”文件夹中创建一个名为“menu”的文件夹。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="Search"/>
    <item
        android:id="@+id/add"
        android:icon="@android:drawable/ic_menu_add"
        android:title="Add"/>
    <item
        android:id="@+id/edit"
        android:icon="@android:drawable/ic_menu_edit"
        android:title="Edit">
        <menu>
            <item
                android:id="@+id/share"
                android:icon="@android:drawable/ic_menu_share"
                android:title="Share"/>
        </menu>
    </item>

</menu>

然后,创建您的 Activity 类:

public class PopupMenu1 extends Activity 
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popup_menu_1);
    

    public void onPopupButtonClick(View button) 
        PopupMenu popup = new PopupMenu(this, button);
        popup.getMenuInflater().inflate(R.menu.popup, popup.getMenu());

        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() 
            public boolean onMenuItemClick(MenuItem item) 
                Toast.makeText(PopupMenu1.this,
                        "Clicked popup menu item " + item.getTitle(),
                        Toast.LENGTH_SHORT).show();
                return true;
            
        );

        popup.show();
    

【讨论】:

以上是关于Android自定义下拉/弹出菜单的主要内容,如果未能解决你的问题,请参考以下文章

Delphi自定义弹出/下拉菜单,如何?

请教实现android工程中点击菜单弹出一个对话框

Android 使用PopupWindow实现弹出更多的菜单

自定义 ListView 中的弹出菜单

Android Kotlin 多选下拉菜单

如何将工具提示/下拉菜单/弹出窗口添加到 UDF/用户定义的 Excel 2010 函数?