I have a recycler view that has many items that I want to intent from every item to specific activities. I tried many ways but all fail to intent to the activities.
This is the adapter:
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
private ArrayList<String> itemsData;
public ItemsAdapter(ArrayList<String> itemsData) {
this.itemsData = itemsData;
}
#Override
public ItemsAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent,
int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, null);
final ViewHolder viewHolder = new ViewHolder(itemLayoutView);
itemLayoutView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String word = viewHolder.txtViewTitle.getText().toString();
Toast.makeText(parent.getContext(),word,Toast.LENGTH_LONG).show();
}
});
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.txtViewTitle.setText(itemsData.get(position));
viewHolder.imgViewIcon.setImageResource(R.drawable.imsge_profile);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtViewTitle;
public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
}
}
#Override
public int getItemCount() {
return itemsData.size();
}
}
This is main_activity:
public class MainActivity extends ActionBarActivity {
Toolbar tBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tBar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(tBar);
getSupportActionBar().setTitle("AdroidCode Recycler View");
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
ArrayList<String> listItems = new ArrayList<String>();
listItems.add("Tom");
listItems.add("Hamdy");
listItems.add("John");
listItems.add("Hasna");
listItems.add("Fadi");
listItems.add("Samer");
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ItemsAdapter mAdapter = new ItemsAdapter(listItems);
recyclerView.setAdapter(mAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
}
}
i tried this instead of the Toast but dosent work
#Override
public void onClick(View v) {
final Intent intent;
switch (getPostion()){
case 0:
intent = new Intent(context, FirstActivity.class);
break;
case 1:
intent = new Intent(context, SecondActivity.class);
break;
...
default:
intent = new Intent(context, DefaultActivity.class);
break;
}
context.startActivity(intent);
}
new adapter
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {
public static class PersonViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView personName;
TextView personAge;
ImageView personPhoto;
public PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
personName = (TextView)itemView.findViewById(R.id.person_name);
personAge = (TextView)itemView.findViewById(R.id.person_age);
personPhoto = (ImageView)itemView.findViewById(R.id.person_photo);
recyclerview.addOnItemTouchListener(new RecyclerItemClickListener(
context, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
// TODO Auto-generated method stub
final Intent intent;
switch (position) {
case 0:
intent = new Intent(context, secoundActivity.class);
break;
}
}
));
}}
}
List<Person> persons;
RVAdapter(List<Person> persons){
this.persons = persons;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
PersonViewHolder pvh = new PersonViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
personViewHolder.personName.setText(persons.get(i).name);
personViewHolder.personAge.setText(persons.get(i).age);
personViewHolder.personPhoto.setImageResource(persons.get(i).photoId);
}
#Override
public int getItemCount() {
return persons.size();
}
}
RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// do whatever
}
})
);
I think you need to add click listener when you intialilize recycler view.Try these
public class RecyclerItemClickListener implements
RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context,
OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
#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) {
}
}
You can not direct use onclick. I have found a solution and it's works for me. Try it. I hope it will helps you.
Step 1: Fist add this RecyclerItemClickListener class to your package.
public class RecyclerItemClickListener implements
RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context,
OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
#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) {
}
}
Step 2: Now use onclick method. this gives you position of item clicked. Once you get position than you can use it as per your requirement.
recyclerview.addOnItemTouchListener(new RecyclerItemClickListener(
context, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, position + "",
Toast.LENGTH_SHORT).show();
final Intent intent;
switch (position) {
case 0:
Toast.makeText(context, "case 0",
Toast.LENGTH_SHORT).show();
intent = new Intent(context,FirstActivity.class);
break;
case 1:
Toast.makeText(context, "case 1",
Toast.LENGTH_SHORT).show();
intent = new Intent(context,SecondActivity.class);
break;
default:
intent = new Intent(context,DefaultActivity.class);
break;
}
}));
Related
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()) {
}
}
}
So i need to start an activity when i click on different rows of recyclerview. I just cant figure out how I tried this code
but seems to be not working
class MyViewholder extends RecyclerView.ViewHolder implements View.OnClickListener{
private final Context context;
public MyViewholder(View itemView) {
super(itemView);
context = itemView.getContext();
}
#Override
public void onClick(View view) {
final Intent intent;
switch (getAdapterPosition()){
case 0:
intent = new Intent(context, CalendarControllerFrancisco.class);
break;
case 1:
intent = new Intent(context, CalendarControllerB.class);
break;
case 2:
intent = new Intent(context, CalendarControllerNa.class);
break;
default:
intent = new Intent(context, CalendarController.class);
break;
}
context.startActivity(intent);
public class LocationAdapter extends RecyclerView.Adapter {
private ArrayList<LocationModel> dataSet;
Boolean check = false;
public class MyViewHolder extends RecyclerView.ViewHolder {
//private final Context context;
TextView locat;
public MyViewHolder(View itemView) {
super(itemView);
// context = itemView.getContext();
this.locat = (TextView)itemView.findViewById(R.id.wordtext);
}
}
public LocationAdapter(ArrayList<LocationModel> data) {
this.dataSet = data;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view_row,parent,false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
TextView word1 = holder.locat;
word1.setText(dataSet.get(position).getLocations());
}
#Override
public int getItemCount() {
return dataSet.size();
}
You need add setOnClickListener event for one component.
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
TextView word1 = holder.locat;
word1.setText(dataSet.get(position).getLocations());
word.setOnClickListener(holder);
}
RecyclerItemClickListener
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
#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 false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
Define ClickListener as same as ListView onItemClickListener
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(context, new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// TODO Handle item click
}
})
);
This is wrong:
#Override
public void onClick(View view) {
final Intent intent;
switch (getAdapterPosition()){
case 0:
intent = new Intent(context, CalendarControllerFrancisco.class);
break;
case 1:
intent = new Intent(context, CalendarControllerB.class);
break;
case 2:
intent = new Intent(context, CalendarControllerNa.class);
break;
default:
intent = new Intent(context, CalendarController.class);
break;
}}
The ViewHolder is a container used by the adapter to fill in item data arbitrarily depending on the RecyclerView items to be displayed. Hence it shouldn't have access to any position data from the item list to identify itself. You are confusing concepts.
Try replacing the above with something like:
class MyViewholder extends RecyclerView.ViewHolder implements View.OnClickListener {
private final Context context;
int type;
public MyViewholder(View itemView) {
super(itemView);
context = itemView.getContext();
}
public void bind(int type) {
this.type = type;
}
#Override
public void onClick(View view) {
final Intent intent;
switch (this.type){
case 0:
intent = new Intent(context, CalendarControllerFrancisco.class);
break;
case 1:
intent = new Intent(context, CalendarControllerB.class);
break;
case 2:
intent = new Intent(context, CalendarControllerNa.class);
break;
default:
intent = new Intent(context, CalendarController.class);
break;
}
}
}
Then, in your Adapter use onBindViewHolder callback to access the item collection and assign their type for the creation of every item.
Something like:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.bind(myItemList.get(position).type());
}
I have this adapter class where I have an object with a list in it.
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductViewHolder> {
private Context context;
private Shop shop;
public ProductAdapter(Context context, Shop shop) {
this.context = context;
this.shop = shop;
}
#Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.product_row, parent, false);
return new ProductViewHolder(v);
}
#Override
public void onBindViewHolder(ProductViewHolder holder, int position) {
holder.tvProductTitle.setText(shop.products.get(position).getTitle());
holder.tvProductDescription.setText(shop.products.get(position).getDescription());
Glide.with(context)
.load(shop.products.get(position).getImageUrl())
.placeholder(android.R.drawable.ic_menu_upload_you_tube)
.error(android.R.drawable.stat_notify_error)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.into(holder.ivProduct);
}
#Override
public int getItemCount() {
if (shop.products != null) {
return shop.products.size();
}
return 0;
}
public static class ProductViewHolder extends RecyclerView.ViewHolder {
private TextView tvProductTitle, tvProductDescription;
private ImageView ivProduct;
public ProductViewHolder(View itemView) {
super(itemView);
tvProductTitle = (TextView) itemView.findViewById(R.id.tvProductTitle);
tvProductDescription = (TextView) itemView.findViewById(R.id.tvProductDescription);
ivProduct = (ImageView) itemView.findViewById(R.id.ivProduct);
}
}
public interface ClickListener {
void onClick(View v, int position);
void onLongClick(View v, int position);
}
public static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ProductAdapter.ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ProductAdapter.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) {
}
}
I use this adapter in my fragment where I can click an item from the recyclerview which will open another activity with the selected product and it's parametars. Instead of clicking the whole item, I would like to click on part of it (lets say imageview) which will do the same as it is doing now. But, I would also like to put a checkbox in the recyclerview item itself which will have different function. At the moment, I can't use an intent in the adapter class. The way it is set up now I can only click the whole item. How can I make it work like I explained above?
public class ProductsFragment extends android.support.v4.app.Fragment {
private RecyclerView rvProduct;
private RecyclerView.LayoutManager layoutManager;
private ProductAdapter productAdapter;
public static ProductsFragment newInstance(Bundle args) {
ProductsFragment fragment = new ProductsFragment();
fragment.setArguments(args);
return fragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_products, container, false);
rvProduct = (RecyclerView) v.findViewById(R.id.rvProduct);
rvProduct.setHasFixedSize(true);
layoutManager = new GridLayoutManager(getContext(), 2);
rvProduct.setLayoutManager(layoutManager);
Bundle bundle = getArguments();
final Shop shop = (Shop) bundle.getSerializable("shop");
productAdapter = new ProductAdapter(getContext(), shop);
rvProduct.setAdapter(productAdapter);
productAdapter.notifyDataSetChanged();
rvProduct.addOnItemTouchListener(new ProductAdapter.RecyclerTouchListener(getContext(), rvProduct, new ProductAdapter.ClickListener() {
#Override
public void onClick(View v, int position) {
Intent details = new Intent(getContext(), ProductDetailsActivity.class);
details.putExtra("product", shop.products.get(position));
startActivity(details);
}
#Override
public void onLongClick(View v, int position) {
}
}));
return v;
}
}
EDIT:
I've managed to do this, please tell me if this is right and efficient way:
holder.tvProductTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context, ProductDetailsActivity.class);
i.putExtra("product", shop.products.get(position));
context.startActivity(i);
}
});
The way you doing it is not correct.
As your onBindViewHolder will be called repeatedly as you scroll through the list, every time a new listener will be set.
Instead you should set the listeners in the ViewHolder class of Adapter. And use getAdapterPosition() method to get the position of item clicked.
For example:
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductViewHolder> {
private Context context; private Shop shop;
public ProductAdapter(Context context, Shop shop) {
this.context = context;
this.shop = shop;
}
#Override public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.product_row, parent, false);
return new ProductViewHolder(v);
}
#Override public void onBindViewHolder(ProductViewHolder holder, int position) {
holder.tvProductTitle.setText(shop.products.get(position).getTitle());
holder.tvProductDescription.setText(shop.products.get(position).getDescription());
Glide.with(context) .load(shop.products.get(position).getImageUrl()) .placeholder(android.R.drawable.ic_menu_upload_you_tube) .error(android.R.drawable.stat_notify_error) .diskCacheStrategy(DiskCacheStrategy.RESULT) .into(holder.ivProduct);
}
#Override public int getItemCount()
{
if (shop.products != null) {
return shop.products.size();
} return 0;
}
public static class ProductViewHolder extends RecyclerView.ViewHolder {
private TextView tvProductTitle, tvProductDescription;
private ImageView ivProduct;
public ProductViewHolder(View itemView)
{
super(itemView);
tvProductTitle = (TextView) itemView.findViewById(R.id.tvProductTitle);
tvProductDescription = (TextView) itemView.findViewById(R.id.tvProductDescription);
ivProduct = (ImageView) itemView.findViewById(R.id.ivProduct);
// Set onclickListener on image
ivProduct.setOnCliCkListener(new onClickListener(){
#Override
public void onClick(View v){
Intent i = new Intent(context, ProductDetailsActivity.class);
i.putExtra("product",
shop.products.get(getAdapterPosition()));
context.startActivity(i);
}
}
}
}
public interface ClickListener {
void onClick(View v, int position);
void onLongClick(View v, int position);
}
}
You can add click listeners to each respective view of the inflated item in public onBindViewHolder. Did you consider that?
Edit: Ok it's what you did. I don't know about the efficiency though, but this is the way I would do it.
Please help me with a problem. The problem is that I need to get the card position to convey this position to another Activity. I need to transfer this position when I pressed the button on the card. How to get the card position?
RVAdapter.java
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {
private final static String myLog = "myLog";
List<ItemsOfRow> items;
private Context context;
RVAdapter(List<ItemsOfRow> items, Context context) {
this.items = items;
this.context = context;
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view, viewGroup, false);
PersonViewHolder pvh = new PersonViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
personViewHolder.imgGroupImage.setImageBitmap(items.get(i).getTitleImage());
personViewHolder.txtTitleGroup.setText(items.get(i).getTitleName());
personViewHolder.txtContentGroup.setText(items.get(i).getTitleContent());
personViewHolder.btnShare.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, items.get(????).getTitleContent());
sendIntent.setType("text/plain");
context.startActivity(sendIntent);
}
});
personViewHolder.btnLearnMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, QuoteActivity.class);
intent.putExtra("title",items.get(?????).getTitleName());
intent.putExtra("positionGroup", ?????? + "");
view.getContext().startActivity(intent);
}
});
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public static class PersonViewHolder extends RecyclerView.ViewHolder{
CardView cv;
TextView txtTitleGroup;
TextView txtContentGroup;
ImageView imgGroupImage;
Button btnShare;
Button btnLearnMore;
PersonViewHolder(final View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
imgGroupImage = (ImageView) itemView.findViewById(R.id.img_group_image);
txtTitleGroup = (TextView) itemView.findViewById(R.id.txt_title_group);
txtContentGroup = (TextView) itemView.findViewById(R.id.txt_content_group);
btnShare = (Button) itemView.findViewById(R.id.btn_share_group);
btnLearnMore = (Button) itemView.findViewById(R.id.btn_learn_more);
}
}
}
You can use method getAdapterPosition() of your viewHolder
The second parameter int i of onBindViewHolder() is actually the position of the card that is going to be created. You can just pass i to your intent.
In your onBindViewHolder
#Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
/* rest of your code */
personViewHolder.btnLearnMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, QuoteActivity.class);
intent.putExtra("title",items.get(i).getTitleName());
intent.putExtra("positionGroup", i);
view.getContext().startActivity(intent);
}
});
}
recyclerView.getChildLayoutPosition(child)
This will return the position of the view in the recycler view.
Here child is the View that registers the click event.
A full click listener code can be similar to:
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.getChildLayoutPosition(child));
}
}
});