Filtering RecyclerView with 4 different Spinner - android

I am currently trying to implement a search function for RecyclerView containing custom items in form of CardViews with 4 different TextViews.
I want to use 4 different spinner elements, each covering one textView.
For now I tried the search with one spinner only, but it does not work.
Custom RecyclerView Adapter:
public class WorkersAdapter extends RecyclerView.Adapter<WorkersAdapter.ViewHolder> {
private List<Worker> workers, filtered;
private Context c;
private int lastPosition = -1;
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView levelracein, nodein, cityin;
public ImageView iv;
public ViewHolder(View view) {
super(view);
levelracein = (TextView) view.findViewById(R.id.levelracein);
cityin = (TextView) view.findViewById(R.id.cityin);
nodein = (TextView) view.findViewById(R.id.nodein);
}
}
public WorkersAdapter(Context c, List<Worker> workers) {
this.c = c;
this.workers = workers;
this.filtered = new ArrayList<>();
this.filtered.addAll(this.workers);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.worker_list_item, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
int pos = position;
Worker worker = filtered.get(position);
holder.levelracein.setText(worker.getLevel() + " " + worker.getRace());
holder.cityin.setText(worker.getCity());
holder.nodein.setText(worker.getNode());
setAnimation(holder.itemView, position);
}
#Override
public int getItemCount() {
return workers != null? workers.size() : 0;
}
private void setAnimation(View viewToAnimate, int position)
{
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(c, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public void filter(final String level, final String race, final String city, final String node) {
new Thread(new Runnable() {
#Override
public void run() {
filtered.clear();
if (level.equals("None")) {
filtered.addAll(workers);
} else {
for (Worker worker : workers) {
if (worker.getLevel().toLowerCase().contains(level.toLowerCase())) {
filtered.add(worker);
}
}
}
((Activity) c).runOnUiThread(new Runnable() {
#Override
public void run() {
// Notify the List that the DataSet has changed...
notifyDataSetChanged();
}
});
}
}).start();
}
}
The Spinner listener:
levelspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
onQueryTextChange(levelspinner.getSelectedItem().toString(),
racespinner.getSelectedItem().toString(),
cityspinner.getSelectedItem().toString(),
nodespinner.getSelectedItem().toString());
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
The function to feed the search in RecyclerView:
public boolean onQueryTextChange(String level, String race, String city, String node) {
wa.filter(level, race, city, node); //wa -> WorkersAdapter
return true;
}
The question is,
How to implement a search which will add all the different spinner selections and search more precise with every spinner item selected?
Why does my RecyclerView still display cardViews which are empty after selecting?

Change your getItemCount() to below code on Adapter class , you used here two ArralList reference when you search it will showing result by your filtered ArrayList reference . so you have to return filtered.size()
#Override
public int getItemCount() {
return filtered!= null? filtered.size() : 0;
}
As per your Comment you want search all of these spinners in single filter change with below code
for (Worker worker : workers) {
if (worker.getLevel().toLowerCase().contains(level.toLowerCase()) || 2nd searchitem || 3rd searchitem || 4th searchitem ) {
filtered.add(worker);
}
}

Related

How to update item in a recycler view using diff item callback?

I'm implementing a recycler view using room database library. I would like to list my items and that they could be edited by clicking. After re-submit the item, go back again to the list and show up the items + changes.
I'm currently using DiffUtil callback to compare the old and the new lists. I think the problem is here. My Dto item has 4 fields.
id title image arraylist
So when the user edits an item, the list should update the UI row (title, image or/and arraylist)
This is my Adapter.
private OnItemClickListener listener;
public ExercicioAdapter() {
super(DIFF_CALLBACK);
}
private static final DiffUtil.ItemCallback<Exercicio> DIFF_CALLBACK = new DiffUtil.ItemCallback<Exercicio>() {
#Override
public boolean areItemsTheSame(#NonNull Exercicio oldExercicio, #NonNull Exercicio newExercicio) {
return oldExercicio.getId() == newExercicio.getId();
}
#Override
public boolean areContentsTheSame(#NonNull Exercicio oldExercicio, #NonNull Exercicio newExercicio) {
return oldExercicio.getTitulo().equals(newExercicio.getTitulo()) &&
Float.compare(oldExercicio.getMaxPeso(), newExercicio.getMaxPeso()) == 0;
}
};
#NonNull
#Override
public MyHolderView onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View view;
LayoutInflater mInflater = LayoutInflater.from(parent.getContext());
view = mInflater.inflate(R.layout.exercicios_item, parent, false);
return new MyHolderView(view);
}
#Override
public void onBindViewHolder(#NonNull MyHolderView exercicioHolder, final int i) {
Exercicio exercicio = getItem(i);
// Mostrar a informacion do obxeto.
ArrayList<Repeticion> repeticions = exercicio.getRepeticions();
float peso_max = 0f;
if (repeticions != null && repeticions.size() > 0) {
for (Repeticion rep : repeticions) {
if (rep.getPeso() > peso_max) {
peso_max = rep.getPeso();
}
}
}
exercicioHolder.nome.setText(exercicio.getTitulo());
String peso_str = exercicioHolder.itemView.getContext().getString(R.string.peso_max);
exercicioHolder.peso.setText(peso_str + " " + Float.toString(peso_max));
if (exercicio.getImaxe() != null && exercicio.getImaxe().length != 0) {
exercicioHolder.imx_exercicio.setImageBitmap(convertByteArrayToBitmap(exercicio.getImaxe()));
}
}
public Exercicio getExercicioAt(int position) {
return getItem(position);
}
public class MyHolderView extends RecyclerView.ViewHolder {
TextView nome;
TextView peso;
ImageView imx_exercicio;
CardView exercicio_cardview;
MyHolderView(#NonNull View itemView) {
super(itemView);
exercicio_cardview = itemView.findViewById(R.id.exercicio_cardview);
nome = itemView.findViewById(R.id.nome);
peso = itemView.findViewById(R.id.peso);
imx_exercicio = itemView.findViewById(R.id.imx_exercicio);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getAdapterPosition();
if (listener != null && position != RecyclerView.NO_POSITION) {
listener.onItemClick(getItem(position));
}
}
});
}
}
public interface OnItemClickListener {
void onItemClick(Exercicio exercicio);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
The problem: when an item is updated, changing the title for example, the list gets updated, but the eddited item disappears. If i end the activity and start it again, the item updated is there. So the problem must be the diff callback, but I'm not really able to make it work. Sorry for my English, this is not my main language, thanks all!
Most probably you are not properly using the DiffUtil functionality. You first need to calculate diff and then dispatch updates to adapter after which it will refresh your adapter with the new data. Use DiffUtil.Callback() and not DiffUtil.ItemCallback()
DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
#Override
public int getOldListSize() {
// old list size, which is same as new in your case
}
#Override
public int getNewListSize() {
// new list size, which is same as old in your case
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition)
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
}
)
result.dispatchUpdatesTo(this); // this parameter is your Recycler View's adapter
You can read more about Diff Util here and here
Let me know if you still have doubts. Thanks.

Recyclerview single item selection not working correctly

I've implemented a recyclerview with staggered gridLayout containing about 31 items in the arrayList, recyclerview is working correctly, but I faced issue relating to single item selection.
When I select the value till "26" as shown in figure, its working fine
But, when I select the value after "26", the values from top most item are also selected, as shown in this next figure.
I require to only select one item at a time.
I've implemented the following code in my adapter class
public class DialogAdapter extends
RecyclerView.Adapter<DialogAdapter.DialogHolder>
{
// components
public Context context;
public ArrayList<AlertDialogModel> dialogArrayList = new
ArrayList<AlertDialogModel>();
private final ArrayList<Integer> selected = new ArrayList<>();
private int lastCheckedPosition = -1;
public Interface interface;
// parameterized constructor
public DialogAdapter(Context context, ArrayList<AlertDialogModel>
dialogArrayList,Interface interface)
{
this.context = context;
this.dialogArrayList = dialogArrayList;
this.interface = interface;
}
#NonNull
#Override
public DialogHolder onCreateViewHolder(#NonNull ViewGroup parent, int
viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_cardview,parent,false);
DialogHolder dialogHolder = new DialogHolder(view);
return dialogHolder;
}
#Override
public void onBindViewHolder(#NonNull final DialogHolder holder, final int position)
{
final AlertDialogModel alertDialogModel = dialogArrayList.get(position);
holder.textView.setText(alertDialogModel.getDisplayValue());
if(lastCheckedPosition == position)
{
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
}
else
{
}
holder.textView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
lastCheckedPosition = position;
notifyDataSetChanged();
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
interface.getSelectedValue(alertDialogModel.getDisplayValue());
}
});
}
#Override
public int getItemCount()
{
return dialogArrayList.size();
}
public static class DialogHolder extends RecyclerView.ViewHolder
{
public TextView textView;
public DialogHolder(View itemView)
{
super(itemView);
textView = (TextView)itemView.findViewById(R.id.textView);
}
}
}
Can anyone relate my code and identify the issue ?
holder.textView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
lastCheckedPosition = position;
notifyDataSetChanged();
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
interface.getSelectedValue(alertDialogModel.getDisplayValue());
//below line is important to remove previous selected position from the variable
lastCheckedPosition = -1;
}
});
you should put the text view to the original state:
if(lastCheckedPosition == position)
{
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
}
else
{
holder.textView.setTextColor(context.getResources().getColor(R.color.transparent));
holder.textView.setBackground(null));
}

Count the clicks on an item of RecyclerView

I am developing an android app in which I use a RecyclerView. Suppose I have 6 items in my RecyclerView i.e. [A, B, C, D, E, F]. So how can I get the number of clicks on these items?
For example:
If an user open item B 4 times. How can I get the count = 4?
P.s. count should increase only when the user click on the same item.
First declare static count variables for each items
private static int aCount = 0;
Then inside your onBindViewHolder, pass a method after the button click along with your position id.
public void onBindViewHolder(ItemAdapter.ViewHolder holder, int position) {
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
thisWasClicked(position);
}
}
}
The method will be something like this
private void thisWasClicked(int position) {
if (position == 0) {
aCount++;
}
}
in holder
itemView.setOnClickListener(){
onClick(){
// count up
}
}
each item needs also an id to know, which item it is
I've made an example
CustomItem object
public class CustomItem {
private String item;
private int click;
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getClick() {
return click;
}
public void setClick(int click) {
this.click = click;
}
}
CustomAdapter and CustomViewHolder for the recyclerview
public class CustomAdapter extends RecyclerView.Adapter{
private List<CustomItem> itemList;
public CustomAdapter(List<CustomItem> itemList){
this.itemList = itemList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.viewholder_generic, parent, false));;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//increase click count for the current item
itemList.get(holder.getAdapterPosition()).setClick(itemList.get(holder.getAdapterPosition()).getClick() + 1);
}
});
}
#Override
public int getItemCount() {
return itemList.size();
}
// Custom ViewHolder
public class CustomViewHolder extends RecyclerView.ViewHolder {
//add fields you need
public CustomViewHolder(View itemView) {
super(itemView);
}
}
}
You can create a Map<Integer, Integer> clicksMap = new HashMap<>() in your adapter
You should also pass an interface to your ViewHolder that acts as a click Listener. Something like.
public interface OnItemLick {
void onItemClick(int position, int id);
}
Then declare an instance of this interface in your adapter.
OnItemLick listener = new OnItemClick() {
void onItemClick(int position, int id) {
//you can either use the item position or an id (if you have an unique one for the items). I will show an example using the position.
int count;
if(clicksMap.contains(position)) {
count = clickMap.get(position);
count ++;
clickMap.put(position, count);
}else {
count ++;
clickMap.put(position, count); }
}
In the end you clicksMap will contain the click count for every position of the items in the recycler.

how to make the header of Recycle view invisible

I have a Recyclerview with header view as slider images and remaining view as normal recycler items.I am wondering if there is any way around to make the header view invisible depending upon some sort of condition.The recycler view consists of two separate layout files for this purpose: layout1 for header items and layout2 for normal recycler items and adapter will pick a layout and binds corresponding data at runtime.
This is my RecyclerView adapter RestaurantAdapter.java
public class RestaurantAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = RestaurantAdapter.class.getName();
private List<Restaurant> mList;
private Context mContext;
private RestaurantType mRestaurantType;
private static final int RECYCLER_HEADER=0,RECYCLER_ITEMS=1;
private LayoutInflater inflater;
private SlideItemViewHolder slideItemViewHolder;
private List<ImageSliderPOJO> mData;
public RestaurantAdapter(Context context, List<Restaurant> list, RestaurantType restaurantType) {
this.mContext = context;
this.mList = list;
this.mRestaurantType = restaurantType;
inflater=LayoutInflater.from(context);
}
public void updateAdapter(List<ImageSliderPOJO> data){
this.mData = data;
this.notifyDataSetChanged();
}
#Override
public int getItemCount() {
return mList.size();
}
#Override
public int getItemViewType(int position) {
return position == 0 ? RECYCLER_HEADER : RECYCLER_ITEMS;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int i) {
int viewType=viewHolder.getItemViewType();
switch (viewType){
case RECYCLER_HEADER:
slideItemViewHolder = (SlideItemViewHolder) viewHolder;
slideItemViewHolder.updateHeader();
break;
case RECYCLER_ITEMS:
final RecyclerItemViewHolder holder = (RecyclerItemViewHolder) viewHolder;
final Restaurant restaurant = mList.get(i);
Picasso.with(mContext)
.load(restaurant.getVendorLogo())
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(holder.restaurentImageView);
holder.restaurentNameTextView.setText(restaurant.getName());
//Remaining code here
break;
default:
throw new RuntimeException(TAG+":Unable to bind the viewType"+viewType);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType){
case RECYCLER_HEADER:
return new SlideItemViewHolder(inflater.inflate(R.layout.slide_show_restaurant_fragment_list,viewGroup,false));
case RECYCLER_ITEMS:
return new RecyclerItemViewHolder(inflater.inflate(R.layout.new_restautant_list_items, viewGroup, false));
default:
throw new RuntimeException(TAG+":Invalid ViewType "+viewType);
}
}
public static class RecyclerItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ClickListener clickListener;
//Initialization here.
public RecyclerItemViewHolder(View v) {
super(v);
ButterKnife.inject(this, v);
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
clickListener.onClick(v, getPosition(), false);
}
public interface ClickListener {
/**
* Called when the view is clicked.
*
* #param v view that is clicked
* #param position of the clicked item
* #param isLongClick true if long click, false otherwise
*/
public void onClick(View v, int position, boolean isLongClick);
}
/* Setter for listener. */
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
}
// id = 87,170
private class SlideItemViewHolder extends RecyclerView.ViewHolder {
SliderLayout sliderLayout;
LinearLayout rootLinearLayout;
public SlideItemViewHolder(View recyclerHeader) {
super(recyclerHeader);
sliderLayout = (SliderLayout) recyclerHeader.findViewById(R.id.home_slider);
rootLinearLayout = (LinearLayout) recyclerHeader.findViewById(R.id.rootLinearLayout);
}
private void updateHeader() {
if(Util.isNetworkAvailable(mContext)){
for (int i = 0; i < mData.size(); i++) {
DefaultSliderView defaultSliderView = new DefaultSliderView(mContext);
final int finalI = i;
defaultSliderView.image(mData.get(finalI).getImageUrl())
.setOnSliderClickListener(new BaseSliderView.OnSliderClickListener() {
#Override
public void onSliderClick(BaseSliderView slider) {
Restaurant restaurantById = Restaurant.searchByRestaurantId(mData.get(finalI).getTargetVendorId());
if(restaurantById != null)
openDetailFragment(restaurantById);
}
});
sliderLayout.addSlider(defaultSliderView);
}
}
}
}
public void openDetailFragment(Restaurant restaurant) {
Intent intent = new Intent(mContext, DetailTabActivity.class);
intent.putExtra(DetailTabActivity.INTENT_RESTAURANT_DATA, restaurant);
mContext.startActivity(intent);
}
public SliderLayout getSliderLayout(){
return slideItemViewHolder.sliderLayout;
}
}
And this adapter is set and updated from this fragment RestaurantFragment.java as:
private void setAdapter() {
dismissDialog();
if (getActivity() != null)
getActivity().runOnUiThread(new Runnable(){
#Override
public void run() {
if (restaurantList != null && restaurantList.size() > 0) {
restaurantRecyclerView.setVisibility(View.VISIBLE);
mEmptyListTextView.setVisibility(View.GONE);
restaurentListAdapter = new RestaurantAdapter(getActivity(), restaurantList, mRestaurantType);
restaurantRecyclerView.setAdapter(restaurentListAdapter);
restaurentListAdapter.updateAdapter(mData);
restaurantRecyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager) {
#Override
public void onLoadMore(int current_page) {
mCurrentPage = mCurrentPage + 1;
getHttpResturantData();
}
});
}
}
});
}
Is this much of an explanation helpful or should I paste more code?
Based on your code, it's possible to remove the header based on a certain condition.
Adjust your code to cater for the following:
#Override
public int getItemViewType(int position) {
if(hasHeaeder()) { // where you add the header
return position == 0 ? RECYCLER_HEADER : RECYCLER_ITEMS;
} else { // where you don't add the header
return RECYCLER_ITEMS;
}
}
This code also needs changing (currently it's wrong since it doesn't take care of the fact that the header adds 1 to the position).
final Restaurant restaurant = mList.get(i);
Replace it with
final Restaurant restaurant = hasHeader() ? mList.get(i +1) : mList.get(i);
Where hasHeader() is the code you need to write in order to determine whether or not the recycler should contain a header.

Android recyclerView findViewHolderForAdapterPosition returns null

I want to click an item in recyclerView programmatically, I found a way do that:
recyclerView.findViewHolderForAdapterPosition(0).itemView.performClick();
but it doesn't work for me, the findViewHolderForAdapterPosition just returns null.
Did I miss something in my code?
HistoryListAdapter:
public class HistoryListAdapter extends RecyclerView.Adapter<HistoryListAdapter.ViewHolder> {
private static ArrayList<RecordItem> recordItems;
private static FragmentActivity activity;
private static RecordList recordList;
public HistoryListAdapter(ArrayList<RecordItem> recordItems, FragmentActivity FA, RecordList FRL) {
this.recordItems = recordItems;
this.activity = FA;
this.recordList = FRL;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recorditem, parent, false);
return new ViewHolder(itemLayoutView);
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
// TextView setText ...
}
// Return the size of the itemsData (invoked by the layout manager)
#Override
public int getItemCount() {
return recordItems.size();
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder{
public TextView result, datetime;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
itemLayoutView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (activity != null) {
// do something...
}
}
});
result = (TextView) itemLayoutView.findViewById(R.id.result);
heartrate = (TextView) itemLayoutView.findViewById(R.id.heartrate);
datetime = (TextView) itemLayoutView.findViewById(R.id.datetime);
}
}
}
RecordList:
RecyclerView listView = (RecyclerView) layoutView.findViewById(R.id.listView);
HistoryListAdapter listadapter = new HistoryListAdapter(itemsToShow, getActivity(), RecordList.this);
listView.swapAdapter(listadapter, false);
listView.findViewHolderForAdapterPosition(0).itemView.performClick();
I omitted some code, But it should not affect the overall structure of my code.
According to the official documentation:
if notifyDataSetChanged() has been called but the new layout has not
been calculated yet, this method will return null since the new
positions of views are unknown until the layout is calculated.
It's not safe to use findViewHolderForAdapterPosition().
While you call this method after listView.swapAdapter(listadapter, false); you'll always get a null as result because notifyDataSetChanged() will be called.
you can do this:
listView.postDelayed(new Runnable()
{
#Override
public void run()
{
if(listView.findViewHolderForAdapterPosition(0)!=null )
{
listView.findViewHolderForAdapterPosition(0).itemView.performClick();
}
}
},50);
I know that is very late, but maybe is helpful for other people in the Kotlin era:
binding.recycler.post {
val view = binding.recycler.findViewHolderForAdapterPosition(position)?.itemView?.performClick()
}
you can do this:
postAndNotifyAdapter(new Handler(),mRecyclerView);
protected void postAndNotifyAdapter(final Handler handler, final RecyclerView recyclerView) {
handler.post(new Runnable() {
#Override
public void run() {
if ( recyclerView.findViewHolderForLayoutPosition(0)!=null) {
// This will call first item by calling "performClick()" of view.
recyclerView.findViewHolderForLayoutPosition(0).itemView.performClick();
} else {
//
postAndNotifyAdapter(handler, recyclerView);
}
}
});
}
Hey I've solved the problem this way:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private TextView mTotalSum;
protected int mSum;
protected ArrayList<BasketRVAdapter.ViewHolder> mViewHolders;
public BasketRVAdapter(JSONArray recyclerItems, Context context, TextView totalSum) {
super(recyclerItems, context);
mTotalSum = totalSum;
mViewHolders = new ArrayList<>();
}
#Override
public RecyclerView.ViewHolder onCreateSwipeViewHolder(ViewGroup parent, int i) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_basket_rv_item, parent, true);
return new ViewHolder(view);
}
#Override
public void onBindSwipeViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {
final BasketRVAdapter.ViewHolder holder = (BasketRVAdapter.ViewHolder) viewHolder;
JSONObject object;
try {
object = mRecyclerItems.getJSONObject(position);
final int priceValue = object.getInt("price");
final int quantityValue = object.getInt("quantity");
holder.setId(object.getInt("id"));
holder.title.setText(object.getString("title"));
holder.price.setText(String.format(mContext.getString(R.string.price), priceValue));
holder.quantity.setText(String.valueOf(quantityValue));
holder.sum.setText(String.valueOf(priceValue * quantityValue));
holder.quantity.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
String value = holder.quantity.getText().toString();
if (value.equals("")) {
return;
}
if (value.equals("0")) {
Toast.makeText(mContext, R.string.null_value_error, Toast.LENGTH_SHORT).show();
return;
}
holder.sum.setText(String.valueOf(priceValue * Integer.valueOf(value)));
setTotalSum();
}
});
mViewHolders.add(holder);
mSum += priceValue * quantityValue;
if (position == getItemCount() - 1) {
mTotalSum.setText(String.format(mContext.getString(R.string.total_sum), mSum));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public SwipeConfiguration onCreateSwipeConfiguration(Context context, int i) {
return new SwipeConfiguration.Builder(context)
.setLeftSwipeBehaviour(SwipeConfiguration.SwipeBehaviour.NORMAL_SWIPE)
.setRightSwipeBehaviour(SwipeConfiguration.SwipeBehaviour.NO_SWIPE)
.setLeftBackgroundColorResource(R.color.dt_basket_deleted)
.setLeftUndoDescription(R.string.deleted)
.setDescriptionTextColorResource(R.color.dt_white)
.setLeftUndoable(true)
.build();
}
#Override
public void onSwipe(int i, int i1, RecyclerView.ViewHolder holder) {
try {
if (i1 == SWIPE_LEFT) {
remove(i);
notifyItemRemoved(i);
mViewHolders.remove(i);
setTotalSum();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public int getSum() {
return mSum;
}
public void setTotalSum() {
int totalSum = 0;
for (BasketRVAdapter.ViewHolder holder : mViewHolders) {
totalSum += Integer.valueOf(holder.sum.getText().toString());
}
mSum = totalSum;
mTotalSum.setText(String.format(mContext.getString(R.string.total_sum), totalSum));
}
public static class ViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.trade_title)
public TextView title;
#Bind(R.id.trade_price)
public TextView price;
#Bind(R.id.trade_quantity)
public EditText quantity;
#Bind(R.id.sum)
public TextView sum;
private int mId;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public int getId() {
return mId;
}
public void setId(int id) {
mId = id;
}
}}
Added ArrayList mViewholders field inside class
added each viewholder instance to mViewHolders arraylist inside onBindSwipeViewHolder method
used mViewholders arraylist instead of findViewHolderForadapterposition method inside setTotalSum method
I wouldnt recommend using post delay. Although it works the timing is arbitrary.
Using OnPreDrawListener on the recyclerview, timing will be aligned with the next draw cycle and visible items are accessible.

Categories

Resources