##背景
我们经常在列表的页面中,点击列表中的行,一般进入详情页面,长按列表中一行,会弹出一个菜单,包含了对某一行的操作(编辑、删除等等),也知道通常的用法:
- 0x01. 在Activity中注册需要上下文菜单的View:
registerForContextMenu(mListView);
0x02. 然后在Activity中继承onCreateContextMenu方法,添加菜单项:
12345678@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {Log.d(LOG_TAG, "onCreateContextMenu");super.onCreateContextMenu(menu, v, menuInfo);menu.setHeaderTitle(R.string.prompt);menu.add(Menu.NONE, R.id.context_menu_item_delete_record, Menu.NONE, R.string.delete_record);//groupId, itemId, order, titlemenu.add(Menu.NONE, R.id.context_menu_item_delete_record_with_file, Menu.NONE, R.string.delete_record_with_file);}PS:每次长按出现上下文菜单都会调用这个方法
12345678910/** * Called when a context menu for the {@code view} is about tobe shown. * Unlike {@link #onCreateOptionsMenu(Menu)}, this willbe called every * time the context menu is about to be shown andshould be populated for * the view (or item inside the view for {@linkAdapterView} subclasses, * this can be found in the {@codemenuInfo})). * <p> * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an* item has been selected. * <p> * It is not safe to hold onto thecontext menu after this method returns. * */public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {}0x03. 接下来长按列表中一行的时候,会弹出上下文菜单:
0x04. 点击菜单后,在Activity中继承onContextItemSelected方法进行处理:
12345@Overridepublic boolean onContextItemSelected(MenuItem item) {switch (item.getItemId()){}}0x05. 获取Item标识(id)
我们删除数据库或者一行记录的时候,要知道主键(一般是id)才能进行操作,很多人就想办法,有的是把ListView的每个ItemView添加一个LongClickListener,然后长按的时候记录下Position,然后在进行相应处理。其实有更优雅的做法,onContextItemSelected(MenuItem item)回调的参数item可以获取item.getMenuInfo(),在ListView和Adapter的模式中,可以强制转换成AdapterContextMenuInfo,拿到targetView(即所长按行的ItemVew,如果我们需要什么参数,直接放到View.setTag中去即可):
123AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();int index = info.position;View view = info.targetView;
至此,常见的用法就完了,那么遇到其他自定义View呢?
- 0x06. 自定义View的ContextMenu实现
下面以用到的RecycleView为例,没有了ListView及其Adapter的封装,我们需要自己处理ContextMenu。
最重要的是继承View的两个方法:
1.上下文菜单Item的附加信息(上面item.getMenuInfo());12345678910/** * Views should implement this if they have extra information toassociate * with the context menu. The return result is supplied as aparameter to * the {@linkOnCreateContextMenuListener#onCreateContextMenu(ContextMenu,View, ContextMenuInfo)} * callback. * * @return Extra informationabout the item for which the context menu * should be shown.This information will vary across different * subclasses of View. */protected ContextMenuInfo getContextMenuInfo() {return null;}
2.ViewGroup的showContextMenuForChild,每次弹出上下文菜单都会调用此方法,需要在这里更新ContextMenuInfo;
|
|
- 0x07. 自定义RecycleView的ContextMenu全部代码
|
|
有两个地方需要注意:
1.onBindViewHolder中给ItemView添加Tag;
2.设置ItemView的LongClickable为true,不然不会出现上下文菜单(具体原因见ContextMenu原理分析);
holder.itemView.setLongClickable(true);