Item click listeners for RecyclerView

2020-02-07 13:05发布

I have been trying to work on RecycleView item click listener. I have come up with following solution. I would like to know if this solution is correct or just a "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;
    }
}

Then in my 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();
            }
        });

4条回答
兄弟一词,经得起流年.
2楼-- · 2020-02-07 13:52
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){}

}

and using:

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) {

    }
}));
查看更多
▲ chillily
3楼-- · 2020-02-07 13:56

This is my implementation of 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);
    }
}

Then you can transfer your onClickListener to this.

RecyclerAdapter adapter = new RecyclerAdapter();
adapter.setClickListener(new ViewHolder.IOnClickListener(){...}, new ViewHolder.IOnLongClickListener(){...})
查看更多
姐就是有狂的资本
4楼-- · 2020-02-07 14:00

Try this:

mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(mActivity, mRecyclerView, new RecyclerTouchListener.ClickListener() { @Override 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();
        }
    }));

public class RecyclerTouchListener implements

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

}

查看更多
趁早两清
5楼-- · 2020-02-07 14:07

This blog post by Hugo shows an alternative way without listeners: http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/

It comes down to adding these lines:

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

When using this class:

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

And this value in ids.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="item_click_support" type="id" />
</resources>
查看更多
登录 后发表回答