Get the clicked position of carousel with Recycler View and Card View - java

I'm using this CarouselView library.
I have used Recycler View and Card View to create the following UI.
In each card view, I have added this carousel view and contains images inside carousel.
This library has the setImageClickListener that gives the index of each clicked image in each card view.
customCarouselView.setImageClickListener(new ImageClickListener() {
#Override
public void onClick(int position) {
Toast.makeText(SampleCarouselViewActivity.this, "Clicked item: "+ position, Toast.LENGTH_SHORT).show();
}
});
I want to know which image is clicked and from which card that image belongs since there are multiple card-views.
I tried to register the click event in the ImageView and get the adapterPosition of clicked cardview using getAdapterPosition().
fruitImageView.setOnClickListener(new View.OnClickListener() { /*Hits only when another click event (setImageClickListner) is not registered*/
#Override
public void onClick(View view) {
int a = getAdapterPosition(); //gives the index of clicked cardview position.
}
});
When both of the events are registered then only click on ImageView (fruitImageView.setOnClickListener) gets hit, which gives the position of the adapter. I also want to know which image is clicked.
When I remove this ImageView Click listener, then carousel view click customCarouselView.setImageClickListener gets hit which gives the postion of image clicked but not the adapter position.
Are there any work around for this? Please help.
My Adapter Class complete code:
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {
private ArrayList<HomeSalesModel> salesLists;
int[] sampleImages = {R.drawable.album1, R.drawable.album2, R.drawable.album3, R.drawable.album4, R.drawable.album5};
String[] sampleTitles = {"A", "B", "C", "D", "E"};
Context myContext = null;
public GridAdapter(ArrayList<HomeSalesModel> salesLists) {
this.salesLists = salesLists;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
myContext = parent.getContext();
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(GridAdapter.ViewHolder viewHolder, int i) {
viewHolder.tv_country.setText(salesLists.get(i).getTitle());
}
#Override
public int getItemCount() {
return salesLists.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private CarouselView customCarouselView;
private TextView tv_country;
private CardView cardView;
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.grid_card_row, parent, false));
tv_country = (TextView) itemView.findViewById(R.id.tv_country);
customCarouselView = (CarouselView) itemView.findViewById(R.id.customCarouselView);
cardView = (CardView) itemView.findViewById(R.id.card);
customCarouselView.setPageCount(sampleImages.length);
//customCarouselView.setSlideInterval(4000);
customCarouselView.setViewListener(viewListener);
customCarouselView.setImageClickListener(imageClickListner);
}
ViewListener viewListener = new ViewListener() {
#Override
public View setViewForPosition(int position) {
LayoutInflater li = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View customView = li.inflate(R.layout.view_custom, null);
TextView labelTextView = (TextView) customView.findViewById(R.id.labelTextView);
ImageView fruitImageView = (ImageView) customView.findViewById(R.id.fruitImageView);
fruitImageView.setImageResource(sampleImages[position]);
labelTextView.setText(sampleTitles[position]);
fruitImageView.setOnClickListener(new View.OnClickListener() { /*Works when another click event (imageClickListner) is not registered*/
#Override
public void onClick(View view) {
int a = getAdapterPosition(); //gives the index cardview position.
}
});
//labelTextView.setText(salesLists.get(position).getProducts().get(position).getSlug());
return customView;
}
};
ImageClickListener imageClickListner = new ImageClickListener() {
#Override
public void onClick(int position) {
Toast.makeText(myContext, "Clicked item: " + position, Toast.LENGTH_SHORT).show(); //gives index the clicked image.
}
};
}
}

Simply you can get the adapter position inside ImageClickListener.
int postion = getAdapterPosition();

Related

Do not treat position as fixed; only use immediately

I have this error in my code:
Do not treat position as fixed; only use immediately and call holder.getAdapterPosition() to look it up later.
I even used holder.getAdapterPosition() in the position place, but it still keeps crashing the app when I click the items.
MusicAdapter(Context mcontext, ArrayList<MusicFile> mfiles) {
this.mfiles = mfiles;
this.mcontext = mcontext;
}
#Override // androidx.recyclerview.widget.RecyclerView.Adapter
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(this.mcontext).inflate(R.layout.music_items, parent, false));
}
public void onBindViewHolder( final MyViewHolder holder, int position) {
holder.file_name.setText(this.mfiles.get(position).getTitle());
byte[] image = getAlbumArt(this.mfiles.get(position).getPath());
if (image != null) {
Glide.with(this.mcontext).asBitmap().load(image).into(holder.album_art);
} else {
Glide.with(this.mcontext).load((int) R.drawable.ic_launcher_background).into(holder.album_art);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(MusicAdapter.this.mcontext, PlayerActivity.class);
intent.putExtra("position", holder.getAdapterPosition());
MusicAdapter.this.mcontext.startActivity(intent);
}
});
}
#Override // androidx.recyclerview.widget.RecyclerView.Adapter
public int getItemCount() {
return this.mfiles.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
ImageView album_art;
TextView file_name;
LinearLayout linearLayout;
public MyViewHolder(View itemView) {
super(itemView);
this.file_name = (TextView) itemView.findViewById(R.id.music_file_name);
this.album_art = (ImageView) itemView.findViewById(R.id.music_img);
linearLayout = itemView.findViewById(R.id.linear_layout);
}
}
private byte[] getAlbumArt(String uri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(uri);
byte[] art = retriever.getEmbeddedPicture();
retriever.release();
return art;
}
}
Imagine that we have a RecyclerView that will display 10 items so it will create 10 items and call onBindView for those 10 items and pass the positions from 0 to 9, so if you fixed the position by using it to handle user clicks and later you added an item at position 0 and notified the data set that you inserted a new item by notifyItemInserted() the RecyclerView will create a new item with position 0 and pass it to the layout but the pre created ones still have the old positions and if you logged those positions you will have 00123…9 which is not true it should be 0123…10. Here come the power of holder.getAdapterPosition().
#Override
public void onBindViewHolder(#NonNull GalleryViewAdapter holder,final int position) {
Glide.with(context).load(images.get(position)).into(holder.imageView);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, FullImageview.class);
intent.putExtra("image", images.get(holder.getAdapterPosition()));
context.startActivity(intent);
}
});
}
now its fine to use holder.getAdapterPosition for user click event
notice that i used getAdapterPosition to bind data and used getLayoutPosition to tell the user the position of the pressed item.

Inconsistent Background Color Changes in RecyclerView?

I am trying to Change the Background of certain CardViews when the user click and Opens the particular items.
This is achieved, but as I scroll to bottom or top, certain other cards also change their colors. Why is that ? Can u guys please provide a Fix.
Here is my Adapter Code :
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.resources_layout, parent, false);
return new ResourcesAdapter.ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
final ResourcesModel resourcesModel = resourcesModelList.get(position);
holder.book_title.setText(resourcesModel.getBook_title());
holder.book_description.setText(resourcesModel.getBook_description());
holder.book_price.setText(resourcesModel.getBook_price());
Glide.with(context).load(resourcesModel.getBook_image()).placeholder(R.drawable.placeholder).into(holder.book_image);
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, ResourcesDetails.class);
intent.putExtra("Title", resourcesModel.getBook_title());
intent.putExtra("Description", resourcesModel.getBook_description());
intent.putExtra("Price", String.valueOf(resourcesModel.getBook_price()));
intent.putExtra("BookImage", resourcesModel.getBook_image());
intent.putExtra("PDFS", resourcesModel.getPdf());
context.startActivity(intent);
}
});
String k = holder.book_title.getText().toString();
SharedPreferences myPreferences;
SharedPreferences.Editor myEditor;
myPreferences = PreferenceManager.getDefaultSharedPreferences(context);
String name = myPreferences.getString(k, "notWatched");
Log.e("Name Value ADAPTER :", String.valueOf(name));
if (myPreferences.contains(k)) {
holder.cardView.setBackgroundColor(context.getResources().getColor(R.color.color_bought));
}
#Override
public int getItemCount() {
return resourcesModelList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView book_image;
TextView book_title, book_description, book_price, pdfLinks;
Button buy_btn;
MaterialCardView cardView;
ImageView tick;
public ViewHolder(#NonNull View itemView) {
super(itemView);
book_image = itemView.findViewById(R.id.book_img);
book_title = itemView.findViewById(R.id.book_title);
book_description = itemView.findViewById(R.id.book_description);
book_price = itemView.findViewById(R.id.book_price);
cardView = itemView.findViewById(R.id.cardView);
}
if (myPreferences.contains(k)) {
holder.cardView.setBackgroundColor(context.getResources().getColor(R.color.color_bought));
}
You're not setting the background color back to the default if it's not in myPreferences. Because of ViewHolder recycling, you need an } else { case to handle this.

Listener interface isn't working with onClick for cardviews in a recycler view

I have several cardviews on my layout. When one gets clicked it should call my Listener's onClick method which will start EquationsActivity and pass it the position of the card. That is not working. My recyclerFragment is in a tablayout. I've looked and looked and I can't seem to figure out the problem! All suggestions are appreciated!!
My recyclerAdapter:
public class recylcerAdapter extends RecyclerView.Adapter<recylcerAdapter.ViewHolder> {
private Listenerr listener;
private int[] imageIds;
private String[] nameArray;
public interface Listenerr{
void onClick(int position);
}
public static class ViewHolder extends RecyclerView.ViewHolder{
private CardView cardView;
public ViewHolder(CardView v){
super(v);
cardView = v;
}
}
public recylcerAdapter(Context context, String title, Cursor cursor, int[]imageIds, String[]nameArray){
this.imageIds = imageIds;
this.nameArray = nameArray;
}
public void setListener(Listenerr listener){
this.listener = listener;
}
#Override
public recylcerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
//create a new view
CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_main, parent, false);
return new ViewHolder(cardView);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position){
//set the values inside the given view
CardView cardView = holder.cardView;
ImageView imageView = (ImageView) cardView.findViewById(R.id.list_icon);
Drawable drawable = cardView.getResources().getDrawable(imageIds[position]);
imageView.setImageDrawable(drawable);
imageView.setContentDescription(nameArray[position]);
TextView textView = (TextView) cardView.findViewById(R.id.card_text);
textView.setText(nameArray[position]);
cardView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
if(listener != null){
Log.v("hitsOnClick", "It has been hit");
listener.onClick(position);
}
}
});
}
#Override
public int getItemCount(){
//return number of items in the data set
return nameArray.length;
}
}
My recycler fragment code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
new listPop().execute();
RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.recylcler_layout, container, false);
recylcerAdapter RecylcerAdapter =
new recylcerAdapter(getActivity(), "Geometry", cursor, imageArray, names.toArray(new String[names.size()]));
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(RecylcerAdapter);
RecylcerAdapter.setListener(new recylcerAdapter.Listenerr() {
#Override
public void onClick(int position) {
Intent intent = new Intent(getActivity(), EquationsActivity.class);
intent.putExtra(EquationsActivity.POSITION, position);
getActivity().startActivity(intent);
}
});
return recyclerView;
}
EDIT:
with more looking I have found that when I tap on a card, the onClick in the onbindviewholder is not being hit.
Let's setup the click listener when you create new view holder:
public static class ViewHolder extends RecyclerView.ViewHolder{
CardView cardView;
ImageView imageView;
TextView textView;
public ViewHolder(CardView v){
super(v);
cardView = v;
imageView = (ImageView) cardView.findViewById(R.id.list_icon);
textView = (TextView) cardView.findViewById(R.id.card_text);
}
}
And modify a little bit when binding and creating:
#Override
public recylcerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
//create a new view
final CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_main, parent, false);
cardView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
if(listener != null){
Log.v("hitsOnClick", "It has been hit");
listener.onClick((int)cardView.getTag());
}
}
});
return new ViewHolder(cardView);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position){
//set the values inside the given view
Drawable drawable = holder.cardView.getResources().getDrawable(imageIds[position]);
holder.imageView.setImageDrawable(drawable);
holder.imageView.setContentDescription(nameArray[position]);
holder.textView.setText(nameArray[position]);
holder.cardView.setTag(position);
}

RecyclerView ClickListener Not Recognizing Touch

I have created a RecyclerView, and in the Adapter I am hoping to create a ClickListener. I want each item in the RecyclerView to send a unique response after click. In other words, a click is loading a different fragment for each specific RecyclerView item. Right now, the RecyclerView is not responding, as I have logged it and even added a Toast without any luck:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<LatestPoll> mDataSet;
int lastPosition = -1;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
// each data item is just a string in this case
protected TextView pollQuestion;
protected ImageView pollImage;
protected RelativeLayout individualItem;
public ViewHolder(View v) {
super(v);
pollQuestion = (TextView) v.findViewById(R.id.latest_item_question);
pollImage = (ImageView) v.findViewById(R.id.pollThumbNailImage);
individualItem = (RelativeLayout) v.findViewById(R.id.individual_item);
individualItem.setOnClickListener(this);
}
#Override
public void onClick(View v) {
v.getId();
int itemPosition = getLayoutPosition();
String item = String.valueOf(mDataSet.get(itemPosition));
Toast.makeText(getActivity().getApplicationContext(), item, Toast.LENGTH_LONG).show();
Log.v("TESTING", "ITEM CLICKED!");
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<LatestPoll> myDataset) {
mDataSet = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
// set the view's size, margins, paddings and layout parameters
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
//The OutOfBoundsException is pointing here
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.v("ON_BIND", "ON_BINDVIEWHOLDER CALLED");
LatestPoll latestPoll = mDataSet.get(position);
holder.pollQuestion.setText(latestPoll.getQuestion());
Picasso.with(getActivity())
.load(latestPoll.getPollImage())
.fit()
.placeholder(R.drawable.loading_spinnter_white)
.into(holder.pollImage);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataSet.size();
}
}
private void onLoad() {
if (mFragmentListener != null) {
mFragmentListener.onFragmentLoaded();
}
}
public interface FragmentListener {
void onFragmentLoaded();
}
}
You need to set onclick listener to the parent layout inside the onBindViewHolder .
holder.parentID.setOnClickListener(mRecyclerViewListener);
In your View holder
parentID = iteView.findViewById(R.id.parent);

OnItemClickEvent not fired in GridView in android

i m developing an application in which gridview contain list of button...
when i place images instead of button in gridview then onItemClickEvent get fired..but if i place button in gridView then click event not getting callled...i dont know what is the problem...even i m not getting exception..
here is my code...
public class MainMenu extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
GridView gridview = (GridView) findViewById(R.id.mainMenu);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
Toast.makeText(MainMenu.this, "hello" + position, Toast.LENGTH_SHORT).show();
}
});
}
//inner class for adapter
class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c)
{
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
//ImageView imageView;
Button btn;
if (convertView == null) { // if it's not recycled, initialize some attributes
btn=new Button(mContext);
// imageView = new ImageView(mContext);
btn.setLayoutParams(new GridView.LayoutParams(120,120));
// imageView.setLayoutParams(new GridView.LayoutParams(140,140));
//imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
btn.setPadding(10,15, 10,15);
btn.setImeActionLabel("hello",0);// actionId)
// imageView.setPadding(8,8, 8, 8);
} else
{
btn=(Button)convertView;
//imageView=(ImageView)convertView;
}
btn.setBackgroundResource(mThumbIds[position]);
//imageView.setImageResource(mThumbIds[position]);
//return imageView;
return btn;
}
// references to our images
private Integer[] mThumbIds =
{
R.drawable.pantrylocator_icon,
R.drawable.volunteeropportunity_icon,
R.drawable.volunteerlocator_icon,
R.drawable.volunteermanagement_icon,
R.drawable.donationform_icon,
R.drawable.donationviamsg_icon,
R.drawable.donationvideo_icon,
R.drawable.virtualfooddrive_icon,
R.drawable.newevent_icon,
R.drawable.pressrelease_icon,
R.drawable.volunteerphotos_icon,
R.drawable.aboutus_icon,
};
}
}
The button has its own OnClickListener:
public View getView(int position, View convertView, ViewGroup parent) {
//ImageView imageView;
Button btn;
if (convertView == null) { // if it's not recycled, initialize some attributes
btn=new Button(mContext);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
// imageView = new ImageView(mContext);
btn.setLayoutParams(new GridView.LayoutParams(120,120));
// imageView.setLayoutParams(new GridView.LayoutParams(140,140));
//imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
btn.setPadding(10,15, 10,15);
btn.setImeActionLabel("hello",0);// actionId)
// imageView.setPadding(8,8, 8, 8);
} else
{
btn=(Button)convertView;
//imageView=(ImageView)convertView;
}
btn.setBackgroundResource(mThumbIds[position]);
//imageView.setImageResource(mThumbIds[position]);
//return imageView;
return btn;
}
In your ImageAdapter-> getView method add the following line before returning newly created "convertView"
convertView.setClickable(false);
convertView.setFocusable(false);
If any of the views in gridview are clickable then they will block the grid's ItemClick listener from responding.
There is no onclick event written for the Buttons you are adding. Write code for the buttons to handle the click event! let us know then.
i have fece this problem also but finally got the solution i have follow the above suggession
and define button click event in base adapter class like as
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v;
if(convertView==null){
LayoutInflater li = LayoutInflater.from(mContext);
v = li.inflate(R.layout.icon, null);
tv = (Button)v.findViewById(R.id.icon_text);
iv = (ImageView)v.findViewById(R.id.icon_image);
iv.setImageResource(mThumbIds[position]);
tv.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(mContext, "vim", Toast.LENGTH_LONG).show();
}
});
}
else
{
v = (View)convertView;
}
return v;
}
gridview = (GridView) findViewById(R.id.gameGrid);
gridview.setAdapter(ia);
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Ur Code here
}
Add click events for the button added in gridView
Here's the cleanest way to do it: call performItemClick() on the GridView from within each button's click listener. That way you can still use the GridView's onItemClickListener like normal.
#Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
...
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((GridView) parent).performItemClick(v, position, 0);
}
});
}
http://www.migapro.com/click-events-listview-gridview/
I have solved my problem as i define button click event in base adpter class and my problem is solved......

Categories