前言

最近自己写了一个问卷调查的APP,想要实现对RecyclerView里面列表进行移动或删除的功能,常规的方法会使用PopupWindow、AlertDialog或是DialogFragment等控件来做,检索资料的时候无意间发现RecyclerView是支持ContextMenu的,所以自己尝试一下。

效果如下:

效果图

实现步骤

先来简单介绍一下实现步骤。分以下几个步骤:

1、给你RecyclerView中的的item布局设置longClickable属性,这样在长按item的时候才能弹出ContextMenu。

android:longClickable="true"

2、在Activity中注册需要上下文菜单的View

registerForContextMenu(mRecyclerView);

3、重载onCreateContextMenu和onContextItemSelected方法。

创建ContextMenu的时候被回调。其中,question_option_menu是自定义的菜单布局,包含三个item——上移、删除、下移。

@Override

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

super.onCreateContextMenu(menu, v, menuInfo);

getMenuInflater().inflate(R.menu.question_option_menu, menu);

}

点击具体菜单条目的时候被回调

@Override

public boolean onContextItemSelected(MenuItem item) {

//获取到的是listView里的条目信息

RecyclerViewWithContextMenu.RecyclerViewContextInfo info = (RecyclerViewWithContextMenu.RecyclerViewContextInfo) item.getMenuInfo();

Log.d(TAG,"onCreateContextMenu position = " + (info != null? info.getPosition() : "-1"));

if(info != null && info.getPosition() != -1) {

switch (item.getItemId()) {

case R.id.action_move_up:

mAdapter.moveUpItem(info.getPosition());

break;

case R.id.action_remove:

mAdapter.removeItem(info.getPosition());

break;

case R.id.action_move_down:

mAdapter.moveDownItem(info.getPosition());

break;

default:

//do nothing

}

}

return super.onContextItemSelected(item);

}

以上就是RecyclerView+ContextMenu实现菜单项的基本步骤,那么问题来了——技术点(坑)在哪呢?

如何获得RecyclerView中被点击item的position

在实现这个功能的时候在这里被卡住了,翻了一下源码,又在网上找了一些资料并没有发现有什么现成的方法可以调用来获得被点击条目的位置信息。细心的码友会发现onCreateContextMenu这个方法有一个ContextMenu.ContextMenuInfo参数,从名字一看就是用来传递跟ContextMenu相关的信息的。ContextMenu类中对ContextMenuInfo的解释是与所创建的ContextMenu相关的附加信息。比如,可以用来传递item在adapter中准确的位置信息。

/**

* Additional information regarding the creation of the context menu. For example,

* {@link AdapterView}s use this to pass the exact item position within the adapter

* that initiated the context menu.

*/

public interface ContextMenuInfo {

}

根据代码上的注释,在AdapterView类中找到了一个实现ContextMenuInfo接口的内部类AdapterContextMenuInfo。

/**

* Extra menu information provided to the

* {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) }

* callback when a context menu is brought up for this AdapterView.

*

*/

public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo {

public AdapterContextMenuInfo(View targetView, int position, long id) {

this.targetView = targetView;

this.position = position;

this.id = id;

}

/**

* The child view for which the context menu is being displayed. This

* will be one of the children of this AdapterView.

*/

public View targetView;

/**

* The position in the adapter for which the context menu is being

* displayed.

*/

public int position;

/**

* The row id of the item for which the context menu is being displayed.

*/

public long id;

}

通过简单的分析,我们知道了上下文菜单附加信息类和如何获得相关信息。当然,我们也可以根据项目实际需要自己实现ContextMenuInfo接口,这里我只关心响应我长按动作的item在RecyclerView中的位置信息,所以自己定义了RecyclerViewContextInfo类来实现ContextMenuInfo接口。

public static class RecyclerViewContextInfo implements ContextMenu.ContextMenuInfo {

private int mPosition = -1;

public int getPosition() {

return mPosition;

}

}

传递上下文菜单附加信息的类有了,如何传递给onCreateContextMenu方法的呢?可以通过重载RecyclerView类的showContextMenuForChild和getContextMenuInfo方法

派生了RecyclerViewWithContextMenu类。其中,在showContextMenuForChild方法中通过RecyclerView对应的LayoutManager方法获取到item的位置信息,并赋值给自定义的菜单附加信息类的对象。然后,在getContextMenuInfo方法中返回这个对象。这样上下文菜单被创建的时候就会在onCreateContextMenu方法的menuInfo对象中获得到传递的附加信息。

public class RecyclerViewWithContextMenu extends RecyclerView {

private final static String TAG = "RVWCM";

private RecyclerViewContextInfo mContextInfo = new RecyclerViewContextInfo();

public RecyclerViewWithContextMenu(Context context) {

super(context);

}

public RecyclerViewWithContextMenu(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

}

public RecyclerViewWithContextMenu(Context context, @Nullable AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

}

@Override

public boolean showContextMenuForChild(View originalView, float x, float y) {

LayoutManager layoutManager = getLayoutManager();

if(layoutManager != null) {

int position = layoutManager.getPosition(originalView);

Log.d(TAG,"showContextMenuForChild position = " + position);

mContextInfo.mPosition = position;

}

return super.showContextMenuForChild(originalView, x, y);

}

@Override

protected ContextMenu.ContextMenuInfo getContextMenuInfo() {

return mContextInfo;

}

public static class RecyclerViewContextInfo implements ContextMenu.ContextMenuInfo {

private int mPosition = -1;

public int getPosition() {

return mPosition;

}

}

}

小结

以上只是我的实现方式,写点文字记录一下,忘得时候翻一翻,有其他更好的方法欢迎留言分享。另外,可以看一下How to create context menu for RecyclerView,里面好多人提供了不同的方法,密密麻麻的很长,没细看,有兴趣的可以去看看。

android contextmenu 自定义,RecyclerView+ContextMenu实现菜单项相关推荐

  1. android自定义起止时间的时间刻度尺,Android中自定义RecyclerView如何实现不固定刻度的刻度尺...

    Android中自定义RecyclerView如何实现不固定刻度的刻度尺 发布时间:2020-07-17 16:50:28 来源:亿速云 阅读:116 作者:小猪 这篇文章主要讲解了Android中自 ...

  2. iOS:菜单控制器和菜单项:UIMenuController和UIMenuItem

    菜单控制器和菜单项:弹出自定义的菜单栏窗口 提示: 1. Menu所处的View必须实现 – (BOOL)canBecomeFirstResponder, 且返回YES 2. Menu所处的View必 ...

  3. android contextmenu 自定义,ContextMenu高级用法

    51CT0不支持MarkDown,原文请至:简书 关键字: ContextMenu ##背景 我们经常在列表的页面中,点击列表中的行,一般进入详情页面,长按列表中一行,会弹出一个菜单,包含了对某一行的 ...

  4. (4.0.15.3)Android 的上下文菜单: ContextMenu的使用方法以及与OptionMenu的区别

    ContextMenu是Android的context menu上下文菜单,选择某项VIEW后长按menu键,就会显示出来.比如EditeText就可以通过长按来弹出拥有"cut" ...

  5. android 使用上下文菜单ContextMenu

    Android 的上下文菜单类似于 PC 上的右键菜单.当为一个视图注册了上下文菜单之后,长按这个视图对象就会弹出一个浮动菜单,即上下文菜单.任何视图都可以注册上下文菜单,不过,最常见的是用于列表视图 ...

  6. android menu item属性,menuitem - Android 4.3菜单项showAsAction =“always”被忽略

    menuitem - Android 4.3菜单项showAsAction ="always"被忽略 我使用从Android 4.3(API级别18)开始提供的新v7 appcom ...

  7. Android 添加菜单项

    刚开始看郭大神的<>,实现以下里面的一些例子.利用Menu给APP添加一个菜单项. 效果图 结构图 在res的menu文件夹下创建一个xml文件,当然你也可以使用系统创建的main.xml ...

  8. CLR自定义菜单项(ToolStripItem)

    新建ToolStripColor.h 让类ToolStripColor继承自ToolStripControlHost实现,则ToolStripColor的对象并可以作为一个MenuItem添加到一个菜 ...

  9. bootstrap 导航菜单 折叠位置_python测试开发django44.xadmin自定义菜单项

    前言 xadmin后台的菜单项是放到一个app下的,并且里面的排序是按字母a-z排序,有时候我们需要划分多个项,需要自定义菜单列表,可以通过重写CommAdminView类实现. xadmin后台提供 ...

最新文章

  1. 深度剖析如何实现事务消息
  2. seaborn系列 (12) | 增强箱图boxenplot()
  3. 常见的网页技巧(转)
  4. Django(part24)--查询数据
  5. JVM虚拟机-Class文件简介
  6. 跨业自学党的第一次面试
  7. pytorch orchvision.transforms.Normalize
  8. Java基础学习总结(64)——Java内存管理
  9. SQL时间格式化 转载备用~
  10. Spine_图片显示出错的处理方法
  11. Visio2010如何安装
  12. **Gcc编译器报错:gcc -m32报错**
  13. 企业最需要的邮件服务器5大功能模块
  14. MySQL中的排序与分页
  15. python中做为词云轮廓的图片,Python如何生成词云图片
  16. 前后端开发的心得体会_从后端支撑岗位到前端渠道运营中心工作感想
  17. 光子虚拟机_光速虚拟机app下载-光速虚拟机安卓版 v1.1.1 - 安下载
  18. 谷歌平庸、百度僵化、联想掉队?
  19. MyJzvdStd+JZMediaExo
  20. 32位单总线计算机系统中,计算机系统结构答案.doc

热门文章

  1. Android开发中如何设置或者取消ExitView的焦点
  2. 计算机调整最佳外观不起作用,Win7怎么设置性能选项视觉效果调整为最佳外观?...
  3. 2年内成准独角兽,影刀RPA登榜2021杭州独角兽准独角兽企业榜单
  4. Fragment是什么,怎么用?
  5. 【 Net Micro Framework PortingKit – 10】世界首款Cortex-M3内核MFV4诞生
  6. java getabsolutepath_Java File getAbsolutePath()用法及代码示例
  7. 开题报告(2.主要观点与可能的创新之处)
  8. dev shm与oracle,初识/dev/shm oracle
  9. LTS(light-task-scheduler)
  10. 学习ROS-Academy-for-Beginners-noetic,修改记录