如何在CustomAdapter中的Recycler View上实现LongPress?

时间:2016-08-15 13:53:55

标签: android android-fragments android-recyclerview

我正在对RecyclerView实施长按。当用户长按CyclelerView时,它会显示一个带有删除选项的菜单栏。现在我遇到了这种实现的两个问题。

首先,菜单栏不会覆盖状态栏。它弹出状态栏上方。我说的状态栏是应用程序名称所在的栏。如何使其与状态栏重叠?

其次,所以我改变了我最初编写代码的方式,现在我正在为不同的java文件中的recycler视图实现适配器。我将活动的上下文从片段传递给此适配器,但是当我长按它时会显示此错误。

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.MenuInflater android.support.v4.app.FragmentActivity.getMenuInflater()' on a null object reference 
at onCreateActionMode

这就是我在片段中实现的内容:

public ModalMultiSelectorCallback mDeleteMode = new ModalMultiSelectorCallback(mMultiSelector) {

        @Override
        public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
            super.onCreateActionMode(actionMode, menu);
            getActivity().getMenuInflater().inflate(R.menu.list_item_delete, menu);
            return true;
        }

在这个片段的onCreateView中,我这样做:

context = getActivity();

然后我用ArrayList将其发送到我的适配器:

customAdapter = new MyCustomAdapter(context, myArrayList);

在我的自定义适配器中,我这样做:

public MyCustomAdapter(Context context, ArrayList<myArrayList> myArrayList) {
        mContext = context;
        this.myArrayList= myArrayList;
    }

在这个Adapter中,我有一个名为CustomRecyclerViewHolder的内部类,我实现了我的onLongPress

@Override
        public boolean onLongClick(View v) {

            ((AppCompatActivity) mContext).startSupportActionMode(myFragment.mDeleteMode);
            myFragment.mMultiSelector.setSelected(this, true);
            return true;
        }

如上所述,最终会出现NullPointerException。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我的猜测是你使用Big Nerd Ranch的recyclerview-multiselect库,this sample code作为项目的基础。在此示例项目中,ModalMultiSelectorCallback对象正在全局范围内实例化。

这似乎不是实例化此对象的最佳位置,考虑到您尝试调用getActivity(),可以null,直到调用片段的onCreate()方法。我会按照这些步骤来解决这个问题。

首先,使用actionMode.getMenuInflater()代替getActivity(),因为ActionMode会提供Context。接下来,创建一个使用您的实现扩展ModalMultiSelectorCallback的类:

public class CustomMultiSelectorCallback extends ModalMultiSelectorCallback {

    public CustomMultiSelectorCallback(MultiSelector multiSelector) {
        super(multiSelector);
    }

    @Override
    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
        super.onCreateActionMode(actionMode, menu);
        actionMode.getMenuInflater().inflate(R.menu.crime_list_item_context, menu);
        return true;
    }

    @Override
    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
        ...
    }
}

最后,在ModalMultiSelectorCallback的{​​{1}}方法中创建onCreate()的实例:

Fragment

答案 1 :(得分:0)

您的实施过于复杂。而不是在适配器内进行所有自定义处理,它应该在持有它的activity / fragment中,适配器应限于处理列表本身。执行此操作的正确方法是在适配器中创建单击侦听器,并在您创建RecyclerView的相同位置处理回调。

在适配器中,创建一个界面:

model

然后在onCreateViewHolder中创建所需的侦听器:

public interface ClickListener {
    void onItemClick(View v, int position);
    void onLongItemClick(View v, int position);
}

创建适配器时需要创建接口,因此请在构造函数中处理:

@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_item, parent, false);

    final ViewHolder viewHolder = new ViewHolder(v);
    v.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            listener.onItemClick(v, viewHolder.getAdapterPosition());
        }
    });
    v.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            listener.onLongItemClick(v, viewHolder.getAdapterPosition());
            return true;
        }
    });
    return viewHolder;
}

当你创建适配器时:

public MyAdapter(List<MyObject> list, ClickListener listener) {
    this.list = list;
    this.listener = listener;
}

理想情况下,一旦实现了这一点,就不需要将Context传递给适配器,并且可以在应有的位置处理其他逻辑和空值检查,适配器可以重用于其他实现。