Android 如何设置弹出菜单项的id,作为视图id? 背景

Android 如何设置弹出菜单项的id,作为视图id? 背景,android,menuitem,popupmenu,Android,Menuitem,Popupmenu,Out自动测试使用视图的ID来点击它们,所以我们尽可能地添加ID 问题 对于弹出菜单,有时需要动态填充它们,但正如我所发现的,即使我为每个项目添加了id,也找不到id,也无法使用。即使使用DDMS的功能“dump view hierarchy for UI automator”也表明弹出菜单中没有视图具有id 我试过的 这是我用来尝试为单个菜单项设置id的示例代码 @Override protected void onCreate(Bundle savedInstanceState) {

Out自动测试使用视图的ID来点击它们,所以我们尽可能地添加ID

问题 对于弹出菜单,有时需要动态填充它们,但正如我所发现的,即使我为每个项目添加了id,也找不到id,也无法使用。即使使用DDMS的功能“dump view hierarchy for UI automator”也表明弹出菜单中没有视图具有id

我试过的 这是我用来尝试为单个菜单项设置id的示例代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View v=findViewById(R.id.button);
    v.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(final View v) {
            PopupMenu popupMenu = new PopupMenu(MainActivity.this, v);
            final Menu menu = popupMenu.getMenu();
            menu.add(0, R.id.myMenuItem, 0, R.string.app_name).setOnMenuItemClickListener(new OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(final MenuItem item) {
                    return false;
                }
            }) ;
            popupMenu.show();
        }
    });
}
请注意,id在“ids.xml”文件中声明,如下所示:

<item name="myMenuItem" type="id"/>

这是DDMS工具向我展示的:

问题
为什么这段代码不能按预期工作(意味着有菜单项视图的id)?如何使其中的视图具有ID?为动态创建的菜单项添加ID的正确方法是什么

好吧,这绝不是问题中描述的问题的答案。将其视为替换
PopupMenu
以实现要求的功能的替代方案

弹出菜单
在翻阅了
PopupMenu
的文档及其源代码后,我终于明白
PopupMenu
不是一个允许定制的实现(我为评论中的误解向PO道歉)

替代方案 另一种选择是使用
ListPopupWindow
创建弹出菜单,原因如下:

  • 它与
    弹出菜单
    -
    列表视图
    共享同一父级
  • 它非常灵活,允许使用自定义布局定义自定义
    适配器
  • 它还允许运行时创建,如
    PopupMenu
    does,并允许将资源id附加到项目视图
  • 实施 首先,让我们为弹出项定义一个自定义布局(
    popup\u item\u view.xml

    最后,将
    弹出菜单
    代码替换为以下内容

    PopupAdapter.Item[] items = {
        new PopupAdapter.Item(R.id.popup_item_1, "item 1"),
        new PopupAdapter.Item(R.id.popup_item_2, "item 2")
    };
    
    ListPopupWindow popup = new ListPopupWindow(MainActivity.this);
    popup.setAnchorView(view);
    popup.setAdapter(new PopupAdapter(items));
    popup.setModal(true);
    popup.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            // do something
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
           // do something
        }
    });
    popup.show();
    
    PopupAdapter.Item[]项={
    新的PopupAdapter.Item(R.id.popup_Item_1,“Item 1”),
    新的PopupAdapter.Item(R.id.popup_Item_2,“Item 2”)
    };
    ListPopupWindow popup=新建ListPopupWindow(MainActivity.this);
    弹出.setAnchorView(视图);
    setAdapter(新的PopupAdapter(项目));
    popup.setModal(true);
    popup.setOnItemSelectedListener(新的AdapterView.OnItemSelectedListener(){
    @凌驾
    已选择公共视图(AdapterView父视图、视图视图、整型位置、长id){
    //做点什么
    }
    @凌驾
    未选择公共无效(AdapterView父级){
    //做点什么
    }
    });
    popup.show();
    

    希望这能有所帮助。

    你能详细说明一下“没有按预期工作”吗?@haike00,正如我所写的:它没有id,即使我已经将它设置为有id。我现在会添加更好的代码和屏幕快照。恐怕我还是不明白你想做什么。据我所知,您正试图将
    R.id.myMenuItem
    设置为
    MenuItem
    的id。因此,在
    OnMenuItemClickListener()
    侦听器中,当您执行
    item.getItemId()
    时,您将能够检索到与
    R.id.myMenuItem
    等效的id。这不是你想要的吗?@haike00正如我在“背景”部分中所写,我需要视图本身具有此id,以便自动测试能够找到视图并单击它。这适用于工具栏菜单项,但不适用于弹出菜单。我不需要应用程序本身的id,因为我已经有了对菜单项的引用。我需要它来进行自动测试。我刚刚做了一个测试,即使是
    工具栏
    也不会给我一个正确的资源id。无论如何,您传递到
    菜单的第二个参数。添加(0,x,0,0)
    是针对项目id的。如果需要,您必须强制循环菜单项视图,并将项目ID设置为其视图ID。另一种选择是考虑使用索引ID来实现您想要做的。这很有趣。它是否还能够选择将弹出窗口放在何处(在视图的顶部或下方)?不管怎样,希望能尽快查出来,然后勾选答案。现在,请使用+1.:)我认为它是在运行时决定的(通过
    ListPopupWindow
    ),如果它觉得在锚定的
    视图下没有足够的空间,它只会在上面绘制它。试试看好的,您可以使用
    setDropDownGravity(gravity)
    进行设置。不,不能使用
    setDropDownGravity(gravity)
    进行设置。我不确定它是否有效。我的意思是这对这:。一个在目标视图的下方,一个在目标视图的顶部。
    package com.example.popupmenu;
    
    import android.support.annotation.NonNull;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class PopupAdapter extends BaseAdapter {
        public static class Item {
            public final int id;
            public final String title;
    
            public Item(int id, @NonNull String title) {
                this.id = id;
                this.title = title;
            }
        }
    
        private List<Item> mItemList = new ArrayList<>();
    
        public PopupAdapter(@NonNull Item[] items) {
            mItemList.addAll(Arrays.asList(items));
        }
    
        @Override
        public int getCount() {
            return mItemList.size();
        }
    
        @Override
        public Item getItem(int position) {
            return mItemList.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final Item item = getItem(position);
            if (convertView == null) {
                LayoutInflater inflater = LayoutInflater.from(parent.getContext());
                convertView = inflater.inflate(R.layout.popup_item_view, parent, false);
            }
            convertView.setId(item.id);
            TextView titleView = (TextView) convertView.findViewById(R.id.popup_text);
            titleView.setText(item.title);
            return convertView;
        }
    }
    
    PopupAdapter.Item[] items = {
        new PopupAdapter.Item(R.id.popup_item_1, "item 1"),
        new PopupAdapter.Item(R.id.popup_item_2, "item 2")
    };
    
    ListPopupWindow popup = new ListPopupWindow(MainActivity.this);
    popup.setAnchorView(view);
    popup.setAdapter(new PopupAdapter(items));
    popup.setModal(true);
    popup.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            // do something
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
           // do something
        }
    });
    popup.show();