【问题标题】:Item click listeners for RecyclerViewRecyclerView 的项目点击监听器
【发布时间】:2015-09-01 18:51:34
【问题描述】:

我一直在尝试处理 RecycleView 项目点击监听器。我想出了以下解决方案。我想知道这个解决方案是正确的还是只是一个“hack”。

public class CityListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context context;
    private int lastPosition = -1;
    private int focusedItem = 0;
    private static Interfaces.OnCityItemClickListener cityItemClickListner;

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        private TextView cityNameTextView, tempTextView, humidityTextView, timeTextView;
        private ImageView weatherStatusImageView;
        private CardView cardView;

        public ViewHolder(View itemView) {
            super(itemView);
            cityNameTextView = (TextView) itemView.findViewById(R.id.city_name_tv);
            tempTextView = (TextView) itemView.findViewById(R.id.temp_tv);
            humidityTextView = (TextView) itemView.findViewById(R.id.humidity_tv);
            timeTextView = (TextView) itemView.findViewById(R.id.time_tv);
            cardView = (CardView) itemView.findViewById(R.id.card_view);
            itemView.setOnClickListener(this);
        }


        @Override
        public void onClick(View v) {
            cityItemClickListner.onCityItemClick(getAdapterPosition(), v);
        }
    }

    public CityListAdapter(Context context){
        this.context = context;
    }

    public void setOnCityItemClickListener(Interfaces.OnCityItemClickListener clickListener){
        cityItemClickListner = clickListener;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(context).inflate(R.layout.row_city, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ViewHolder myViewHolder = (ViewHolder) holder;
        myViewHolder.itemView.setSelected(focusedItem == position);
    }

    @Override
    public int getItemCount() {
        return 15;
    }
}

然后在我的Activity

adapter.setOnCityItemClickListener(new Interfaces.OnCityItemClickListener() {
            @Override
            public void onCityItemClick(int position, View view) {
                Toast.makeText(BaseActivity.this, "Clicked position " + position, Toast.LENGTH_SHORT).show();
            }
        });

【问题讨论】:

  • 这才是正确的做法
  • @tyczj 感谢您的快速回复。

标签: android android-recyclerview


【解决方案1】:

Hugo 的这篇博文展示了另一种没有听众的方法:http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/

归结为添加以下几行:

ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
    @Override
    public void onItemClicked(RecyclerView recyclerView, int position, View v) {
        // do it
    }
});

当使用这个类时:

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);
    }
}

以及 ids.xml 中的这个值:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="item_click_support" type="id" />
</resources>

【讨论】:

    【解决方案2】:

    这是我对 RecyclerAdapter 的实现。

    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
    ViewHolder.IOnClickListener clickListener;
    ViewHolder.IOnLongClickListener longClickListener;
    @Override
    public void setClickListener(ViewHolder.IOnClickListener clickList, ViewHolder.IOnLongClickListener longClickListener) {
        clickListener = clickList;
        longClickListener = longClickListener;
    }
    @Override
    public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.item_event, viewGroup, false);
        return new ViewHolder(v, new ViewHolder.IOnClickListener() {
            @Override
            public void onLogo(View view, ViewHolder holder, int position) {
                Log.d(TAG, "on logo click");
                clickListener.onLogo();
            }
    
            @Override
            public void onItem(View view, ViewHolder holder, final int position) {
                Log.d(TAG, "on item click");
                clickListener.onItem();
            }
        }, new ViewHolder.IOnLongClickListener() {
            @Override
            public void onItem(View view, ViewHolder holder, int position) {
                Log.d(TAG, "on item long click");
                longClickListener.onItem();                
            }
        });
    }
    
    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, OnLongClickListener {
        View mView;
        ImageView mIcon;
        IOnClickListener mClickListener;
        IOnLongClickListener mLonglickListener;
    
        public ViewHolder(View itemView,
                          IOnClickListener listener,
                          IOnLongClickListener longClickListener) {
            super(itemView);
            mView = itemView;
            mIcon = (ImageView)itemView.findViewById(R.id.icon);
    
            mClickListener = listener;
            mLonglickListener = longClickListener;
            mIcon.setOnClickListener(this);
            itemView.setOnClickListener(this);
            itemView.setOnLongClickListener(this);
        }
    
        @Override
        public void onClick(View v){
            if(v instanceof ImageView){
                mClickListener.onLogo(v, this, getAdapterPosition());
            } else {
                mClickListener.onItem(v, this, getAdapterPosition());
            }
        }
        @Override
        public boolean onLongClick(View v) {
            mLonglickListener.onItem(v, this, getAdapterPosition());
            return true;
        }
    
        public static interface IOnClickListener {
            void onLogo(View view, ViewHolder v,int position);
            void onItem(View view, ViewHolder v, int position);
        }
        public static interface IOnLongClickListener {
            void onItem(View view, ViewHolder v,int position);
        }
    }
    

    然后你可以将你的 onClickListener 转移到这个。

    RecyclerAdapter adapter = new RecyclerAdapter();
    adapter.setClickListener(new ViewHolder.IOnClickListener(){...}, new ViewHolder.IOnLongClickListener(){...})
    

    【讨论】:

      【解决方案3】:
      public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
      private OnItemClickListener mListener;
      
      public interface OnItemClickListener {
          void onItemClick(View view, int position);
      
          void onLongItemClick(View view, int position);
      }
      GestureDetector mGestureDetector;
      
      public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
          mListener = listener;
          mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
              @Override
              public boolean onSingleTapUp(MotionEvent e) {
                  return true;
              }
      
              @Override
              public void onLongPress(MotionEvent e) {
                  View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                  if (child != null && mListener != null) {
                      mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
                  }
              }
          });
      }
      
      @Override
      public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
          View childView = view.findChildViewUnder(e.getX(), e.getY());
          if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
              mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
              return true;
          }
          return false;
      }
      
      @Override
      public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
      
      @Override
      public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
      

      }

      并使用:

      recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(parentView.getContext(),
              recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
          @Override
          public void onItemClick(View view, int position) {
              //here your logic
          }
      
          @Override
          public void onLongItemClick(View view, int position) {
      
          }
      }));
      

      【讨论】:

        【解决方案4】:

        试试这个:

        mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(mActivity, mRecyclerView, new RecyclerTouchListener.ClickListener() { @覆盖 public void onClick(View view, int position) { Toast.makeText(mActivity, mProductList.get(position).getPname(), Toast.LENGTH_SHORT).show(); }

                @Override
                public void onLongClick(View view, int position) {
                    Toast.makeText(mActivity, mProductList.get(position).getPname(), Toast.LENGTH_SHORT).show();
                }
            }));
        

        公共类 RecyclerTouchListener 实现

        RecyclerView.OnItemTouchListener {

        private GestureDetector gestureDetector;
        private ClickListener clickListener;
        
        public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
            this.clickListener = clickListener;
            gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }
        
                @Override
                public void onLongPress(MotionEvent e) {
                    View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (child != null && clickListener != null) {
                        clickListener.onLongClick(child, recyclerView.getChildAdapterPosition(child));
                    }
                }
            });
        }
        
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            View child = rv.findChildViewUnder(e.getX(), e.getY());
            if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
                clickListener.onClick(child, rv.getChildAdapterPosition(child));
            }
            return false;
        }
        
        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        
        }
        
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        
        }
        
        public interface ClickListener {
            void onClick(View view, int position);
        
            void onLongClick(View view, int position);
        }
        

        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-02
          • 1970-01-01
          • 1970-01-01
          • 2018-12-27
          • 1970-01-01
          • 1970-01-01
          • 2021-03-16
          • 1970-01-01
          相关资源
          最近更新 更多