【问题标题】:Android - Long Click on RecyclerView item and ContextMenuAndroid - 长按 RecyclerView 项目和 ContextMenu
【发布时间】:2016-07-27 08:12:03
【问题描述】:

问题:当长按回收站视图中的项目时,无法显示显示“删除”选项的上下文菜单

预期结果:见下图

我快到了,但我缺少一些东西来使 contextMenu 显示在 longClick 上。

这是我放在 viewHolder 中的内容。我不知道我应该添加什么以及在 onLongClick 事件中在哪里显示上下文菜单。

我跳过了一些代码行并保留了与我的问题相关的代码。

非常感谢您的帮助,

处理这两种点击的界面

public interface OnItemClickListener{
    void onItemClick(int position);
}

public interface OnItemLongClickListener{
    void onItemLongClick(int position);
}

Viewholder 代码

public void bindLongClick(final int position, final OnItemLongClickListener onItemLongClickListener) {
        itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                onItemLongClickListener.onItemLongClick(position);
                return true;
            }
        });
    }

    @Override
    public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo){
            //menuInfo is null
        Log.v(LOG_TAG, "grrr");
        contextMenu.setHeaderTitle("Select The Action");
        contextMenu.add(0, view.getId(), 0, "Supprimer");//groupId, itemId, order, title
    }

适配器代码

@Override
    public void onBindViewHolder(CityListViewholder holder, int position) {
        holder.cityName.setText(cityArrayList.get(position).getCityName());
        holder.bindClick(position, onItemClickListener);
        holder.bindLongClick(position, onItemLongClickListener);
    }

然后,在活动中 - 我跳过了与我的问题无关的内容

mCityListAdapter = new CityListAdapter(mContext, cityArrayList, new CityListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                mPager.setCurrentItem(position);
                mDrawerLayout.closeDrawers();
            }
        }, new CityListAdapter.OnItemLongClickListener() {
            @Override
            public void onItemLongClick(int position) {
                Log.v(LOG_TAG, "Position "+position);
            }
        });

        registerForContextMenu(mRecyclerView);

【问题讨论】:

  • 抱歉,我好像没完全明白?你想在长按项目时显示弹出窗口吗?
  • 谢谢迈克尔,我更新了我的问题,添加了我所期待的说明,并在问题之上更好地描述了我的问题。
  • @millinet 在长按中显示上下文菜单。通过查看您的代码,您没有在 LongClick 中实现任何内容
  • @JagjitSingh 我知道,这就是我所缺少的。这可能很容易,但我不知道如何“调用/显示”它。
  • 我应该把“onCreateContextMenu(...);”在长按?谢谢

标签: android android-recyclerview contextmenu


【解决方案1】:

您需要在其中显示带有列表的对话框。像这样:

    itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View view) {
            final CharSequence[] items = {"Supprimer", "etc", "etc1"};

            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);

            builder.setTitle("Select The Action");
            builder.setItems(items, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int item) {
                }
            });
            builder.show();
            return true;
        }
    });

【讨论】:

  • 所以不需要注册ContextMenu和相关的方法?即使我想试验上下文菜单,这个解决方案也确实可以解决问题。
  • 没必要,至少上次我使用上下文菜单是在 3 年前,我认为它没有用。
  • 我最终选择了您的解决方案,这是实现我想做的最简单的方法。谢谢!
  • @Divers 完美的解决方案,小巧而优化。谢谢:)
  • RecyclerView中如何获取选中项?
【解决方案2】:

接受的答案在技术上不是“答案”,它是一个相当聪明的解决方法,因为它创建一个 AlertDialog 而不是 OP 要求的 ContextMenu,它确实“解决了要求”,但它没有创建一个ContextMenu

这是我找到的最短的实现:

在 Activity 中,照常覆盖:

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    menu.add("do this");
    menu.add("do that");
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    if (item.getTitle().equals("do this") {
        // do whatever this...
    }
    else if (item.getTitle().equals("do that") {
        // do whatever that...
    }
    return super.onContextItemSelected(item);
}

在 RecyclerView 的 item ViewHolder 中:

private class ItemViewHolder extends RecyclerView.ViewHolder {
    ...
    private ItemViewHolder(@NonNull View pItemView) {
        super(pItemView);
        pItemView.setLongClickable(true); // <-- make long clickable
        ...
    }
}

在 Activity onCreate:

registerForContextMenu(myRecyclerView);

【讨论】:

  • 投了反对票,因为没有逻辑可以获取哪个项目已被长时间点击! ContextMenu 在 Activity 上下文中,而 LongClick 在 Adapter 中
  • 它就在上面的 .onContextItemSelected() 事件处理程序中 - 它非常清晰。在活动上调用 .registerForContextMenu() 会注册带有上面定义的事件处理程序的 RecyclerView。事件处理程序不必在适配器内部,实际上它可以完全在一个单独的类中。仅供参考,这也是经过良好测试的代码,样本取自生产中的一个应用程序。
  • @AlexVPerl 对,但是如果我们有一个人的recycler,我们如何获取onContextItemSelected()中被长点击的人的名字?
【解决方案3】:

编辑1:要专门显示对话框,请使用

 openContextMenu(v);

其中 v 指的是视图。和

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.context_menu,menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
  int id = item.getItemId();
        default:
            return super.onContextItemSelected(item);
    }
}

Menu 文件夹中context_menu 文件中的代码应如下所示:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.MainActivity">

    <item
        android:id="@+id/item"
        android:orderInCategory="200"
        android:title="Item"
        android:icon="@drawable/faq"
        app:showAsAction="ifRoom"
        ></item>
</menu>

过去,我对 RecyclerView 的onClickListeneronLongClickListener 也有一些问题。所以这是我正在使用的:

public class ItemClickSupport {
    private final RecyclerView mRecyclerView;
    private OnItemClickListener mOnItemClickListener;
    private OnItemLongClickListener mOnItemLongClickListener;
    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
        }
    };
    private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (mOnItemLongClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
            return false;
        }
    };
    private RecyclerView.OnChildAttachStateChangeListener mAttachListener
            = new RecyclerView.OnChildAttachStateChangeListener() {
        @Override
        public void onChildViewAttachedToWindow(View view) {
            if (mOnItemClickListener != null) {
                view.setOnClickListener(mOnClickListener);
            }
            if (mOnItemLongClickListener != null) {
                view.setOnLongClickListener(mOnLongClickListener);
            }
        }

        @Override
        public void onChildViewDetachedFromWindow(View view) {

        }
    };

    private ItemClickSupport(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        mRecyclerView.setTag(R.id.item_click_support, this);
        mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
    }

    public static ItemClickSupport addTo(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support == null) {
            support = new ItemClickSupport(view);
        }
        return support;
    }

    public static ItemClickSupport removeFrom(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support != null) {
            support.detach(view);
        }
        return support;
    }

    public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
        return this;
    }

    public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
        mOnItemLongClickListener = listener;
        return this;
    }

    private void detach(RecyclerView view) {
        view.removeOnChildAttachStateChangeListener(mAttachListener);
        view.setTag(R.id.item_click_support, null);
    }

    public interface OnItemClickListener {

        void onItemClicked(RecyclerView recyclerView, int position, View v);
    }

    public interface OnItemLongClickListener {

        boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
    }
}

然后在活动中,使用以下内容:

ItemClickSupport.addTo(recyclerView).setOnItemLongClickListener(new ItemClickSupport.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) {

                return true;
            }
    });

使用position指定项目。希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 2016-04-04
    • 2018-11-14
    相关资源
    最近更新 更多