处理项目长按回收站视图

Posted

技术标签:

【中文标题】处理项目长按回收站视图【英文标题】:Handle on item long click on recycler view 【发布时间】:2015-07-16 16:26:02 【问题描述】:

我有一个自定义recyclerView 的适配器,我想在recyclerView 的项目上的长按事件上打开一个弹出菜单。 我该怎么做?

【问题讨论】:

How to create context menu for RecyclerView 的可能重复项 【参考方案1】:

这已经回答here。无论如何,你可以这样做:

class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener 
    private Article article;

    private TextView nameTextView;

    public ViewHolder(View itemView) 
        super(itemView);
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
        nameTextView = (TextView) itemView.findViewById(R.id.grid_item_article_name_textView);
    

    public void bind(Article article) 
        this.article = article;
        nameTextView.setText(article.getName());
    

    @Override
    public void onClick(View view) 
        // Context context = view.getContext();
        // article.getName()
    

    @Override
    public boolean onLongClick(View view) 
        // Handle long click
        // Return true to indicate the click was handled
        return true;
    

更新:如果您使用的是 Kotlin,请执行以下操作:

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), 
    View.OnClickListener, View.OnLongClickListener 

    init 
        itemView.setOnClickListener(this)
        itemView.setOnLongClickListener(this)
    

    private lateinit var article: Article

    private val titleTextView: TextView = itemView.findViewById(R.id.item_article_title_textView)

    fun bind(article: Article) 
        this.article = article
        titleTextView.text = article.title
    

    override fun onClick(view: View) 
        listener.onItemClick(article)
    

    override fun onLongClick(view: View): Boolean 
        Toast.makeText(view.context, "long click", Toast.LENGTH_SHORT).show()
        // Return true to indicate the click was handled
        return true
    

【讨论】:

你必须让监听器下到 Viewholder,但它仍然比所有将 TouchListeners 添加到 RecylerView 的直接解决方案要容易得多【参考方案2】:

我是这样做的:

static class ViewHolder extends RecyclerView.ViewHolder 
    TextView tvName;

    ViewHolder(View v) 
        super(v);
        tvName = (TextView) v.findViewById(R.id.textView_Username);
        //Single Tapup
        v.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
            
        );

        //Long Press
        v.setOnLongClickListener(new View.OnLongClickListener() 
            @Override
            public boolean onLongClick(View v) 
                Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
                return false;
            
        );
    

【讨论】:

这对我来说是最简单的方法! (我正在使用带有 ItemTouchHelper 的 RecyclerView 将项目从视图中滑出,并通过长按来处理值。)谢谢!!!【参考方案3】:

首先,您必须注册 Activity 以监听来自 recyclerView 的 longClick 事件(因此您不必使用任何类型的 onLongClickListener...):

registerForContextMenu(recyclerView);

然后你创建一个菜单资源(context_menu.xml):

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:title="Mostra documento" android:id="@+id/context_menu_documents_fragment_view"></item>
    <item android:title="Aggiungi ad un contenitore" android:id="@+id/context_menu_documents_fragment_add_to_box"></item>
    <item android:title="Elimina documento" android:id="@+id/context_menu_documents_fragment_delete"></item>
</menu>

在您为上下文菜单注册的活动中,您会覆盖此方法:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) 
        super.onCreateContextMenu(menu, v, menuInfo);

        // Inflate Menu from xml resource
        MenuInflater menuInflater = getActivity().getMenuInflater();
        menuInflater.inflate(R.menu.context_menu_documents_fragment, menu);
    

    @Override
    public boolean onContextItemSelected(MenuItem item) 

        Toast.makeText(getActivity(), " User selected something ", Toast.LENGTH_LONG).show();


        return false;
    

这很重要,你必须像这样修改RecyclerView适配器中的代码:

@Override
    public void onBindViewHolder(final DocumentViewHolder viewHolder, int position) 

        ...
        viewHolder.itemView.setLongClickable(true);
        ...
    

现在您可以显示上下文菜单并拦截用户选择! 但是您无法知道用户单击了哪个项目,为此您必须使用这样的自定义 RecyclerView(来自 Renaud Cerrato 的原始代码):

public class ContextMenuRecyclerView extends RecyclerView 

    private RecyclerContextMenuInfo mContextMenuInfo;



    public ContextMenuRecyclerView(Context context) 
        super(context);
    

    public ContextMenuRecyclerView(Context context, AttributeSet attrs) 
        super(context, attrs);
    

    public ContextMenuRecyclerView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
    

    @Override
    protected ContextMenu.ContextMenuInfo getContextMenuInfo() 
        return mContextMenuInfo;
    

    @Override
    public boolean showContextMenuForChild(View originalView) 
        final int longPressPosition = getChildAdapterPosition(originalView);
        if (longPressPosition >= 0) 
            final long longPressId = getAdapter().getItemId(longPressPosition);
            mContextMenuInfo = new RecyclerContextMenuInfo(longPressPosition, longPressId);
            return super.showContextMenuForChild(originalView);
        
        return false;
    

    public static class RecyclerContextMenuInfo implements ContextMenu.ContextMenuInfo 

        public RecyclerContextMenuInfo(int position, long id) 
            this.position = position;
            this.id = id;
        

        final public int position;
        final public long id;
    


在前面的onContextItemSelected() 方法中,您可以使用以下代码知道recyclerView 项目的id 和位置:

ContextMenuRecyclerView.RecyclerContextMenuInfo info = (ContextMenuRecyclerView.RecyclerContextMenuInfo) item.getMenuInfo();

最后,您必须修改 recyclerView 适配器和布局文件中的 getItemId() 方法,以确保您使用的是您的 recyclerView 而不是 android 的!

【讨论】:

【参考方案4】:

我一直在努力获取点击时项目的位置,这对我有用:

public void onClick(View view) 
    ViewHolder holder =(ViewHolder)view.getTag();
    int position = holder.getLayoutPosition();
    Log.d("testing ","pos" +position);

【讨论】:

int position = getAdapterPosition() 将返回点击项目的位置。

以上是关于处理项目长按回收站视图的主要内容,如果未能解决你的问题,请参考以下文章

长按回收站查看项目动画

如何在回收站视图android中选择多个项目?

如何在回收站视图上启用和禁用拖放

处理物品的正确方法点击回收站视图

回收站视图项目中未显示分隔线

滚动回收站视图时如何防止项目重复