RecyclerView: gives wrong position onClick of specific View of custom row - android

Desired Result
Maintain scroll position and give right position on specific view of custom row.
I am using RecyclerView in which I am trying to add on Demand Data on beginning of list as well as end of list.
Fetching data through Scrolling bottom is working perfectly.
But Scrolling top having issues as follows:
Set Click listener in Adapter's onBindViewHolder.
Set Click listener in Recyclerview's OnItemTouchListener.
Here is the case:
When I scroll up the list and then It loads 15 data and add it to the top of list.
Our intention is to Maintain scroll position.
Which can be achieved through
adapter.notifyItemRangeInserted(0, stringArrayListTemp.size());
But the Issue is while I am clicking on any Item without scrolling then View's OnClickListener gives wrong position.
You can check adapter's method:
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
String item = moviesList.get(position);
holder.title.setText(item);
holder.title.setTag(position);
holder.title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("onClick", "stringArrayList position: " + moviesList.get(position) + " - view position: " + moviesList.get((int) view.getTag()));
}
});
}
But at the same time in Recyclerview's addOnItemTouchListener gives right position with stringArrayList.get(position) but gives wrong position using getTag.
mRecyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Log.e("onItemClick", "stringArrayList position: "+stringArrayList.get(position)+ " - view position: "+stringArrayList.get((int)view.getTag()));
}
}));
When I try to add data in the beginning of the list by following I am getting the exact issue.
// retain scroll position and gives wrong position onClick
adapter.notifyItemRangeInserted(0, stringArrayListTemp.size());
// does not retain scroll position, scroll to top & gives right position onClick
//adapter.notifyDataSetChanged();

This code work for me, so try some thing like that
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private final Typeface font;
public TextView mTitle, mDetail, mDate, mCategory;
public CheckBox mCheckBox;
public ImageButton mImageButton;
public ImageView mImage;
public View mview;
private SparseBooleanArray selectedItems = new SparseBooleanArray();
public MyViewHolder(View view) {
super(view);
mTitle = (TextView) view.findViewById(R.id.item_title);
mDetail = (TextView) view.findViewById(R.id.item_detail);
mImage = (ImageView) view.findViewById(R.id.item_thumbnail);
mDate = (TextView) view.findViewById(R.id.date);
mCategory = (TextView) view.findViewById(R.id.category);
mCheckBox = (CheckBox) view.findViewById(R.id.checkbox);
mImageButton = (ImageButton) view.findViewById(R.id.imageButton);
mview = view;
view.setOnClickListener(this);
view.setOnLongClickListener(this);
}
#Override
public void onClick(View v) {
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(MainActivity.activity, Uri.parse(mDataSet.get(getAdapterPosition()).getPostLink()));
}
how i maintain the recyclerview position
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
if (mRecyclerView.getLayoutManager() != null) {
scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
}
switch (layoutManagerType) {
case GRID_LAYOUT_MANAGER:
mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
break;
case LINEAR_LAYOUT_MANAGER:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
break;
default:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
}
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.scrollToPosition(scrollPosition);
}

Related

Removing element from adapter throws Index out of bound exception

I have two recycler views. The first recyclerview is basically a list of data where I can choose an item and its quantity and I am storing this chosen item data into a map. The second one is the list of the selected data. which I am generating from getting the values() from the map. The second one also has similar viewholder and I can change the quantity there also. One the quantity reaches zero I remove the item from the list and try to notifydatasetChanged().
The problem is the removing of an item from the second list is not working properly and the app crashes with error
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder
I am using a listener interface on my first Recycler so that when the quantity is changed and the item is added to the map. The adapter of the second recycler is notified of the changes. below is the code i am using to update the second recycler view.
public void updateList(){
mMap = ((UserMainActivity)getActivity()).getItemMap();
inputs.clear();
// adapter.notifyDataSetChanged();
adapter = new MyCartAdapter(inputs,getContext());
cartList.setAdapter(adapter);
for(AllItems t:mMap.values()) {
inputs.add(t);
}
adapter.notifyDataSetChanged();
}
Below is my second recycler view's adapter. Where I am changing the quantities of the selected items.
public class MyCartAdapter extends RecyclerView.Adapter<MyCartAdapter.MyCartViewHolder>{
private List<AllItems> listItems1;
private Context context;
private Typeface typeface;
public MyCartAdapter(List<AllItems> listItems1, Context context) {
this.listItems1 = listItems1;
this.context = context;
}
#NonNull
#Override
public MyCartAdapter.MyCartViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cart_items_layout, parent, false);
return new MyCartViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull final MyCartAdapter.MyCartViewHolder holder, final int position) {
final AllItems orderItem = listItems1.get(position);
holder.setProductImage(orderItem.getImageUrl(),context);
holder.name.setText(orderItem.getName());
String price = String.valueOf(orderItem.getPrice());
holder.price.setText(price);
final HashMap<String, AllItems> items = ((UserMainActivity)context).getItemMap();
holder.counter.setText(orderItem.getQuantity());
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String quantity = String.valueOf(holder.counter.getText());
int count = Integer.parseInt(quantity)+1;
holder.counter.setText(String.valueOf(count));
String url = orderItem.getImageUrl();
AllItems newitem = new AllItems(orderItem.getName(),orderItem.getComname(),url, String.valueOf(count),orderItem.getWeight,orderItem.getPrice());
((UserMainActivity)context).addItem(orderitemname,newitem);
// notifyItemChanged(position);
}
});
//counter text iitem.textview showing the quantity of the selected item . integer count returns the value of counter text below i am checking if its zero than it simply sets the value to zero and else reduce it and update the map.
holder.minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String counterText = String.valueOf(holder.counter.getText());
int count = Integer.parseInt(counterText);
if (count==0){
holder.counter.setText("0");
}
if (count==1){
holder.counter.setText("0");
AllItems item = items.get(orderItem.getName());
if (item!=null){
String orderit = orderItem.getName();
((UserMainActivity)context).removeItem(orderit);
// here i am removing the value from the list which throws the exception
listItems1.remove(position);
notifyItemRemoved(position);
}
}
if (count>1){
String quantity = String.valueOf(count-1);
holder.counter.setText(quantity);
String orderitemname = orderItem.getName();
String url = orderItem.getImageUrl();
String weight = "100";
long weightl = Long.parseLong(weight);
AllItems newitem = new AllItems(orderItem.getName(),orderItem.getComname(),url, quantity,weight,orderItem.getPrice());
((UserMainActivity)context).addItem(orderitemname,newitem);
// listItems1.set(position, newitem);
// notifyItemChanged(position);
}
}
});
}
#Override
public int getItemCount() {
return listItems1.size();
}
public class MyCartViewHolder extends RecyclerView.ViewHolder {
public TextView name,price,count,comname;
public TextView weight;
LinearLayout add,minus;
TextView counter;
public MyCartViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.ProName);
price = (TextView) itemView.findViewById(R.id.proPrice);
weight = (TextView) itemView.findViewById(R.id.ProWeight);
counter = (TextView) itemView.findViewById(R.id.counter);
add = (LinearLayout) itemView.findViewById(R.id.addLin);
minus= (LinearLayout) itemView.findViewById(R.id.minusLin);
}
public void setProductImage(final String thumb_image, final Context ctx){
productImage = (ImageView) itemView.findViewById(R.id.ProImage);
Picasso.with(ctx).setIndicatorsEnabled(false);
Picasso.with(ctx)
.load(thumb_image)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.basket_b).into(productImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(ctx).load(thumb_image).placeholder(R.drawable.basket).into(productImage);
}
});
}
public void setComname(String name){
comname = (TextView)itemView.findViewById(R.id.proComName);
comname.setText(name);
}
}
}
This jumps out at me:
listItems1.remove(position);
notifyItemChanged(position);
The notifyItemChanged() method exists to tell the adapter that the data at the given position has changed, and that the ViewHolder should be re-bound. This is not what you're doing; you're removing an item.
Probably your app is crashing because you're removing the last item in your data set (e.g. position 10) and then telling the adapter that the item at position 10 has changed... but now the maximum position in your data set is 9.
Instead, you should use the notifyItemRemoved() method.
listItems1.remove(position);
notifyItemRemoved(position);

RecyclerView.Adapter notifyItemChanged() and click on view not working properly

What I'm trying to do is to display a list of cardViews with info in it, and one of the infos is a tablelayout populated with data added by user, so he can edit or delete a tableRow. The problem is that when an object is edit/deleted and notifyitemChanged(position), notifyDataSetChanged(position), notifyItemRemoved(position) methods are called, they duplicate the tableLayout view inside the cardView, giving it a creepy look, like this:
Tablelayout populated and duplicated after calling notify methods
private void removeRow(int position, int i) {
listX.get(position).getListY().remove(i);
if(listX.get(position).getListY().size()==0){
listX.remove(position);
this.notifyItemRemoved(position);
}
this.notifyDataSetChanged();
this.notifyItemChanged(position);
}
removeRow() is called everytime removeIcon is clicked
private void editRow(ObjectX objectX, int position, int index) {
Log.i("position : index",position+" : "+index);
listX.get(position).getListY().get(index).setAttributeX(objectX.getAttributeX());
this.notifyItemChanged(position);
}
editRow() is called everytime editIcon is clicked*
OnBindViewHolder()->
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
HolderExample holder = (HolderExample) viewHolder;
ObjectX objectX = this.listX.get(position);
holder.bind(objectX,listener);
for (TableRow tableRow:getRowsFromFata(objectX)) {
holder.tableLayout.addView(tableRow);
}
}
getRowsFromData(ObjectX objectX)->
private List<TableRow> getRowsFromFata(ObjectX objectX){
List<TableRow> tableRows = new ArrayList<>();
//... setting layoutParams
TableRow heading = new TableRow(context);
//Header
// ... creating and adding 4 textViews to "heading row" with addView(textView) method
tableRows.add(heading);
//Content
for(ExampleData exampleData:objextX.getListY()){
//creating and setting values of 4 textViews with each attribute of ExampleData
//getListY holds List<ExampleData> listY = ArrayList<>();
ImageView editIcon = new ImageView(context);
editIcon.setImageResource(R.drawable.ic_edit_black);
editIcon.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onClick(View view) {
//opens an AlertDialog and when POSITIVE_BUTTON is clicked calls editRow() method
openAddTaskAlertDialog(objectX,listX.indexOf(objectX),objectX.getListY().indexOf(exampleData));
}
});
ImageView removeIcon = new ImageView(context);
removeIcon.setImageResource(R.drawable.ic_delete_forever);
removeIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
removeTaskCompleted(listX.indexOf(objectX),objectX.getListY().indexOf(exampleData));
}
});
TableRow contentRow = new TableRow(context);
//... adding textViews and ImageViews to contentRow
tableRows.add(contentRow);
}
return tableRows;
}

ArrayList is clearing when new values are inserting in adaper

I have a recycler view which is showing fruit list. Each item has a buy button.When I click the buy button of an item in the list, the details of that item should pass to the order list page through intent and should be displayed in recycler view.I have used ArrayList for passing the data.Then when I click the continue button it will come back to fruit list page and I want to buy another fruit.But my issue is, when I click the buy button of another item, only that particular item is displayed in the order list.the previous item is missing and the recycler view is showing only one row.(ie, latest data).Can any one please help?
this is the adapter code:
public ViewHolder(View view) {
super(view);
fruitname = (TextView) view.findViewById(R.id.category_name);
rate = (TextView) view.finenter code heredViewById(R.id.rate);
buy = (TextView) view.findViewById(R.id.buy);
mProfilepic = (ImageView) view.findViewById(R.id.profilepic);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View rootView = LayoutInflater.
from(mContext).inflate(R.layout.list_item, null, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.setLayoutParams(lp);
return new ViewHolder(rootView);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
item = mListItem.get(position);
final ViewHolder mViewHolder = (ViewHolder) viewHolder;
mViewHolder.fruitname.setText(item.get_name());
mViewHolder.rate.setText(item.get_email()+"/kg");
}
mViewHolder.buy.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
item1.set_contact(mListItem.get(position).get_designation());
item1.set_bank_fee(mListItem.get(position).get_name());
item1.set_category(mListItem.get(position).get_email());
dataItem.add(item1);
Intent intent = new Intent(mContext,OrderListActivity.class);
intent.putExtra("arraylist",dataItem);
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mListItem.size();
}
note:I have used notifyDataSetChanged.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.order_list);
mrecyclerview = (RecyclerView)findViewById(R.id.fruits_recycler);
mrecyclerview.setLayoutManager(new
LinearLayoutManager(getApplicationContext()));
dataItem =
(ArrayList<ListItem>)getIntent().getSerializableExtra("arraylist");
mOrderAdapter = new OrderAdapter(OrderListActivity.this,dataItem);
mrecyclerview.setAdapter(mOrderAdapter);
mOrderAdapter.notifyDataSetChanged();
}
}
Try this .
Intent intent = new Intent(mContext,OrderListActivity.class);
// edited here
intent.putParcelableArrayListExtra("arraylist", productList);
mContext.startActivity(intent);
And next Activity .
ArrayList<ListItem>) dataItem = getIntent().getParcelableArrayListExtra("arraylist");
if (dataItem != null && dataItem.size() > 0) {
mOrderAdapter = new OrderAdapter(OrderListActivity.this, dataItem);
mrecyclerview.setAdapter(mOrderAdapter);
// remove this
// mOrderAdapter.notifyDataSetChanged();
}

Recycle View scrolls slow . How to fix it?

I just implemented expandable layout in recycle view .ExpandableLayout library
Issue : Recycle view scroll slow at first time . expand/collpase working good but list scroll slow
NOTE : Its working smoothly on 4 GB RAM Device but laggy scroll on 2 GB RAM Device . I tested with Moto g3 (2 GB RAM) and Moto
g5 Plus (4 GB RAM)
Data coming from web-service and passing array-list through adapter.
Layout row file (XML) in Nested Linear Layouts. (may be its viewgroups load but i also tried with Constraint layout .Still recycleview load laggy)
I am replacing view during expansion and collapse item view (I already commented that code. but still my recycle view is slow )
There is no use of any image storing in itemview .
Already tried setHasFixedSize , notifyDataChanged , setCache , adapter.setHasStableIds(true);
but still recycleview loads laggy at first time only .
Help me to fix this issue. I am still finding the issue !
You can check my Adapter Code!
public class PendingOrdersAdapter extends RecyclerView.Adapter<PendingOrdersAdapter.ViewHolder> {
public LayoutInflater mInflater;
public HashSet<Integer> mExpandedPositionSet = new HashSet<>();
Context context;
ArrayList<CustomerDetails> list;
CustomerDetails details;
public PendingOrdersAdapter(Context context, ArrayList<CustomerDetails> list) {
this.context = context;
this.list = list;
this.mInflater = LayoutInflater.from(context);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = mInflater.inflate(R.layout.pending_order_item, parent, false);
return new ViewHolder(item);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
details = list.get(position);
holder.updateItem(position, holder);
holder.tvOrderNo.setText("" + details.getOrderID());
holder.tvCustomerName.setText("" + details.getCustomerName());
holder.tvTotalPrice.setText("" + details.getTotalPrice());
holder.tvCustomerContactNo.setText("" + details.getPrimaryContactNo());
holder.tvProductWeight.setText("" + details.getProductWeight());
holder.tvCustomerStatus.setText("" + details.getCustomerStatus());
holder.tvDeliveryManStatus.setText("" + details.getDeliveryManStatus());
holder.tvAddress.setText("" + details.getAddress());
holder.tvDeliveryMan.setText("" + details.getCustomerName() + " ( " + details.getPrimaryContactNo() + " ) ");
holder.tvTime.setText("" + details.getTime());
holder.tvPickUpDate.setText("" + details.getPickupDate());
holder.tvDeliveryCharge.setText("" + details.getDeliveryCharge());
//Opening DialogFragment on Click Listner
holder.tvDeliveryMan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AppCompatActivity activity = (AppCompatActivity) (context);
android.app.FragmentTransaction ft = activity.getFragmentManager().beginTransaction();
android.app.Fragment prev = activity.getFragmentManager().findFragmentByTag("dvdialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DeliveryManDetailsDialog newFragment = new DeliveryManDetailsDialog();
newFragment.show(ft, "dvdialog");
}
});
holder.tvAddress.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_RIGHT = 2;
//Address icon click listner right side
if (event.getAction() == MotionEvent.ACTION_UP) {
if (event.getRawX() >= (holder.tvAddress.getRight() - holder.tvAddress.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
Intent intent = new Intent(context, RouteActivity.class);
intent.putExtra("custLat", details.getCustLatitude());
intent.putExtra("custLong", details.getCustLongitude());
intent.putExtra("boLat", details.getBoLatitude());
intent.putExtra("boLong", details.getBosLongitude());
context.startActivity(intent);
}
return true;
}
return true;
}
});
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getItemCount() {
return list.size();
}
public void registerExpand(int position, ViewHolder holder) {
if (mExpandedPositionSet.contains(position)) {
//Replacing views at runtime and arrow animation
ViewGroupUtils.replaceView(holder.timeLayout, holder.statusLayout);
holder.orderbox.setBackgroundResource(R.drawable.box_fill_drawable);
holder.ivArrow.animate().rotation(360).start();
removeExpand(position);
} else {
ViewGroupUtils.replaceView(holder.statusLayout, holder.timeLayout);
holder.orderbox.setBackgroundResource(R.drawable.box_fill_drawable_top);
holder.ivArrow.animate().rotation(180).start();
addExpand(position);
}
}
public void removeExpand(int position) {
mExpandedPositionSet.remove(position);
}
public void addExpand(int position) {
mExpandedPositionSet.add(position);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ExpandableLayout expandableLayout;
public LinearLayout orderbox, orderbox_bottom;
public ImageView ivArrow;
public TextView tvAddress, tvOrderNo, tvCustomerName, tvTotalPrice, tvCustomerContactNo;
public TextView tvProductWeight, tvCustomerStatus, tvDeliveryManStatus;
public TextView tvDeliveryCharge, tvDeliveryMan, tvTime;
public TextView tvPickUpDate;
public LinearLayout statusLayout, statusParentLayout, timeLayout, timeParentLayout, addressLayout;
public ViewHolder(final View itemView) {
super(itemView);
expandableLayout = (ExpandableLayout)
itemView.findViewById(R.id.expandable_layout);
orderbox = (LinearLayout) itemView.findViewById(R.id.orderbox);
orderbox_bottom = (LinearLayout)
itemView.findViewById(R.id.orderbox_bottom);
ivArrow = (ImageView) itemView.findViewById(R.id.ivArrow);
tvOrderNo = (TextView) itemView.findViewById(R.id.tvOrderNo);
tvCustomerName = (TextView)
itemView.findViewById(R.id.tvCustomerName);
tvTotalPrice = (TextView)
itemView.findViewById(R.id.tvTotalPrice);
tvCustomerContactNo = (TextView)
itemView.findViewById(R.id.tvCustomerContactNo);
tvProductWeight = (TextView)
itemView.findViewById(R.id.tvProductWeight);
tvCustomerStatus = (TextView)
itemView.findViewById(R.id.tvCustomerStatus);
tvDeliveryManStatus = (TextView)
itemView.findViewById(R.id.tvDeliveryManStatus);
tvDeliveryCharge = (TextView)
itemView.findViewById(R.id.tvDeliveryCharge);
tvAddress = (TextView) itemView.findViewById(R.id.tvAddress);
tvDeliveryMan = (TextView)
itemView.findViewById(R.id.tvDeliveryMan);
tvTime = (TextView) itemView.findViewById(R.id.tvTime);
tvPickUpDate = (TextView)
itemView.findViewById(R.id.tvPickUpDate);
statusParentLayout = (LinearLayout)
itemView.findViewById(R.id.statusParentLayout);
statusLayout = (LinearLayout)
itemView.findViewById(R.id.statusLayout);
timeParentLayout = (LinearLayout)
itemView.findViewById(R.id.timeParentLayout);
timeLayout = (LinearLayout)
itemView.findViewById(R.id.timeDateLayout);
addressLayout = (LinearLayout)
itemView.findViewById(R.id.addressLayout);
}
public void updateItem(final int position, final ViewHolder holder) {
holder.orderbox.setBackgroundResource(R.drawable.box_fill_drawable_top);
holder.expandableLayout.setOnExpandListener(new ExpandableLayout.OnExpandListener() {
#Override
public void onExpand(boolean expanded) {
registerExpand(position, holder);
}
});
expandableLayout.setExpand(mExpandedPositionSet.contains(position));
}
}
Calling Adapter from Fragment
** PendingOrdersAdapter adapter = new PendingOrdersAdapter(getActivity(), detailsArrayList);
recyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(20);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
recyclerview.setAdapter(adapter);
adapter.notifyDataSetChanged();**
Make one class, for example, Util and added this method to the class and use it.
public static void setDivider(Context context, RecyclerView recyclerView, RecyclerView.LayoutManager layoutManager) {
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(20);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
DividerItemDecoration horizontalDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
Drawable horizontalDivider = ContextCompat.getDrawable(context, R.drawable.horizontal_divider);
horizontalDecoration.setDrawable(horizontalDivider);
recyclerView.addItemDecoration(horizontalDecoration);
}
here first parameter is context, second one pass your recyclerview and third one pass the layout manager.
if you have more stuff then change the CacheSize
use this
recyclerView.setNestedScrollingEnabled(false);

How to implement single selection in RecyclerView?

I can change properties of selected item in RecyclerView but I want to remove selection for older selections.
Here is how I create RecyclerView :
fragmentViewPagerAdapter.addFragmentView((arg1, arg2, arg3) -> {
View view = arg1.inflate(R.layout.recyclerview_layout, arg2, false);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
selectDateRecyclerViewAdapter = new SelectDateRecyclerViewAdapter(dayList,this,(v,position) ->
{
AppCompatButton appCompatButton = (AppCompatButton)v.findViewById(R.id.selectHourButton);
AppCompatImageView appCompatImageView = (AppCompatImageView)v.findViewById(R.id.calendarDot);
highlightButton(appCompatButton,appCompatImageView);
});
recyclerView.setHasFixedSize(false);
recyclerView.addItemDecoration(selectDateRecyclerViewAdapter. new CalendarItemDecoration(10,dayList.size()));
GridLayoutManager gridLayoutManager = new GridLayoutManager(getApplicationContext(),4,GridLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.setAdapter(selectDateRecyclerViewAdapter);
selectDateRecyclerViewAdapter.notifyDataSetChanged();
return view;
});
highlightButton method changes background of Button etc.
Thanks.
You may need to hold flags to record which buttons are selected, when you select a new item, clear the flags first and reset it to the position of your new selected item. Then notifyDataSetChanged() or notifyItemChanged().done.
The main code of this function may be placed in highlightButton method. so It's better If you post the highlightButton code.
Since its a single selection, you can track the selected position using an external variable, say int selectedIndex;
In your adapter code :
public class ViewHolder extends RecyclerView.ViewHolder {
View itemView;
public ViewHolder(View v) {
super(v);
itemView = v;
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedPostion = getAdapterPosition();
if( selectedPosition == RecyclerView.NO_POSITION) return;
recyclerViewOnItemClickListener.onItemSelect(itemView, getAdapterPosition()); //Custom listener - in turn calls your highlightButton method
//call notifyDataSetChanged(); or notifyItemRangeChanged();
}
});
}
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.itemView.setSelected(position == selectedPostion);
}

Categories

Resources