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();
}
});
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>
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(){...})
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) {
}
}));
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);
}
}
Related
I've implemented the recyclerView clicklistener using best practices yet it still isn't working. The recyclerview is loading data from the internet using retrofit and should take users to the site where the article was published below is my code:
NOTE: My RecyclerView is a RecyclerView of Cardviews
RecyclerView Adapter
public class NewsArticleAdapter extends RecyclerView.Adapter<NewsArticleAdapter.Viewholder> {
private ArrayList<Article> newsArticles = new ArrayList<>();
private Context context;
private OnArticleListener onArticleListener;
public NewsArticleAdapter(List<Article> newsArticles, Context context, OnArticleListener onArticleListener) {
this.newsArticles = (ArrayList<Article>) newsArticles;
this.context = context;
this.onArticleListener = onArticleListener;
}
#NonNull
#Override
public Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_list_item, parent, false);
Viewholder viewholder = new Viewholder(view, onArticleListener);
return viewholder;
}
#Override
public void onBindViewHolder(#NonNull Viewholder holder, int position) {
Article currentArticle = newsArticles.get(position);
holder.newsHeadline.setText(currentArticle.getTitle());
Glide.with(context)
.load(currentArticle.getUrlToImage())
.placeholder(R.drawable.ic_launcher_foreground)
.into(holder.newsImage);
holder.newsContent.setText(currentArticle.getContent());
// holder.publishedTime.setText(UTCtoLocalDateConverter(currentArticle.getPublishedAt()));
}
#Override
public int getItemCount() {
return newsArticles.size();
}
public class Viewholder extends RecyclerView.ViewHolder implements View.OnClickListener {
OnArticleListener onArticleClickedListner;
TextView newsHeadline;
TextView newsContent;
// TextView publishedTime;
ImageView newsImage;
ConstraintLayout parentLayout;
public Viewholder(#NonNull View itemView, OnArticleListener onArticleListener) {
super(itemView);
newsHeadline = itemView.findViewById(R.id.news_headline_textView);
newsContent = itemView.findViewById(R.id.news_content_textView);
// publishedTime = itemView.findViewById(R.id.published_time_textView);
newsImage = itemView.findViewById(R.id.news_image_view);
parentLayout = itemView.findViewById(R.id.list_item_parent_layout);
onArticleClickedListner = onArticleListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Log.d("RecyclerViewAdapter", "item position clicked: " + getAdapterPosition());
onArticleClickedListner.onArticleClicked(getAdapterPosition());
}
}
/*RecyclerView onItemClickListenerInterface*/
public interface OnArticleListener {
void onArticleClicked(int position);
}
}
MainActivity (Houses RecyclerView)
public class MainActivity extends AppCompatActivity implements NewsArticleAdapter.OnArticleListener {
private RecyclerView newsRecyclerView;
private NewsArticleAdapter newsAdapter;
private NewsAPI NewsAPI;
private ArrayList<Article> newsArticles;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
newsRecyclerView = findViewById(R.id.newsRecyclerView);
newsAdapter = new NewsArticleAdapter(new ArrayList<Article>(), this, this);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
newsRecyclerView.setLayoutManager(layoutManager);
newsRecyclerView.setAdapter(newsAdapter);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RetrofitClient.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
NewsAPI = retrofit.create(NewsAPI.class);
Call<Example> call = NewsAPI.getRootJSONObject();
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
if (response.isSuccessful()) {
newsArticles = (ArrayList<Article>) response.body().getArticles();
refreshAdapterWithNewsArticles(newsArticles);
} else {
Log.d("MainActivity", "Error in on Response " + String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
Toast.makeText(MainActivity.this, "Error retrieving News Articles :(", Toast.LENGTH_SHORT).show();
}
});
}
/*
*Method used to generate list of data using recyclerView with costom adapter
* */
private void refreshAdapterWithNewsArticles(List<Article> body) {
newsAdapter = null;
newsAdapter = new NewsArticleAdapter(body, this, MainActivity.this);
newsRecyclerView.setAdapter(newsAdapter);
}
#Override
public void onArticleClicked(int position) {
Log.d("MainActivity", "onArticleClicked Was called in MainACtivity");
Article currentArticle = newsArticles.get(position);
Uri articleUri = Uri.parse(currentArticle.getUrl());
Intent intent = new Intent(Intent.ACTION_VIEW, articleUri);
startActivity(intent);
}
}
Inspired by the code provided in this answer from Jacob Tabak, in your mainActivity under onCreate method.
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(MainActivity.this, recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
//whatever you want to do with position
}
#Override
public void onLongItemClick(View view, int position) {
//whatever you want to do with position
}
}));
and create a new class name it RecyclerItemClickListener
and paste this
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
GestureDetector mGestureDetector;
private OnItemClickListener mListener;
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) {
}
public interface OnItemClickListener {
public void onItemClick(View view, int position);
public void onLongItemClick(View view, int position);
}}
It is a custom RecyclerItemClickListener.
Why don't you try the listener from the onBindViewHolder() method?
holder.your_layout_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onArticleClickedListner.onArticleClicked(position);
}
});
If you have any confusion I can explain it more clear. If you solved it you can accept the answer.
I am new to Android and I have a question.
I have a recyclerview that can be clicked and will send a query. When clicked, it will get a number/ID of each position that is clicked,
like this:
fno = arrivals.get(position).flightno;
codeCity = arrivals.get(position).arr;
When clicked for the first time it succeeds, but when clicked for the second or third time, it gets an error. I think this because the variable fno and codeCity has been filled. So how to delete the value on the variable?
This my code when the recyclerview clicked:
mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
GestureDetector gestureDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
public boolean onSingleTapUp(MotionEvent e){
return true;
}
});
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && gestureDetector.onTouchEvent(e)){
int position = rv.getChildAdapterPosition(child);
fno = arrivals.get(position).flightno;
codeCity = arrivals.get(position).arr;
final Bundle i = new Bundle();
i.putString("city", codeCity.toString()); // Key1
i.putString("flightno", fno.toString()); // Key1
open2(i);
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
});
This the query
public void open2(Bundle args) {
codeIata = args.getString("city");
String flightdate = args.getString("flightdate");
fno = args.getString("flightno");
ArrivalActivity.detail(codeIata, flightdate, fno);
}
public static void detail(String s, String date, String fno) {
DateFormat df = new SimpleDateFormat("yyyy-MM-d");
date = df.format(Calendar.getInstance().getTime());
Call<GetArrivals> arrCall = mApiInterface.getArr(s, "2019-03-04", "", fno);
arrCall.enqueue(new Callback<GetArrivals>() {
#Override
public void onResponse(Call<GetArrivals> call, Response<GetArrivals>
response) {
System.out.println("status code "+response.code());
arrivals = response.body().getResult();
mAdapter = new ArrivalAdapter(mContext, arrivals);
//mRecyclerView.setAdapter(mAdapter);
}
#Override
public void onFailure(Call<GetArrivals> call, Throwable t) {
Log.e("Retrofit Get", t.toString());
}
});
}
Thank you!
There are two approaches you can capture a click event on item of a recyclerview:
First approach
override onClick method instead of onInterceptTouchEvent.
I am providing you with an example.
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(this,
recyclerView, new ClickListener() {
#Override
public void onClick(View view, final int position) {
fno = arrivals.get(position).flightno;
codeCity = arrivals.get(position).arr;
}
}));
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private ClickListener clicklistener;
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recycleView, 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=recycleView.findChildViewUnder(e.getX(),e.getY());
if(child!=null && clicklistener!=null){
clicklistener.onLongClick(child,recycleView.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) {
}
}
Second Approach(a more conventional one)
override the OnClickListener of the viewholder of your adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
LayoutInflater inflater;
Context context;
private MyAdapter.RecyclerViewClickListener mListener;
public MyAdapter(Context context, RecyclerViewClickListener mListener) {
this.context = context;
this.mListener = mListener;
inflater = LayoutInflater.from(this.context);
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public MyViewHolder(View item, RecyclerViewClickListener listener) {
super(item);
mListener = listener;
item.setOnClickListener(this);
}
#Override
public void onClick(View view) {
mListener.onClick(view, getAdapterPosition());
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.mylayout, parent, false);
return new MyViewHolder(itemView,mListener);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return youylist.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public long getItemId(int position) {
return 0;
}
public interface RecyclerViewClickListener {
void onClick(View view, int position);
}
}
and in your Fragment/Activity:
myadapter = new MyAdapter(getContext(), new MyAdapter.RecyclerViewClickListener() {
#Override
public void onClick(View view, int position) {
fno = arrivals.get(position).flightno;
codeCity = arrivals.get(position).arr;
}
});
recyclerView.setAdapter(MyAdapter);
MyAdapter.notifyDataSetChanged();
Hope this helps you.
Error on android recyclerView Adapter. App will stop working while click on RecyclerView items. I want to go other activity when click any items, when i'm using Toast it working fine but if i add Intent then it stop working.
Here is my Interface :
public interface OnItemClickListener {
void onClick(View view, int position);
}
here is my recycler Adapter calss :
public class RecAdapter extends RecyclerView.Adapter<RecAdapter.MyViewHolder> {
private List<Items> items;
private Context context;
public RecAdapter(List<Items> items, Context context )
{
this.items = items;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.countryname.setText(items.get(position).getCountryname());
holder.rank.setText(items.get(position).getRank());
Picasso.with(context)
.load(items.get(position).getFlag())
.into(holder.flag);
holder.setClickListener(new OnItemClickListener() {
#Override
public void onClick(View view, int position) {
Intent intent = new Intent(context , Main2Activity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return items.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView countryname, rank;
ImageView flag;
private OnItemClickListener clickListener;
public MyViewHolder(View itemView) {
super(itemView);
countryname = (TextView) itemView.findViewById(R.id.capital);
rank = (TextView) itemView.findViewById(R.id.rank);
flag = (ImageView) itemView.findViewById(R.id.flag);
itemView.setTag(itemView);
itemView.setOnClickListener(this);
}
public void setClickListener(OnItemClickListener itemClickListener) {
this.clickListener = itemClickListener;
}
#Override
public void onClick(View view) {
if (clickListener != null) clickListener.onClick(view, getAdapterPosition());
}
}
}
Add click listener like this:-
View itemView;
Context context;
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);
this.context=parent.getContext();
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context , Main2Activity.class);
context.startActivity(intent);
}
});
}
copying an answer of mine from a different question:
as you already know this method is no longer available in the RecyclerView class.
My approach towards implementing onClick events in a RecyclerView is something like this:
class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
interface OnClickListener {
void onClick(Item item);
}
private final List<Item> dataset;
private final OnClickListener l;
public MyAdapter(List<Item> data, OnClickListener listener) {
this.dataset = data;
this.l = listener;
}
#Override MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = //inflate layout
MyClick click = new MyClick() {
onClick(int position) {
if (l != null) {
l.onClick(dataset.get(position));
}
}
};
return new MyViewHolder(click, v);
}
static class MyViewHolder {
final MyClick l;
public MyViewHolder(MyClick listener, View view) {
super(view);
l = listener;
// inflate views
view.setOnClickListener(new OnClickListener() {
if (l != null) {
l.onClick(getAdapterPosition());
}
});
}
interface MyClick {
void onClick(int position);
}
}
}
class MyActivity extends AppCompatActivity {
#Override void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set layout
MyAdapter adapter = new MyAdapter(getData(), new OnClickListener() {
#Override onClick(Item item) {
// do stuff with item
}
});
}
}
You can not click an holder directly..... give a id to the view then re write the code as below:
holder.(someitem).setClickListener(new OnItemClickListener() {//you need a view to execute the onclicklistener
#Override
public void onClick(View view, int position) {
Intent intent = new Intent(context , Main2Activity.class);
context.startActivity(intent);
}
});
Here is code which i create click listener for Recycler Item Click
Using this you will get two types of click
Simple Item click.
Item Long click.
Here is RecyclerItemClickListener.java File
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
public interface OnItemClickListener
{
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickListener mListener;
private 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 childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if(childView != null && mListener != null)
{
mListener.onItemLongClick(childView, recyclerView.getChildPosition(childView));
}
}
});
}
#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.getChildPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent){}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
How to use in Activity and Fragment
rvcyclerView.addOnItemTouchListener(new RecyclerItemClickListener(context, rvcyclerView,
new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
//do you what you want tot do simple click
}
#Override
public void onItemLongClick(View view, int position) {
//do you what you want tot do on long click
}
}));
public class RecAdapter extends RecyclerView.Adapter<RecAdapter.MyViewHolder> implements View.OnClickListener {
private List<Items> items;
private Context context;
private OnItemClickListener clickListener;
public RecAdapter(List<Items> items, Context context )
{
this.items = items;
this.context = context;
}
public void setClickListener(OnItemClickListener itemClickListener) {
this.clickListener = itemClickListener;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.countryname.setText(items.get(position).getCountryname());
holder.rank.setText(items.get(position).getRank());
Picasso.with(context)
.load(items.get(position).getFlag())
.into(holder.flag);
holder.flag.setOnClickListener(this);
}
#Override
public int getItemCount() {
return items.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView countryname, rank;
ImageView flag;
public MyViewHolder(View itemView) {
super(itemView);
countryname = (TextView) itemView.findViewById(R.id.capital);
rank = (TextView) itemView.findViewById(R.id.rank);
flag = (ImageView) itemView.findViewById(R.id.flag);
}
#Override
public void onClick(View view) {
if (clickListener != null) clickListener.onClick(view, getAdapterPosition());
}
}
}
On Your Activity / Fragment Implement OnItemClickListener
public class MainActivity extends AppCompatActivity implements OnItemClickListener{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayoutManager layout = new
LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layout );
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
RecAdapter adapter = new RecAdapter(items ,getContext());
adapter.setClickListener(this);
mRecyclerView.setAdapter(adapter );
}
#Override
public void onClick(View view, int position) {
switch(view.getId()) {
}
}
}
i am working on one project in which i have used open source code, but at one point i am stuck, in this code i am using RecyclerView in which onRecycleItemClickListener is already implemented but now i need to implement onItemLongClickListener in existing code
public abstract class BaseRecyclerViewAdapter<T, VH extends BaseClickListenerViewHolder> extends RecyclerView.Adapter<VH> {
private List<T> objectsList;
protected final BaseActivity baseActivity;
protected final LayoutInflater layoutInflater;
protected final Resources resources;
protected QBUser currentQbUser;
// Package private because we need access in BaseViewHolder but not in child classes
OnRecycleItemClickListener<T> onRecycleItemClickListener;
AdapterView.OnItemLongClickListener onItemLongClickListener;
public BaseRecyclerViewAdapter(BaseActivity baseActivity) {
this.baseActivity = baseActivity;
this.layoutInflater = LayoutInflater.from(baseActivity);
resources = baseActivity.getResources();
objectsList = new ArrayList<>();
}
public BaseRecyclerViewAdapter(BaseActivity baseActivity, List<T> objectsList) {
this(baseActivity);
this.objectsList = objectsList;
currentQbUser = AppSession.getSession().getUser();
}
public void setList(List<T> items) {
objectsList = items;
notifyDataSetChanged();
}
public void addItem(T item) {
objectsList.add(item);
notifyItemInserted(objectsList.size() - 1);
}
public void addItem(int position, T item) {
objectsList.add(position, item);
notifyItemInserted(position);
}
public void addAll(Collection<T> collection) {
objectsList.addAll(collection);
notifyItemRangeChanged(objectsList.size() - collection.size(), collection.size());
}
public void removeItem(int position) {
objectsList.remove(position);
notifyItemRemoved(position);
}
public void removeItem(T item) {
int position = objectsList.indexOf(item);
if (position != -1) {
objectsList.remove(item);
notifyItemRemoved(position);
}
}
public void clear() {
objectsList.clear();
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return objectsList.size();
}
public T getItem(int position) {
return objectsList.get(position);
}
public List<T> getAllItems() {
return objectsList;
}
public boolean isEmpty() {
return objectsList.size() == 0;
}
public void setOnRecycleItemClickListener(OnRecycleItemClickListener<T> onRecycleItemClickListener) {
this.onRecycleItemClickListener = onRecycleItemClickListener;
}
protected void displayAvatarImage(String uri, ImageView imageView) {
ImageLoader.getInstance().displayImage(uri, imageView, ImageLoaderUtils.UIL_USER_AVATAR_DISPLAY_OPTIONS);
}
}
You can use this class ItemTouchListenerAdapter in your code to easily add support for both item clicks and long-clicks.
Usage:
recyclerView.addOnItemTouchListener(new ItemTouchListenerAdapter(recyclerView, this));
Code:
public class ItemTouchListenerAdapter extends GestureDetector.SimpleOnGestureListener implements RecyclerView.OnItemTouchListener {
public interface RecyclerViewOnItemClickListener {
void onItemClick(RecyclerView parent, View clickedView, int position);
void onItemLongClick(RecyclerView parent, View clickedView, int position);
}
private RecyclerViewOnItemClickListener listener;
private RecyclerView recyclerView;
private GestureDetector gestureDetector;
public ItemTouchListenerAdapter(RecyclerView recyclerView, RecyclerViewOnItemClickListener listener) {
if (recyclerView == null || listener == null) {
throw new IllegalArgumentException("RecyclerView and Listener arguments can not be null");
}
this.recyclerView = recyclerView;
this.listener = listener;
this.gestureDetector = new GestureDetector(recyclerView.getContext(), this);
}
#Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
gestureDetector.onTouchEvent(motionEvent);
return false;
}
#Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
#Override
public void onShowPress(MotionEvent e) {
View view = getChildViewUnder(e);
if (view != null) {
view.setPressed(true);
}
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
View view = getChildViewUnder(e);
if (view == null) return false;
view.setPressed(false);
int position = recyclerView.getChildPosition(view);
listener.onItemClick(recyclerView, view, position);
return true;
}
public void onLongPress(MotionEvent e) {
View view = getChildViewUnder(e);
if (view == null) return;
int position = recyclerView.getChildPosition(view);
listener.onItemLongClick(recyclerView, view, position);
view.setPressed(false);
}
#Nullable
private View getChildViewUnder(MotionEvent e) {
return recyclerView.findChildViewUnder(e.getX(), e.getY());
}
}
How to implement RecyclerView onItemClick listener as we do with ListView, this is my old Adapter class using ListView:
public class GenreAdapter extends BaseAdapter {
....
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// convert view = design
View v = convertView;
if (v == null) {
holder = new ViewHolder();
v = vi.inflate(Resource, null);
holder.textTitle = (TextView) v.findViewById(R.id.textTitle);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.textTitle.setText(genreArrayList.get(position).getTitle());
v.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putSerializable("data", genreArrayList);
bundle.putInt("current", position);
Intent intent = new Intent(context, MovieActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtras(bundle);
context.startActivity(intent);
}
});
return v;
}
static class ViewHolder {
public TextView textTitle;
}
MainFragment.java:-
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
/* Initialize recycler view */
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
list = new ArrayList<MainPoho>();
adapter = new MainAdapter(getActivity(), list);
mRecyclerView.setAdapter(adapter);
.......
}
And here is my new Adapter class using RecyclerView :
public class MyRecyclerAdapter extends RecyclerView.Adapter<FeedListRowHolder> {
private List<FeedItem> feedItemList;
private Context mContext;
public MyRecyclerAdapter(Context context, List<FeedItem> feedItemList) {
this.feedItemList = feedItemList;
this.mContext = context;
}
#Override
public FeedListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
FeedListRowHolder mh = new FeedListRowHolder(v);
return mh;
}
#Override
public void onBindViewHolder(FeedListRowHolder feedListRowHolder, int i) {
FeedItem feedItem = feedItemList.get(i);
feedListRowHolder.title.setText(Html.fromHtml(feedItem.getTitle()));
}
#Override
public int getItemCount() {
if(feedItemList !=null){
return feedItemList.size();
} else {
return 0;
}
}
public class FeedListRowHolder extends RecyclerView.ViewHolder {
protected TextView title;
public FeedListRowHolder(View view) {
super(view);
this.title = (TextView) view.findViewById(R.id.title);
}
FeedItem.java:-
public class FeedItem {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
first store whole view in your viewHolder:
public class FeedListRowHolder extends RecyclerView.ViewHolder {
protected TextView title;
protected View mRootView;
public FeedListRowHolder(View view) {
super(view);
this.title = (TextView) view.findViewById(R.id.title);
mRootView = view;
}
then set click listener at onBindViewHolder:
#Override
public void onBindViewHolder(FeedListRowHolder feedListRowHolder, int i) {
FeedItem feedItem = feedItemList.get(i);
feedListRowHolder.title.setText(Html.fromHtml(feedItem.getTitle()));
feedListRowHolder.mRootView.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
}
});
}
First you have to implement your own OnItemTouchListener :
static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener){
gestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapUp(MotionEvent e) {
//here get the view that has been touched
View child = recyclerView.findChildViewUnder(e.getX(),e.getY());
//now pass the item and its position to your click listener
if(child!=null && clickListener!=null){
clickListener.onClick(child, recyclerView.getChildPosition(child));
}
return true;
}
#Override
public void onLongPress(MotionEvent e) {
}
});
}
public static interface ClickListener {
public void onClick(View view, int position);
}
#Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
//use the gesture detector to intercept singletap and longtouch events
gestureDetector.onTouchEvent(motionEvent);
return false;
}
#Override
public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
}
}
And then you will have to implement the ClickListener that will be called by the RecyclerTouchListener above :
private RecyclerTouchListener.ClickListener mClickListener = new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, final int position) {
//Do something with your item...
mRecyclerAdapter.getElementAt(position).doSomething();
}
}
I know its a little late but for all those who wander and are not lost. I found this elegant solution here.
So basically you create a ItemClickSupport class like below
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 then in your activity/fragment where you have defined and bind your recyclerView just do the following
//Here the mRecyclerView is the name of the defined recyclerView
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
#Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// do it
}
});
Also, you need to create an ids.xml file inside your res/values folder and define the following inside
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="item_click_support" type="id" />
</resources>
I hope this helps. Still recommend you to go through the article to read more regarding it.