【问题标题】:Setting OnClickListener on RecyclerView itself not on item在 RecyclerView 本身上设置 OnClickListener 不在项目上
【发布时间】:2018-06-26 13:30:50
【问题描述】:

我想在RecyclerView 上设置一个OnClickListener不在它的项目上 以便在用户点击RecyclerView 时触发点击事件(即使它是空的或满载物品)。

  • 我正在使用 MVVM
  • 我试过mRecyclerView.setClickable(true),不行

我想要什么

mRecyclerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // do something
    }
});

我的适配器类

public class TaskItemAdapter extends RecyclerView.Adapter<TaskItemAdapter.BaseItemAdapterViewHolder> {
    private static final String TAG = TaskItemAdapter.class.getSimpleName();
    private List<Task> mTaskList;
    private View.OnLongClickListener mOnLongClickListener;

    public TaskItemAdapter(List<Task> taskList, View.OnLongClickListener longClickListener) {
        mTaskList = taskList;
        mOnLongClickListener = longClickListener;
    }

    @NonNull
    @Override
    public BaseItemAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (parent instanceof RecyclerView) {
            int layoutId = R.layout.item_list_main;
            View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
            view.setFocusable(true);
            return new BaseItemAdapterViewHolder(view);

        } else {
            throw new RuntimeException(TAG + "Not bound to recyclerView");
        }
    }

    @Override
    public void onBindViewHolder(@NonNull BaseItemAdapterViewHolder holder, int position) {
        Task task = mTaskList.get(position);
        holder.mItemTextView.setText("- " + task.getName());

        holder.itemView.setTag(task);
        holder.itemView.setOnLongClickListener(mOnLongClickListener);
    }

    @Override
    public int getItemCount() {
        return mTaskList.size();
    }

    public void loadItems(List<Task> taskList) {
        mTaskList = taskList;
        notifyDataSetChanged();
    }

    public class BaseItemAdapterViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.item_textView)
        TextView mItemTextView;

        public BaseItemAdapterViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }
}

【问题讨论】:

  • RecyclerView 我认为不要对点击事件进行操作。您可以通过将onClickListener 添加到为空的背景视图(在回收器视图下)来解决您的问题,或者在它不为空时收听onItemClick
  • 当您点击RecyclerView 的项目时,您希望在 RecyclerView 和 RecyclerView 项目或仅 RecyclerView 上接收点击监听?
  • 你在解决什么问题?
  • 你想达到什么目的?因为如果你为recyclerview设置了一个clicklistener,无论它是满的还是空的,那么你将无法正确地为每个项目设置一个clicklistener。

标签: android android-recyclerview onclicklistener


【解决方案1】:
mRecyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return true;
    }
});

然后只需处理您想要的 MotionEvent 类型。如果您不希望 RecylerView 用它做任何其他事情,则返回 true。

【讨论】:

    【解决方案2】:

    来自 View.OnTouchListener onTouch() 按下和释放事件。可以触发视图。

    【讨论】:

      【解决方案3】:

      默认情况下,RecyclerView 不提供 OnClick 回调。所以你可以创建一个 OnTouchListener 来消费点击事件。

      public class RVClickHandler implements View.OnTouchListener {
      
          private RecyclerView mRecyclerView;
          private float mStartX;
          private float mStartY;
      
          public RVClickHandler(RecyclerView recyclerView) {
              mRecyclerView = recyclerView;
          }
      
          @Override
          public boolean onTouch(View v, MotionEvent event) {
              boolean isConsumed = false;
              switch (event.getAction()) {
                  case MotionEvent.ACTION_DOWN: {
                      mStartX = event.getX();
                      mStartY = event.getY();
                      break;
                  }
                  case MotionEvent.ACTION_UP: {
                      float endX = event.getX();
                      float endY = event.getY();
                      if(detectClick(mStartX, mStartY, endX, endY)) {
                          //Ideally it would never be called when a child View is clicked.
                          //I am not so sure about this.
                          View itemView = mRecyclerView.findChildViewUnder(endX, endY);
                          if(itemView == null) {
                              //RecyclerView clicked
                              mRecyclerView.performClick();
                              isConsumed = true;
                          }
                      }
                      break;
                  }
              }
              return isConsumed;
          }
      
          private static boolean detectClick(float startX, float startY, float endX, float endY) {
              return Math.abs(startX-endX) < 3.0 && Math.abs(startY-endY) < 3.0;
          }
      
      }
      

      将此添加到您的RecyclerView,如下所示

      recyclerView.setOnTouchListener(new RVClickHandler(recyclerView));
      

      现在您可以附加一个普通的 OnClickListener 来处理点击。

      recyclerView.setOnClickListener((v) -> {
          //Called when an empty space is clicked inside RecyclerView.
      });
      

      子视图的点击事件可以在ViewHolder内处理

      【讨论】:

        【解决方案4】:

        我设法做到了:

        我将两个监听器传递给适配器:

        View.OnClickListener;
        View.OnTouchListener;
        

        onCreateViewHolder 方法中,我设置了两个监听器,并将 recyclerViewID 传递到标签中。

        int layoutId = R.layout.item_list_main;
        View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
        view.setFocusable(true);
        parent.setOnTouchListener(mOnTouchListener);
        view.setTag(R.id.PARENT_VIEW_ID, parent.getId());
        view.setOnClickListener(mOnClickListener);
        return new BaseItemAdapterViewHolder(view);
        

        在主要活动中:

        1. View.OnTouchListener在recyclerView的空白处操作 本身。
        2. View.OnClickListener在recyclerView的item中操作。
        3. 并使用了一个空的布局点击监听器。

        所以现在无论用户点击 recyclerView 或其项目,还是它的空状态,它都会触发整个点击。

        【讨论】:

          【解决方案5】:

          当您在 onCreateView 中将焦点设置为 Adapter 视图时,您的父级(即 recyclerview 在设置焦点规则之前不会获得焦点。)您可以尝试

          recycler.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
          

          【讨论】:

            【解决方案6】:

            您可以在适配器内为 View 添加,而不是向 RecyclerView 添加 onClick 侦听器。

            @Override
                public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                    View itemView = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.recycler_layout, parent, false);
                    itemView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(mContext,"RecyclerView Clicked", Toast.LENGTH_SHORT).show();
                        }
                    });
            
                    return new MyViewHolder(itemView);
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-01-04
              • 1970-01-01
              • 1970-01-01
              • 2013-10-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多