Checkbox changing state when scrolling in recyclerview - android

I made a small app that shows me a list of all the apps installed to my phone I want to add a check box to every cardview so that I can mark my favorite apps and other classification. The problem is when scrolling through the list the state of the checkbox change ex. I checked chrome and when I scrolled down then scrolled up chrome is not marked and a random app is checked. I searched for other question related to this problem but none of those solutions worked for me.
updated version of appsadapter.java
public class AppsAdapter extends RecyclerView.Adapter<AppsAdapter.ViewHolder>{
private final SparseBooleanArray array=new SparseBooleanArray();
public class ViewHolder extends RecyclerView.ViewHolder{
public CardView cardView;
public ImageView imageView;
public TextView textView_App_Name;
public CheckBox checkBox;
public ViewHolder (View view){
super(view);
checkBox = (CheckBox) view.findViewById(R.id.chckbox);
cardView = (CardView) view.findViewById(R.id.card_view);
imageView = (ImageView) view.findViewById(R.id.imageview);
textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
//textView_App_Package_Name = (TextView) view.findViewById(R.id.Apk_Package_Name);
}
}
private Context context1;
private List<String> stringList;
public AppsAdapter(Context context, List<String> list){
context1 = context;
stringList = list;
}
//viewholder initialized
#Override
public AppsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view2 = LayoutInflater.from(context1).inflate(R.layout.cardview_layout,parent,false);
ViewHolder viewHolder = new ViewHolder(view2);
return viewHolder;
}
//DATA IS BOUND TO VIEWS
private SparseBooleanArray sba = new SparseBooleanArray();
#Override
public void onBindViewHolder(ViewHolder viewHolder,final int position){
viewHolder.setIsRecyclable(false);
ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
final String ApplicationPackageName = (String) stringList.get(position);
//calling apps name and icon
String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);
//setting app name and icon for every card
viewHolder.textView_App_Name.setText(ApplicationLabelName);
viewHolder.imageView.setImageDrawable(drawable);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sba.put(position, !sba.get(position));
notifyDataSetChanged();
}
});
viewHolder.checkBox.setChecked(sba.get(position));
/*Adding click listener on CardView to open clicked application directly from here
viewHolder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = context1.getPackageManager().getLaunchIntentForPackage(ApplicationPackageName);
if(intent != null){
context1.startActivity(intent);
}
else {
Toast.makeText(context1,ApplicationPackageName + " Error, Please Try Again.", Toast.LENGTH_LONG).show();
}
}
});*/
}
#Override
public int getItemCount(){
return stringList.size();
}
}

That is because in the recycler view, item views are re used to show new data. You have to add a variable in your data item that holds the state of the checkbox at a particular position. Then in the onBindViewHolder you can check the value of the tracking variable and set the state of the checkbox like yourCheckbox.setchecked(item.getSelected()) set the tracking variable value in the onCheckChanged method

set view onclicklistener in BindViewholder method so you can use the current position of item as in
private SparseBooleanArray sba = new SparseBooleanArray();
#Override
public void onBindViewHolder(ViewHolder viewHolder,final int position){
viewHolder.setIsRecyclable(false);
ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
final String ApplicationPackageName = (String) stringList.get(position);
//calling apps name and icon
String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);
//setting app name and icon for every card
viewHolder.textView_App_Name.setText(ApplicationLabelName);
viewHolder.imageView.setImageDrawable(drawable);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sba.put(position,!sba.get(position));
notifyDataSetChanged();
}
});
viewHolder.checkBox.setChecked(sba.get(position));
}

Set checkbox inside checkBox onclickListener
holder.mCheckBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CheckBox checkBox = (CheckBox) view;
mDataModel = (DataModel) checkBox.getTag();
mDataModel.setChecked(checkBox.isChecked());
arrayList.get(position).setChecked(checkBox.isChecked());
}
});

Related

How to use notifyDataSetChanged and setText inside a same onclick method

I need to use notifyDataSetChanged() and setText a value to a TextView inside onBindViewHolder. I tried to use both inside onClick method,
qtyIncrease.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
quantityText.setText("Good");
toatlPriceText.setText("250");
notifyDataSetChanged();
}
});
My adapter class,
public class CartCardviewAdapter extends RecyclerView.Adapter<CartCardviewAdapter.MyViewHolder> {
private Context context;
private ArrayList<CartCardviewModel> dataSet;
private ShoppingCart shoppingCart;
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView itemNameText, itemTypeText, itemDescText, unitPriceText, toatlPriceText, quantityText;
ImageView itemImage, removeIcon, qtyIncrease, qtyDecrease;
public MyViewHolder(final View itemView) {
super(itemView);
this.itemNameText = (TextView) itemView.findViewById(R.id.item_name_text);
this.itemTypeText = (TextView) itemView.findViewById(R.id.item_type_text);
this.itemDescText = (TextView) itemView.findViewById(R.id.item_desc_text);
this.unitPriceText = (TextView) itemView.findViewById(R.id.item_unit_price_text);
this.toatlPriceText = (TextView) itemView.findViewById(R.id.item_total_price_text);
this.quantityText = (TextView) itemView.findViewById(R.id.item_quantity_text);
this.itemImage = (ImageView) itemView.findViewById(R.id.item_image);
this.removeIcon = (ImageView) itemView.findViewById(R.id.item_remove_icon);
this.qtyIncrease = (ImageView) itemView.findViewById(R.id.cart_quantity_increase);
this.qtyDecrease = (ImageView) itemView.findViewById(R.id.cart_quantity_decrease);
}
}
public CartCardviewAdapter(ArrayList<CartCardviewModel> data) {
this.dataSet = data;
}
#Override
public CartCardviewAdapter.MyViewHolder onCreateViewHolder(final ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cart_cardview_layout, parent, false);
CartCardviewAdapter.MyViewHolder myViewHolder = new CartCardviewAdapter.MyViewHolder(view);
context = parent.getContext();
return myViewHolder;
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onBindViewHolder(final CartCardviewAdapter.MyViewHolder holder, final int listPosition) {
shoppingCart = MainActivity.getCartInstance().getCart();
TextView itemNameText = holder.itemNameText;
TextView itemTypeText = holder.itemTypeText;
TextView itemDescText = holder.itemDescText;
TextView unitPriceText = holder.unitPriceText;
final TextView toatlPriceText = holder.toatlPriceText;
final TextView quantityText = holder.quantityText;
ImageView itemImage = holder.itemImage;
ImageView removeIcon = holder.removeIcon;
ImageView qtyIncrease = holder.qtyIncrease;
ImageView qtyDecrease = holder.qtyDecrease;
itemNameText.setText(dataSet.get(listPosition).getItemName());
itemTypeText.setText(dataSet.get(listPosition).getItemType());
itemDescText.setText(dataSet.get(listPosition).getItemDescription());
unitPriceText.setText(String.valueOf(dataSet.get(listPosition).getUnitPrice()));
toatlPriceText.setText(String.valueOf(dataSet.get(listPosition).getTotalPrice()));
String qty;
if (dataSet.get(listPosition).getItemQuantity() < 9) {
qty = "0" + String.valueOf(dataSet.get(listPosition).getItemQuantity());
} else {
qty = String.valueOf(dataSet.get(listPosition).getItemQuantity());
}
quantityText.setText(qty);
Picasso.with(context).load(dataSet.get(listPosition).getItemImageUrl()).into(itemImage);
removeIcon.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(v.getContext(), String.valueOf(listPosition), Toast.LENGTH_SHORT).show();
shoppingCart.removeItem(listPosition);
dataSet.remove(listPosition);
notifyDataSetChanged();
}
});
qtyIncrease.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
shoppingCart.increaseItemQuantity(listPosition);
quantityText.setText(String.valueOf(shoppingCart.getItemQuantity(listPosition)));
toatlPriceText.setText(String.valueOf(shoppingCart.getTotalPrice(listPosition)));
notifyDataSetChanged();
}
});
qtyDecrease.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (shoppingCart.getItemQuantity(listPosition) == 1) {
Toast.makeText(v.getContext(), "Already Minimum Quantity is Reached", Toast.LENGTH_SHORT).show();
} else {
shoppingCart.decreaseItemQuantity(listPosition);
quantityText.setText(String.valueOf(shoppingCart.getItemQuantity(listPosition)));
toatlPriceText.setText(String.valueOf(shoppingCart.getTotalPrice(listPosition)));
notifyDataSetChanged();
}
}
});
}
#Override
public int getItemCount() {
return dataSet.size();
}
}
but both don't work at a click. I need to go back and come to see the affected change. I could't understand the problem. Please help me
First This line #RequiresApi(api = Build.VERSION_CODES.N) is for too restrictive, take into consideration lower levels down the line. There are many ways to approach this problem, first you can use a RecyclerView.OnItemTouchListener to the recycler hosting the adaptor. Here is a detailed tutorial describing single and long click , Link. Another approach is the interface segration principle.
In the adaptor class, create a interface, with one method
method signature (View view, int position), depicts a view clicked with repective position in adaptor.
Declare a instance of this interface in the adaptor
Modify the contructor to accept a interface of that type
Let the class with the recylcler view instance implement above interface
Pass a new instance to the contructor in the implemented class
Then in the overriden method, change your text and call adaptor.notifyItemChanged(position)
oh, also, in the adaptor class where the views gets init , set onClicklistener with the interface instance.
This tutorial describes exactly the above in great detail,link.
Your welcome!
the click won't trigger from there , you need to set the click listener of the Image View "qtyIncrease" inside the ViewHolder not in "OnBindViewHolder"
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView itemNameText, itemTypeText, itemDescText, unitPriceText, toatlPriceText, quantityText;
ImageView itemImage, removeIcon, qtyIncrease, qtyDecrease;
public MyViewHolder(final View itemView) {
super(itemView);
this.itemNameText = (TextView) itemView.findViewById(R.id.item_name_text);
this.itemTypeText = (TextView) itemView.findViewById(R.id.item_type_text);
this.itemDescText = (TextView) itemView.findViewById(R.id.item_desc_text);
this.unitPriceText = (TextView) itemView.findViewById(R.id.item_unit_price_text);
this.toatlPriceText = (TextView) itemView.findViewById(R.id.item_total_price_text);
this.quantityText = (TextView) itemView.findViewById(R.id.item_quantity_text);
this.itemImage = (ImageView) itemView.findViewById(R.id.item_image);
this.removeIcon = (ImageView) itemView.findViewById(R.id.item_remove_icon);
this.qtyIncrease = (ImageView) itemView.findViewById(R.id.cart_quantity_increase);
this.qtyDecrease = (ImageView) itemView.findViewById(R.id.cart_quantity_decrease);
qtyIncrease.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
quantityText.setText("Good");
toatlPriceText.setText("250");
notifyDataSetChanged();
}
});
}

OnClick for item in RecyclerView

I am witnessing a wierd behavior of RecyclerView. so I have set an OnClickListener in the ViewHolder on a Button which is meant to do 3 things, when the user clicks:
Add the current item's data to an ArrayList [displayed on a different Fragment]
Display a Toast to the user.
modify the UI of the selected item. [i.e setVisibility of Button to View.INVISIBLE etc..]
now, while the first two tasks of the OnClickListener are fulfilled successfully and apply only to the selected item, the third one which is meant to modify the UI of the selected item only, instead gets also applied to each 9th Item on the RecyclerView.
How do I prevent this behavior?
Why is this behavior occurring with the 3rd task only?
i.e from previous answers on this. particular topic that I saw, I got the notion that it's better to insert the OnClickListener in the ViewHolder rather then putting it in onBindViewHolder, which did not solve the issue. I have followed other suggestions on stackOverflow and all failed.
Here is my code:
static class ItemsRecyclerAdapter extends RecyclerView.Adapter<ItemsRecyclerAdapter.ItemsViewHolder>{
FragmentActivity fragmentActivity;
List<ProductItem> data;
LayoutInflater inflater;
private int id;
private int shopCode;
public ItemsRecyclerAdapter(List<ProductItem> data, FragmentActivity fragmentActivity, int id, int shopCode) {
this.fragmentActivity = fragmentActivity;
this.data = data;
this.inflater = LayoutInflater.from(fragmentActivity);
this.id = id;
this.shopCode = shopCode;
}
#Override
public ItemsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = inflater.inflate(R.layout.pricing_item, parent, false);
return new ItemsViewHolder(v);
}
#Override
public void onBindViewHolder(final ItemsViewHolder holder, int position) {
ProductItem itemPrice = data.get(position);
holder.productName.setText(itemPrice.getProductName());
holder.quantity.setText(itemPrice.getProductQuantity());
holder.tvPrice.setText(itemPrice.getproductPrice());
Picasso.with(fragmentActivity).load(itemPrice.getThumbUrl()).into(holder.imgProduct);
}
#Override
public int getItemCount() {
return data.size();
}
class ItemsViewHolder extends RecyclerView.ViewHolder{
TextView productName, quantity, tvPrice;
ImageView imgProduct;
Button btnAddToBasket, btnAdd, btnRemove;
Typeface myCustomFont = Typeface.createFromAsset(fragmentActivity.getAssets(), "fonts/Assistant-SemiBold.ttf");
public ItemsViewHolder(View itemView) {
super(itemView);
productName = (TextView) itemView.findViewById(R.id.productName);
quantity = (TextView) itemView.findViewById(R.id.manufacturer);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
imgProduct = (ImageView) itemView.findViewById(R.id.imgProduct);
btnAddToBasket = (Button) itemView.findViewById(R.id.btnAddToBasket);
btnAdd = itemView.findViewById(R.id.btnAdd);
btnRemove = itemView.findViewById(R.id.btnRemove);
btnAdd.setVisibility(View.INVISIBLE);
btnRemove.setVisibility(View.INVISIBLE);
quantity.setTypeface(myCustomFont);
productName.setTypeface(myCustomFont);
tvPrice.setTypeface(myCustomFont);
Typeface fontAwesomeBasketIcon = Typeface.createFromAsset(fragmentActivity.getAssets(), "fontawesome-webfont.ttf");
btnAddToBasket.setTypeface(fontAwesomeBasketIcon);
btnAdd.setTypeface(fontAwesomeBasketIcon);
btnRemove.setTypeface(fontAwesomeBasketIcon);
btnAddToBasket.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
MyBasketFragment.myBasketList
.add(new ProductItem(data.get(pos).getProductName(), data.get(pos).getProductQuantity(),
data.get(pos).getproductPrice(), data.get(pos).getThumbUrl(), id, shopCode));
btnAddToBasket.setOnClickListener(null);
Toast.makeText(fragmentActivity, "New product..", Toast.LENGTH_SHORT).show();
btnAdd.setVisibility(View.VISIBLE);
btnRemove.setVisibility(View.VISIBLE);
}
});
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ItemsFragment.atomic.incrementAndGet();
btnAddToBasket.setText(String.valueOf(atomic.get()));
}
});
}
}
}
On every Click of an item, I assign a boolean in the instantiated object to true and and then I run notifyDataSetChanged() which. updates all items with data objects which have a boolean true. this way I'm ensuring that only the selected object will be updated.
It looks something like this:
ViewHolder
class ItemsViewHolder extends RecyclerView.ViewHolder {
TextView productName, quantity, tvPrice;
ImageView imgProduct;
Button btnAddToBasket, btnAdd, btnRemove;
Typeface myCustomFont = Typeface.createFromAsset(fragmentActivity.getAssets(), "fonts/Assistant-SemiBold.ttf");
public ItemsViewHolder(View itemView) {
super(itemView);
productName = (TextView) itemView.findViewById(R.id.productName);
quantity = (TextView) itemView.findViewById(R.id.manufacturer);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
imgProduct = (ImageView) itemView.findViewById(R.id.imgProduct);
btnAddToBasket = (Button) itemView.findViewById(R.id.btnAddToBasket);
btnAdd = itemView.findViewById(R.id.btnAdd);
btnRemove = itemView.findViewById(R.id.btnRemove);
btnAdd.setVisibility(View.INVISIBLE);
btnRemove.setVisibility(View.INVISIBLE);
quantity.setTypeface(myCustomFont);
productName.setTypeface(myCustomFont);
tvPrice.setTypeface(myCustomFont);
Typeface fontAwesomeBasketIcon = Typeface.createFromAsset(fragmentActivity.getAssets(), "fontawesome-webfont.ttf");
btnAddToBasket.setTypeface(fontAwesomeBasketIcon);
btnAdd.setTypeface(fontAwesomeBasketIcon);
btnRemove.setTypeface(fontAwesomeBasketIcon);
}
public void bind(final ProductItem item) {
btnAddToBasket.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
item.clicked = true;
item.atomic.incrementAndGet();
Toast.makeText(fragmentActivity, "New product..", Toast.LENGTH_SHORT).show();
notifyDataSetChanged();
MyBasketFragment.myBasketList
.add(new ProductItem(item.getProductName(), item.getProductQuantity(),
item.getproductPrice(), item.getThumbUrl(), id, shopCode));
}
});
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ItemsFragment.atomic.incrementAndGet();
btnAddToBasket.setText(String.valueOf(atomic.get()));
}
});
}
}
onBindViewHolder
#Override
public void onBindViewHolder(final ItemsViewHolder holder, final int position) {
ProductItem itemPrice = data.get(position);
holder.productName.setText(itemPrice.getProductName());
holder.quantity.setText(itemPrice.getProductQuantity());
holder.tvPrice.setText(itemPrice.getproductPrice());
Picasso.with(fragmentActivity).load(itemPrice.getThumbUrl()).into(holder.imgProduct);
holder.bind(itemPrice);
if(itemPrice.clicked){
holder.btnAddToBasket.setOnClickListener(null);
holder.btnAddToBasket.setText(String.valueOf(atomic.get()));
holder.btnAdd.setVisibility(View.VISIBLE);
holder.btnRemove.setVisibility(View.VISIBLE);
} else {
holder.btnAddToBasket.setText("\uf291");
holder.btnAdd.setVisibility(View.INVISIBLE);
holder.btnRemove.setVisibility(View.INVISIBLE);
}
}
I think getAdapterPosition() is causing the problem. Please, try creating a new int attribute position in the viewholder, onBindViewHolder pass the the position to the viewholder, holder.position = position, and in your viewholder use the position, so will be int pos = position instead of getAdapterPosition()

Recyclerview item click not always work and sometimes can work but with more more click (don't know how many click)

Recyclerview item click not always work and sometimes can work but with more more click (don't know how many click).If just click once that can't clicked.
Note few days ago I tried to click once and it's worked, but now when I tried to running again using AS it's not work, even though I not modified that file
My code
public class RecyclerViewAdapterRiwayat extends RecyclerView.Adapter<RecyclerViewAdapterRiwayat.ViewHolder> {
Context context;
private static final String TAG = RecyclerViewAdapterRiwayat.class.getSimpleName();
List<GetDataAdapterRiwayat> getDataAdapter;
ImageLoader imageLoader1;
String FIXURL = "http://192.168.1.101/AndroidFileUpload/";
String url = FIXURL + "uploads/";
String StatusRiwayat;
public RecyclerViewAdapterRiwayat(List<GetDataAdapterRiwayat> getDataAdapter, Context context) {
super();
this.getDataAdapter = getDataAdapter;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_items_riwayat, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder Viewholder, int position) {
final GetDataAdapterRiwayat getDataAdapter1 = getDataAdapter.get(position);
imageLoader1 = ServerImageParseAdapter.getInstance(context).getImageLoader();
imageLoader1.get(url+getDataAdapter1.getFotoSetelahRiwayat(),
ImageLoader.getImageListener(
Viewholder.networkImageView,//Server Image
R.mipmap.ic_launcher,//Before loading server image the default showing image.
android.R.drawable.ic_dialog_alert //Error image if requested image dose not found on server.
)
);
Viewholder.networkImageView.setImageUrl(url+getDataAdapter1.getFotoSetelahRiwayat(), imageLoader1);
Viewholder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "coba nih5 : "+getDataAdapter1.getNamaJalanRiwayat());
Intent intent = new Intent(v.getContext(), DetailRiwayatActivity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return getDataAdapter.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView ImageTitleNameView;
public NetworkImageView networkImageView;
public ViewHolder(View itemView) {
super(itemView);
ImageTitleNameView = (TextView) itemView.findViewById(R.id.textView_item_riwayat);
networkImageView = (NetworkImageView) itemView.findViewById(R.id.VollyNetworkImageView2);
}
}
}
If you only have the issue after scrolling / flinging the RecyclerView, it's a known bug in the SupportLibrary
After a user scrolls, they cannot click on an item in a RecyclerView. (AOSP issue 66996774)
Issuetracker ID 66996774 and also 69823266 because it's still not fixed in 27.0.1. Even though Google states it has fixed it.
Most important: the fix here (by Chris Banes, Googler) works perfectly: https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2
Try this:
class ViewHolder extends RecyclerView.ViewHolder{
public TextView ImageTitleNameView;
public NetworkImageView networkImageView;
public ViewHolder(View itemView) {
super(itemView);
ImageTitleNameView = (TextView) itemView.findViewById(R.id.textView_item_riwayat);
networkImageView = (NetworkImageView) itemView.findViewById(R.id.VollyNetworkImageView2);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getLayoutPosition(); // use this to get item from list
Log.d(TAG, "coba nih5 : "+getDataAdapter1.getNamaJalanRiwayat());
Intent intent = new Intent(v.getContext(), DetailRiwayatActivity.class);
context.startActivity(intent);
}
});
}
Your code
Viewholder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "coba nih5 : "+getDataAdapter1.getNamaJalanRiwayat());
Intent intent = new Intent(v.getContext(), DetailRiwayatActivity.class);
context.startActivity(intent);
}
});
creating new listener every time to the itemView , Instead implement OnClickListener or pass null before assigning new Listener
Viewholder.itemView.setOnClickListener(null);
Viewholder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "coba nih5 : "+getDataAdapter1.getNamaJalanRiwayat());
Intent intent = new Intent(v.getContext(), DetailRiwayatActivity.class);
context.startActivity(intent);
}
});
Or add listener in ViewHolder onCreateViewHolder()
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = viewHolder.getAdapterPosition(); // use this to get item from list
Log.d(TAG, "coba nih5 : "+getDataAdapter1.getNamaJalanRiwayat());
Intent intent = new Intent(v.getContext(), DetailRiwayatActivity.class);
context.startActivity(intent);
}
});
Add these to your parent element of R.layout.recyclerview_items_riwayat
android:clickable="false"
android:focusable="false"
That's probably due to the parent's onTouch method which intercepts the touch event. You need to check if there is a parent view like SwipeLayout.

RecyclerView - a single selection selects every 10 row

It's strange but when I long click on one row using my code, the star on that row turns gold (which is what I want), but also each star ten rows apart.
This is my code:
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView localeDisplay;
private static final int grey_blue = 0xff546E7A;
private static final int gold = 0xffffa000;
public MyViewHolder(final View view) {
super(view);
localeDisplay = (TextView) view.findViewById(R.id.languageText);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Languages currentLanguages = languagesList.get(getAdapterPosition());
Snackbar snackbar;
snackbar = Snackbar.make(view, currentLanguages.getLocaleDisplay() + " selected", Snackbar.LENGTH_INDEFINITE)
.setAction("Next", new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), MainActivity.class);
v.getContext().startActivity(intent);
}
});
View snackBarView = snackbar.getView();
snackBarView.setBackgroundColor(grey_blue);
snackbar.show();
}
}
);
view.setOnLongClickListener(new View.OnLongClickListener()
{
#Override
public boolean onLongClick(View v) {
Toast.makeText(v.getContext(), "Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
ImageView star = (ImageView) view.findViewById(R.id.imageView);
if (star.getColorFilter() == null) {
star.setColorFilter(gold);
} else star.clearColorFilter();
return true;
}
}
);
}
I have tried following this tutorial but the same behavior happens.
Any ideas what I could do to correct this?
in your adapter constructor, just add this part:
setHasStableIds(true).
and after that override the following methods in the adapter class.
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
Seems like your view is being recycled, what means your listener reference is being called to all recycled views.
An easy way to solve this is setting new references for each single view at onBindViewHolder method. Usually Viewholder is used to find views and keep the references for recycled views, isn't a good idea set data inside it.
You could change the viewholder for:
public ExampleViewHolder(View view) {
super(view);
myContainer = (LinearLayout) view.findViewById(R.id.myContainer);
localeDisplay = (TextView) view.findViewById(R.id.languageText);
star = (ImageView) view.findViewById(R.id.imageView);
}
And set the listener at onBindViewHolder:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
ExampleHolder holder = (ExampleHolder) viewHolder;
//Insert the position reference
holder.myContainer.setTag(position);
// Setting listeners
holder.myContainer.setOnClickListener(this);
holder.myContainer.setOnLongClickListener(this);
}
Then implement the OnLongClickListener and OnClickListener at your adapter.
#Override
public boolean onLongClick(View v) {
//Getting position
int position = (int)v.getTag();
//Insert your code
return false;
}
#Override
public void onClick(View v) {
//code here
}
Drop me a line back if works. Good luck.
This is because you are getting all items that have the R.id.imageView id. To do what you want, you need to grab the item that was clicked and change the color of the selected line only;

View Changes While scrolling RecyclerView

I'm using RecyclerView, I have one ImageButton as Child view, I'm changing the background of that ImageButton on click.
Now my problem is when change Image of ImageButton by clicking and than scroll up again scroll to the top, the state of set to the initial stage. I tried everything but its not happening. help me with that.
My Adapter class
public class ViewAllAdapter extends RecyclerView.Adapter<ProductHolder> {
int[] objects;
Context context;
Boolean flag = false;
public ViewAllAdapter(int[] objects, Context context) {
super();
this.objects = objects;
this.context = context;
}
#Override
public int getItemCount() {
return objects.length;
}
#Override
public void onBindViewHolder(final ProductHolder arg0, int arg1) {
arg0.title.setText("Product" + arg1 + 1);
arg0.aPrice.setPaintFlags(arg0.aPrice.getPaintFlags()
| Paint.STRIKE_THRU_TEXT_FLAG);
arg0.aPrice.setText("\u20B9" + " " + "5000");
arg0.off.setText("56% off");
arg0.price.setText("\u20B9" + " " + "2300");
arg0.mainImage.setImageResource(objects[arg1]);
arg0.ratings.setRating(4f);
arg0.clickme.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this,
ProductDetailsPage.class);
startActivity(i);
}
});
arg0.wish.setBackgroundResource(R.drawable.heart);
arg0.wish.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (!flag) {
arg0.wish.setBackgroundResource(R.drawable.heartfade);
YoYo.with(Techniques.Tada).duration(550)
.playOn(arg0.wish);
Toast.makeText(context, "Product Added to wish list..",
Toast.LENGTH_SHORT).show();
flag = true;
} else {
arg0.wish.setBackgroundResource(R.drawable.heart);
Toast.makeText(context,
"Product Removed to wish list..",
Toast.LENGTH_SHORT).show();
flag = false;
}
}
});
}
#Override
public ProductHolder onCreateViewHolder(ViewGroup arg0, int arg1) {
LayoutInflater inflater = LayoutInflater.from(arg0.getContext());
View view = inflater.inflate(R.layout.viewall_item, arg0, false);
return new ProductHolder(view);
}
public class ProductHolder extends RecyclerView.ViewHolder {
protected TextView title;
protected TextView aPrice;
protected TextView off;
protected TextView price;
protected ImageView mainImage;
protected RatingBar ratings;
protected ImageButton wish;
protected RelativeLayout clickme;
public ProductHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.productName);
aPrice = (TextView) itemView
.findViewById(R.id.productActualPrice);
off = (TextView) itemView.findViewById(R.id.offPrice);
price = (TextView) itemView.findViewById(R.id.productPrice);
mainImage = (ImageView) itemView
.findViewById(R.id.productImage);
wish = (ImageButton) itemView.findViewById(R.id.addToWishList);
ratings = (RatingBar) itemView
.findViewById(R.id.productRatings);
clickme = (RelativeLayout) itemView
.findViewById(R.id.clickToGO);
}
}
}
And in My MainActicity I'm doing
rv = (RecyclerView) findViewById(R.id.gvViewAll);
rv.setHasFixedSize(true);
GridLayoutManager glm = new GridLayoutManager(getApplicationContext(),
2);
rv.setLayoutManager(glm);
final ViewAllAdapter adp = new ViewAllAdapter(productImage,
getApplicationContext());
rv.setAdapter(adp);
rvh = (RecyclerViewHeader) findViewById(R.id.header);
rvh.attachTo(rv, true);
Thanks for any help.
As per your Custom RecyclerView adapter, I suggest you to use HashMap to store Values. After all Data Model is best option to load data in to RecyclerView.
HashMap<Integer, Integer> hashMapTest = new HashMap<>();
When user click on ImageButton then add following code:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(hashMapTest.get(position) != null && hashMapTest.get(position) != false) {
// Code of Product Added to wish list..
hashMapTest.put(getPosition(), 1);
} else {
// Code of Product Removed to wish list..
hashMapTest.put(getPosition(), 0);
}
}
});
In your onBindViewHolder(ProductHolder holder, int position) add following code
if(hashMapTest.get(position) != null && hashMapTest.get(position) != false) {
// Show your ImageButton color Product Added to wish list..
} else {
// Show your ImageButton color Product Removed to wish list..
}
Hope it helps you.

Categories

Resources