识别在ContextMenu(Android)中select的视图

在Android中, onContextItemSelected只有一个MenuItem参数,所以不清楚如何识别select的视图。 MenuItem.getMenuInfo提供对Contextmenu.ContextMenuInfo的访问,但是当两个已知的子类都提供对目标视图的访问时,在界面上似乎没有访问器。

另一种方法是将onCreateContextMenu中提供的View保存在一个私有类variables中,该variables依赖于onCreateContextMenu不会在onContextItemSelected之前的活动中再次被调用。 另一种方法是使用View的id作为ContextMenu.add的itemId参数。 如果我们这样做,那么我们需要通过使用其(可能是国际化的)标题来识别从上下文菜单中select的选项。

onContextSelectedselectView的最佳方法是什么?

Solutions Collecting From Web of "识别在ContextMenu(Android)中select的视图"

Android中没有select任何选项菜单或上下文菜单中的“标识所选视图”的概念。 因此,回答你的问题是相当困难的。 所以,我会采取一些猜测。

如果通过“识别所select的视图”,则表示select哪个菜单选项,即传递给onOptionsItemSelected()onContextItemSelected()MenuItem上的getItemId() onContextItemSelected()

如果通过“识别所select的视图”,您意味着ListView中的哪一行是长时间点击以打开上下文菜单,将getMenuInfo() (在MenuItem上调用)转换为AdapterView.AdapterContextMenuInfo ,然后使用id或根据您的适配器适当的position值。 看到这里使用这种技术的示例项目 。

如果通过“标识所select的视图”,您的意思是在一个活动中有多个非ListView上下文菜单,我不会使用该UI技术。

上下文菜单的要点在于它与一个单独的底层视图相关联,显然这是Android中的一个devise局限性,即关联在onContextItemSelectedcallback中丢失了。 只要点击鼠标右键,就可以长时间触摸任何尺寸足够的视图。

正如其他职位已经build议,在一些情况下:

 AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 

是合适的,targetView是一个有用的参考点。

另一种方法是对视图进行子类化并覆盖“getContextMenuInfo”以提供视图引用。 例如,一个简单的TextView:

包...

公共类TextViewWithContext扩展TextView {
     TextViewContextMenuInfo _contextMenuInfo = null;

     public TextViewWithContext(Context context){
        超级(上下文);
         _contextMenuInfo = new TextViewContextMenuInfo(this);
     }

     public TextViewWithContext(Context context,AttributeSet attrs){
         super(context,attrs);
         _contextMenuInfo = new TextViewContextMenuInfo(this);
     }   

    受保护的ContextMenuInfo getContextMenuInfo(){
        返回_contextMenuInfo;
     }

     public boolean isContextView(ContextMenuInfo menuInfo){
        返回menuInfo ==(ContextMenuInfo)_contextMenuInfo;
     }

    受保护的类TextViewContextMenuInfo实现ContextMenuInfo {
        受保护的TextView _textView = null;

        受保护的TextViewContextMenuInfo(TextView textView){
             _textView = textView;
         }
     }
 }

 ...
     @覆盖
     public boolean onContextItemSelected(MenuItem item){   

         ContextMenuInfo menuInfo = item.getMenuInfo();

         if(textViewWithContext.isContextView(menuInfo){
             ...
         }
     }

最后,如果基类View类已经为视图指定了一个带有反向引用的ContextInfo对象,而不是像目前那样为null,那将会更有帮助。

类TestActivity extends Activity {

 // create temp item here private ImageView tmpImageView = null; 

 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){ super.onCreateContextMenu(menu, v, menuInfo); // initialize temp item mCurrentStatusImage = (ImageView) v.findViewById(R.id.rule_status); } public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case ENABLE_ID: // use temp item tmpImageView.setImageResource(android.R.drawable.presence_online); return super.onContextItemSelected(item); case DISABLE_ID: // use temp item tmpImageView.setImageResource(android.R.drawable.presence_invisible); return super.onContextItemSelected(item); default: return super.onContextItemSelected(item); } 

我通过为MenuItem设置一个groupID来解决类似的问题,例如:

  textview.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) { menu.setHeaderTitle("Context Menu"); menu.add(R.id.whateverviewclicked, RENAME_MENU_ITEM, 0, "Rename"); menu.add(R.id.whateverviewclicked, DELETE_MENU_ITEM, 1, "Delete"); } }); 

这将允许您获取onContextItemSelected中的groupID:

 public boolean onContextItemSelected(MenuItem aItem) { int selectedViewID = aItem.getGroupId(); int selectedItem = aItem.getItemId(); }; 

你不必使用资源ID – 你可以使用任何你想要的int。 为我工作!

如果您将ContextMenus附加到不在ListView中的多个视图(即视图底层没有适配器),并且您希望确定哪个View被长时间按下以访问ContextMenu,则可以实现以下“hack”。 (如果Android提供了一个可以与每个项目关联的监听器,那将会更好)。

“hack”是在类中创build一个私有View成员mLastViewTouched ,然后将以下onTouchListener附加到所有可以生成ContextMenu的视图:

  private View.OnTouchListener onTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { mLastViewTouched = view; // Store a handle on the last view touched. This will be used to identify the view on which the Context Menu was launched return false; // We return false since this indicates that the touch was not handled and so it is passed down the stack to be handled appropriately } }; 

所以每当一个视图触摸mLastViewTouched更新。 现在在onContextItemSelected您将可以访问启动ContextMenu的View。

OnCreateContextMenuListenerpublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)实现中public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)可以为每个项目设置自定义的MenuItem.OnMenuItemClickListener

  addPhotosBtn.setOnCreateContextMenuListener((menu, v, menuInfo) -> { getMenuInflater().inflate(R.menu.upload_image_menu, menu); int itemCount = menu.size(); for(int i = 0; i < itemCount; i++) { menu.getItem(i).setOnMenuItemClickListener(addPhotosBtnMenuItemClickListener); } }); 

由于此时您可以访问正在创build上下文菜单的视图,因此可以将侦听器与该视图紧密耦合。