When I scroll the recyclerView some items appear in positions where they shouldn't.
Where I should have only "First" or only "Second" suddenly I have both "First Second" in a view.
EDIT : most probably it reuses some views but how am I going to check if this is correct?
My code is :
#Override
public void onBindViewHolder(MyRecyclerAdapter.ViewHolder holder, int position) {
DiaryDay item = items.get(position);
holder.tvDay.setText(item.getDay());
holder.tvMonth.setText(item.getMonth());
showSplash(holder, item);
if (holder.tvSunBathingMins!=null) {
holder.tvSunBathingMins.setText(String.valueOf(item.getSunBathing()) + " mins sunbathing. ");
}
}
private void showSplash(ViewHolder holder, DiaryDay item) {
if ( item.getSun_1() + item.getSun_2() + item.getSun_3() + item.getSun_4() == 4 ) {
holder.tvSplash2.setText( "All day! Amazing!");
} else {
if (item.getSun_1() != 0) {
holder.tvSplash1.setText("First ");
}
if (item.getSun_2() != 0) {
holder.tvSplash2.setText("Second ");
}
if (item.getSun_3() != 0) {
holder.tvSplash3.setText("Third ");
}
if (item.getSun_4() != 0) {
holder.tvSplash4.setText("Fourth ");
}
}
}
#Override
public MyRecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
return new ViewHolder(v);
}
And finally my ViewHolder is :
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvDay;
public TextView tvMonth;
public TextView tvSplash1; public TextView tvSplash2; public TextView tvSplash3; public TextView tvSplash4;
public TextView tvSunBathingMins;
public TextView tvSumMins;
public ViewHolder(View itemView) {
super(itemView);
tvDay = (TextView) itemView.findViewById(R.id.dayID);
tvMonth = (TextView) itemView.findViewById(R.id.monthID);
tvSplash1 = (TextView) itemView.findViewById(R.id.sun1);
tvSplash2 = (TextView) itemView.findViewById(R.id.sun2);
tvSplash3 = (TextView) itemView.findViewById(R.id.sun3);
tvSplash4 = (TextView) itemView.findViewById(R.id.sun4);
tvSunBathingMins = (TextView) itemView.findViewById(R.id.sunbathMinsID);
tvSumMins = (TextView) itemView.findViewById(R.id.sumMinsID);
}
}
The problem is in the way you define if statements without else clause. What happens is when the view holder gets recycled, views such as tvSplash1, tvSplash2 and etc. still have values assigned from the view that got off the screen. That's why you need to reset these items as follows:
#Override
public void onBindViewHolder(MyRecyclerAdapter.ViewHolder holder, int position) {
DiaryDay item = items.get(position);
holder.tvDay.setText(item.getDay());
holder.tvMonth.setText(item.getMonth());
showSplash(holder, item);
if (holder.tvSunBathingMins!=null) {
holder.tvSunBathingMins.setText(String.valueOf(item.getSunBathing()) + " mins sunbathing. ");
} else {
holder.tvSunBathingMins.setText("");
}
}
private void showSplash(ViewHolder holder, DiaryDay item) {
if ( item.getSun_1() + item.getSun_2() + item.getSun_3() + item.getSun_4() == 4 ) {
holder.tvSplash2.setText( "All day! Amazing!");
} else {
if (item.getSun_1() != 0) {
holder.tvSplash1.setText("First ");
} else {
holder.tvSplash1.setText("");
}
if (item.getSun_2() != 0) {
holder.tvSplash2.setText("Second ");
} else {
holder.tvSplash2.setText("");
}
if (item.getSun_3() != 0) {
holder.tvSplash3.setText("Third ");
} else {
holder.tvSplash3.setText("");
}
if (item.getSun_4() != 0) {
holder.tvSplash4.setText("Fourth ");
} else {
holder.tvSplash4.setText("");
}
}
}
Related
Create an adapter object, find recycler view id to set adapter and then set layout manager. In scroll listener, unable to get correct LastVisibleItemPosition, it return -1 to me. findFirstVisibleItemPosition() also returning -1.
//Here is Adapter
public class CategoryProduct extends RecyclerView.Adapter<RecyclerView.ViewHolder>
`enter code here`{
private static final int ITEM = 0;
private static final int LOADING = 1;
public String vertical = "";
Context context;
private boolean isLoadingAdded = false;
private boolean retryPageLoad = false;
private List<com.example.it.camanagement.model.CategoryProduct> dataSet;
public CategoryProduct(ArrayList<com.example.it.camanagement.model.CategoryProduct> data, Context context, String vertical) {
this.dataSet = data;
this.context = context;
this.vertical = vertical;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ITEM:
View viewLoading;
if (vertical.equals("vertical")) {
viewLoading = LayoutInflater.from(parent.getContext())
.inflate(R.layout.category_product_list, parent, false);
} else {
viewLoading = LayoutInflater.from(parent.getContext())
.inflate(R.layout.category_product_list_grid, parent, false);
}
viewHolder = new MyViewHolder(viewLoading);
break;
case LOADING:
View viewLoading1 = inflater.inflate(R.layout.item_progress, parent, false);
viewHolder = new LoadingVH(viewLoading1);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int listPosition) {
if (listPosition == dataSet.size() - 1) {
CategoryDetails categoryDetails = (CategoryDetails) context;
categoryDetails.onBottomReached(listPosition);
}
switch (getItemViewType(listPosition)) {
case ITEM:
final MyViewHolder myViewHolder = (MyViewHolder) holder;
TextView textViewName = myViewHolder.productName;
// TextView textViewVersion = holder.textViewVersion;
ImageView imageView = myViewHolder.productImage;
RatingBar productRating = myViewHolder.productRasting;
TextView productCost = myViewHolder.productCost;
TextView productDiscount = myViewHolder.productDistCount;
TextView productCOLOR = myViewHolder.productColor;
TextView productId = myViewHolder.product_id;
TextView productModel = myViewHolder.productModel;
TextView productQuantity = myViewHolder.productQuantity;
productModel.setText(dataSet.get(listPosition).getModel());
productQuantity.setText(dataSet.get(listPosition).getQuantity());
productId.setText(dataSet.get(listPosition).getProduct_id());
textViewName.setText(dataSet.get(listPosition).getName());
Glide.with(context).load(dataSet.get(listPosition).getImage()).into(imageView);
productRating.setRating(Float.parseFloat(String.valueOf(dataSet.get(listPosition).getRating())));
productCost.setText("RM " + dataSet.get(listPosition).getPrice());
productDiscount.setText(dataSet.get(listPosition).getDiscount());
if (dataSet.get(listPosition).getSpecial().trim().length() != 0) {
myViewHolder.special.setText("RM " + dataSet.get(listPosition).getSpecial());
strikeThroughText(productCost);
}
break;
case LOADING:
LoadingVH loadingVH = (LoadingVH) holder;
if (retryPageLoad) {
loadingVH.mErrorLayout.setVisibility(View.VISIBLE);
loadingVH.mProgressBar.setVisibility(View.GONE);
loadingVH.mErrorTxt.setText(
errorMsg != null ?
errorMsg :
context.getString(R.string.error_msg_unknown));
} else {
loadingVH.mErrorLayout.setVisibility(View.GONE);
loadingVH.mProgressBar.setVisibility(View.VISIBLE);
}
break;
}
}
private void strikeThroughText(TextView price) {
price.setPaintFlags(price.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
#Override
public int getItemCount() {
return dataSet == null ? 0 : dataSet.size();
//return dataSet.size();
}
#Override
public int getItemViewType(int position) {
return (position == dataSet.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
}
public com.example.it.camanagement.model.CategoryProduct getItem(int position) {
return dataSet.get(position);
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView productName, productColor, productCost, productDistCount, product_id, productModel, productQuantity, special;
RatingBar productRasting;
ImageView productImage;
public MyViewHolder(View itemView) {
super(itemView);
this.productName = (TextView) itemView.findViewById(R.id.product_name);
this.productColor = (TextView) itemView.findViewById(R.id.product_color);
this.productCost = (TextView) itemView.findViewById(R.id.cost);
this.productDistCount = (TextView) itemView.findViewById(R.id.discount);
this.productRasting = (RatingBar) itemView.findViewById(R.id.product_rating);
this.product_id = (TextView) itemView.findViewById(R.id.product_iid);
this.productQuantity = (TextView) itemView.findViewById(R.id.quantity);
this.productModel = (TextView) itemView.findViewById(R.id.modelProduct);
//this.textViewVersion = (TextView) itemView.findViewById(R.id.textViewVersion);
this.productImage = (ImageView) itemView.findViewById(R.id.product_image);
this.special = (TextView) itemView.findViewById(R.id.special);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent i = new Intent(context, ProductDescription.class);
i.putExtra("productName", ((TextView) v.findViewById(R.id.product_name)).getText().toString());
i.putExtra("product_id", ((TextView) v.findViewById(R.id.product_iid)).getText().toString());
context.startActivity(i);
if (getPosition() == 0) {
// Toast.makeText(v.getContext(), " On CLick one", Toast.LENGTH_SHORT).show();
}
if (getPosition() == 1) {
//Toast.makeText(v.getContext(), " On CLick Two", Toast.LENGTH_SHORT).show();
}
if (getPosition() == 2) {
// Toast.makeText(v.getContext(), " On CLick Three", Toast.LENGTH_SHORT).show();
}
if (getPosition() == 3) {//
// Toast.makeText(v.getContext(), " On CLick Fore", Toast.LENGTH_SHORT).show();
}
}
});
}
}
protected class LoadingVH extends RecyclerView.ViewHolder {
private ProgressBar mProgressBar;
private ImageButton mRetryBtn;
private TextView mErrorTxt;
private LinearLayout mErrorLayout;
public LoadingVH(View itemView) {
super(itemView);
mProgressBar = (ProgressBar) itemView.findViewById(R.id.loadmore_progress);
mRetryBtn = (ImageButton) itemView.findViewById(R.id.loadmore_retry);
mErrorTxt = (TextView) itemView.findViewById(R.id.loadmore_errortxt);
mErrorLayout = (LinearLayout) itemView.findViewById(R.id.loadmore_errorlayout);
}
}
}
//Recycler View
categoryProduct = (RecyclerView) findViewById(R.id.categoryProductList);
categoryProductAdapter = new CategoryProduct(categoryProduct,categoryProductList, context);
categoryProduct.setAdapter(categoryProductAdapter);
categoryProduct.setNestedScrollingEnabled(false);
categoryProduct.setHasFixedSize(false);
girdLayoutManager = new GridLayoutManager(CategoryDetails.this, 2);
categoryProduct.setLayoutManager(girdLayoutManager);
//scroll Listener
scrollListener = new EndlessRecyclerViewScrollListener(girdLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
Log.d("pageCount", "" + page);
Log.d("FirstVisibleITEM", "" + girdLayoutManager.findFirstVisibleItemPosition());
Log.d("LastVisibleITEM", "" + girdLayoutManager.findLastVisibleItemPosition());
}
};
categoryProduct.addOnScrollListener(scrollListener);
Finally solved it, Issue was: I was creating the object of layout manager two times. one in method(API response received and after notify the adapter) and another one in OnCreate() method of activity. after removing one object from method( API response received and after notify the adapter), fixed the issue.
I am trying to develop an activity where there is a custom listView made out of CustomAdapter.
The list consists of a TextView and an EditText. The EditText when clicked, it auto fetches the system time.
What I want is when a particular EditText is filled, I want all the previous(above) list items in the sequence to be disabled.
So far, I have tried using isEnabled() and areAllItemsEnabled() functions returning respective boolean values using position, but however didn’t work.
Please help me achieve the above.
Thanks.
This is my CustomAdapter Class
public class SelectStnListByRoute extends BaseAdapter implements View.OnClickListener {
Context context;
ArrayList<StnNames> stnList;
LayoutInflater layoutInflater = null;
ViewHolder viewHolder;
private int mLastClicked;
public SelectStnListByRoute(Context context, ArrayList<StnNames> stnList) {
super();
this.context = context;
this.stnList = stnList;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return stnList.size();
}
#Override
public Object getItem(int position) {
return stnList.get(position);
}
#Override
public long getItemId(int position) {
return stnList.indexOf(getItem(position));
}
public int getViewTypeCount() {
return 1;
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
if(position==position){
return false;
}
return false;
}
#Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
int type = getItemViewType(position);
StnNames stnDetails = stnList.get(position);
viewHolder = new ViewHolder();
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.footplate_custome_layout, null);
viewHolder.txtStnNAme = (TextView) convertView.findViewById(R.id.txtStnCode);
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
viewHolder.txtStnDep = (TextView) convertView.findViewById(R.id.txtDepTime);
convertView.setTag(viewHolder);
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
}
viewHolder.txtStnNAme.setText(stnDetails.getStnCode());
viewHolder.txtStnArr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: " , String.valueOf(position)); //Here I am getting the position of the row item clicked, where should I put the Onclick false for disabling all of the above fields using the position?
}
});
viewHolder.txtStnDep.setOnClickListener(this);
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
if (stnDetails.getArrivalTime() != null) {
viewHolder.txtStnArr.setText(stnDetails.getArrivalTime());
} else {
viewHolder.txtStnArr.setText("");
}
if (stnDetails.getDeptTime() != null) {
viewHolder.txtStnDep.setText(stnDetails.getDeptTime());
} else {
viewHolder.txtStnDep.setText("");
}
return convertView;
}
class ViewHolder {
TextView txtStnNAme, txtStnArr, txtStnDep;
int ref;
}
#Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case txtArrivalTime:
TextView textViewArrVal = (TextView) view.findViewById(R.id.txtArrivalTime);
textViewArrVal.setClickable(false);
StnNames listItemsArrr = (StnNames) textViewArrVal.getTag();
if (listItemsArrr.getArrivalTime() != getCurrentTime()) {
listItemsArrr.setArrivalTime(getCurrentTime());
if (listItemsArrr.getArrivalTime() != null) {
int position = textViewArrVal.getSelectionStart();
textViewArrVal.setText(listItemsArrr.getArrivalTime());
} else {
textViewArrVal.setText("");
}
}
break;
case txtDepTime:
TextView textViewDepVal = (TextView) view.findViewById(R.id.txtDepTime);
StnNames listItemsDepp = (StnNames) textViewDepVal.getTag();
if (listItemsDepp.getDeptTime() != getCurrentTime()) {
listItemsDepp.setDeptTime(getCurrentTime());
if (listItemsDepp.getDeptTime() != null) {
textViewDepVal.setText(listItemsDepp.getDeptTime());
} else {
textViewDepVal.setText("");
}
}
break;
default:
break;
}
}
public String getCurrentTime(){
Calendar calendar = Calendar.getInstance();
SimpleDateFormat mdformat = new SimpleDateFormat("HH:mm:ss");
String arrDate = mdformat.format(calendar.getTime());
return arrDate;
}
}
You can do this as below mentioned -:
You need to store the position of clicked button was. So initialize a variable in your class
int mButtonSelected = -1;
EDIT 1.
Then make a change to your isEnabled method
#Override
public boolean isEnabled(int position) {
if(position<mButtonSelected){
return false;
}
return true;
}
That will work it if any other button was clicked. but you have to do that in your onClick
mButtonSelected = position;
notifyDataSetChanged();
Let me it worked or not
EDIT
see below changes in your code-:
public class SelectStnListByRoute extends BaseAdapter {
Context context;
ArrayList<StnNames> stnList;
LayoutInflater layoutInflater = null;
ViewHolder viewHolder;
private int mLastClicked;
private SQLiteDB sqLiteDB;
int mArrivalSelected = -1;
int mDepartSelected = -1;
public SelectStnListByRoute(Context context, ArrayList<StnNames> stnList) {
super();
this.context = context;
this.stnList = stnList;
layoutInflater = LayoutInflater.from(context);
sqLiteDB = new SQLiteDB(context);
}
#Override
public int getCount() {
return stnList.size();
}
#Override
public Object getItem(int position) {
return stnList.get(position);
}
#Override
public long getItemId(int position) {
return stnList.indexOf(getItem(position));
}
public int getViewTypeCount() {
return 1;
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
if (position <= mArrivalSelected) {
return false;
}
return true;
}
public boolean isEnabledd(int position) {
if (position <= mDepartSelected) {
return false;
}
return true;
}
#Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
int type = getItemViewType(position);
StnNames stnDetails = stnList.get(position);
viewHolder = new ViewHolder();
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.footplate_custome_layout, null);
viewHolder.txtStnNAme = (TextView) convertView.findViewById(R.id.txtStnCode);
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
viewHolder.txtStnDep = (TextView) convertView.findViewById(R.id.txtDepTime);
convertView.setTag(viewHolder);
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
} else {
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.txtStnArr.setTag(stnDetails);
viewHolder.txtStnDep.setTag(stnDetails);
}
viewHolder.txtStnNAme.setText(stnDetails.getStnCode());
if (!isEnabled(position)) {
if (position <= mArrivalSelected) {
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#ffa500"));
viewHolder.txtStnArr.setEnabled(false);
if (position < mArrivalSelected) {
viewHolder.txtStnDep.setEnabled(false);
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#ffa500"));
}
}
} else {
viewHolder.txtStnArr.setEnabled(true);
viewHolder.txtStnDep.setEnabled(true);
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#b4b4b4"));
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#b4b4b4"));
}
viewHolder.txtStnArr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: ", String.valueOf(position));
mArrivalSelected = position;
arrivalClick(view);
notifyDataSetChanged();
}
});
if (!isEnabledd(position)) {
if (position <= mDepartSelected) {
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#ffa500"));
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#ffa500"));
viewHolder.txtStnArr.setEnabled(false);
viewHolder.txtStnDep.setEnabled(false);
} else {
viewHolder.txtStnArr.setEnabled(true);
viewHolder.txtStnDep.setEnabled(true);
viewHolder.txtStnArr.setBackgroundColor(Color.parseColor("#b4b4b4"));
viewHolder.txtStnDep.setBackgroundColor(Color.parseColor("#b4b4b4"));
}
}
viewHolder.txtStnDep.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: ", String.valueOf(position));
mDepartSelected = position;
departureClick(view);
notifyDataSetChanged();
}
});
viewHolder.txtStnArr = (TextView) convertView.findViewById(R.id.txtArrivalTime);
if (stnDetails.getArrivalTime() != null) {
viewHolder.txtStnArr.setText(stnDetails.getArrivalTime());
} else {
viewHolder.txtStnArr.setText("");
}
if (stnDetails.getDeptTime() != null) {
viewHolder.txtStnDep.setText(stnDetails.getDeptTime());
} else {
viewHolder.txtStnDep.setText("");
}
return convertView;
}
class ViewHolder {
TextView txtStnNAme, txtStnArr, txtStnDep;
StnNames pos;
int ref;
}
public void arrivalClick(View view) {
TextView textViewArrVal = (TextView) view.findViewById(R.id.txtArrivalTime);
StnNames listItemsArrr = (StnNames) textViewArrVal.getTag();
if (listItemsArrr.getArrivalTime() != getCurrentTime()) {
listItemsArrr.setArrivalTime(getCurrentTime());
int stnId = listItemsArrr.getStnId();
String arrClick = "arrival";
String upSideKm = listItemsArrr.getStnUpsideKm();
String downsideKm = listItemsArrr.getStnDownSideKm();
String arrTime = getCurrentTime();
/* sqLiteDB.open();
*//* long abc = sqLiteDB.insertJourneySchedule(stnId,arrTime,"",userId,journeyId,latitute,longitute,journyDate,arrClick);*//*
*//* long abcd = sqLiteDB.updateJourneySchedule(stnId,arrTime,"",userId,journeyId,latitute,longitute,journyDate,arrClick,downsideKm,upSideKm);
Log.e("arrclick",String.valueOf(abcd));*//*
sqLiteDB.close();*/
if (listItemsArrr.getArrivalTime() != null) {
int position = textViewArrVal.getSelectionStart();
textViewArrVal.setText(listItemsArrr.getArrivalTime());
} else {
textViewArrVal.setText("");
}
}
}
public void departureClick(View view) {
TextView textViewDepVal = (TextView) view.findViewById(R.id.txtDepTime);
StnNames listItemsDepp = (StnNames) textViewDepVal.getTag();
if (listItemsDepp.getDeptTime() != getCurrentTime()) {
listItemsDepp.setDeptTime(getCurrentTime());
String depTime = getCurrentTime();
int stnId = listItemsDepp.getStnId();
String depClick = "departure";
String upSideKm = listItemsDepp.getStnUpsideKm();
String downsideKm = listItemsDepp.getStnDownSideKm();
sqLiteDB.open();
/*long abc = sqLiteDB.insertJourneySchedule(stnId,"",depTime,userId,journeyId,latitute,longitute,journyDate,depClick);*/
/*long abcd = sqLiteDB.updateJourneySchedule(stnId,"",depTime,userId,journeyId,latitute,longitute,journyDate,depClick,downsideKm,upSideKm);
Log.e("depclick",String.valueOf(abcd));*/
sqLiteDB.close();
if (listItemsDepp.getDeptTime() != null) {
textViewDepVal.setText(listItemsDepp.getDeptTime());
} else {
textViewDepVal.setText("");
}
}
}
public String getCurrentTime() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat mdformat = new SimpleDateFormat("HH:mm:ss");
String arrDate = mdformat.format(calendar.getTime());
return arrDate;
}
}
Get the position of the row which is clicked and then set onclick false for positions less than clicked position
as follows:
viewHolder.txtStnArr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e("Position: " , String.valueOf(position));
for (int i = 0; i < position; i++) {
viewHolder.txtStnArr.setEnable(false);
}
notifyDataSetChanged();
}
});
I have implemented an recycler view with Multi Select successfully using addOnItemTouchListener for identifying and selecting using single and double click.When i have Less than 5 items int the recycler view,Everything works fine but when i have more data,to be exact when the recycler view starts recycling the view,my selection is going crazy and it selects differnt possition.I logged out to see the clicking position,those seems to be right but something is not right which makes my selection wrong.I'm new to programming and to android app development.Can anyone take alot at this and help me out please,Here is my code
My adapter class
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactHolder> implements SectionIndexer, Filterable {
public List<Contact> contactList;
List<Contact> filteredUsersList;
CustomFilter filter;
Context mContext;
int itemResource;
ArrayList<Contact> selected_usersList = new ArrayList<>();
int pos;
private ArrayList<Integer> mSectionPositions;
ContactAdapter(Context mContext, int itemResource, List<Contact> contactList, ArrayList<Contact> selectedList) {
this.contactList = contactList;
this.mContext = mContext;
this.itemResource = itemResource;
this.selected_usersList = selectedList;
this.filteredUsersList = contactList;
}
#Override
public ContactHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(itemResource, parent, false);
return new ContactHolder(v);
}
#Override
public void onBindViewHolder(final ContactHolder holder, int position) {
pos = position;
final Contact contact = contactList.get(pos);
holder.colg.setText(contact.getColg());
holder.name.setText(contact.getName());
holder.job.setText(contact.getJob());
if (contact.getImage() != null)
holder.img.setImageBitmap(Utility.getPhoto(contact.getImage()));
}
#Override
public int getItemCount() {
return this.contactList.size();
}
class ContactHolder extends RecyclerView.ViewHolder {
private TextView name, colg, job, id, mentee, mentor, participant;
private ImageView selected;
// private PorterShapeImageView img;
private HexagonMaskView img;
private RelativeLayout rr_layout;
ItemClickListener itemClickListener;
ContactHolder(View itemView) {
super(itemView);
// Set up the UI widgets of the holder
// img = (PorterShapeImageView) itemView.findViewById(R.id.contact_image);
img = (HexagonMaskView) itemView.findViewById(R.id.contact_image);
name = (TextView) itemView.findViewById(R.id.contact_name);
colg = (TextView) itemView.findViewById(R.id.contact_colg);
job = (TextView) itemView.findViewById(R.id.contact_job);
mentee = (TextView) itemView.findViewById(R.id.mentee);
mentor = (TextView) itemView.findViewById(R.id.mentor);
participant = (TextView) itemView.findViewById(R.id.participant);
rr_layout = (RelativeLayout) itemView.findViewById(R.id.rr_layout);
selected = (ImageView) itemView.findViewById(R.id.tic_contact_selected);
}
}
}
My RecyclerItemClickListener Class
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickListener mListener;
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null) {
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
My Implementation of addOnItemTouchListener
contactsRecyclerViewT.addOnItemTouchListener(new RecyclerItemClickListener(this, contactsRecyclerViewT, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, final int position) {
Log.e("tag", "" + position);
for (int i = 0; i < multiselect_list.size(); i++) {
Log.e("tag", "sss" + multiselect_list.get(i).getName());
}
pos = position;
contact = contactArrayList.get(position);
menteeTextView = (TextView) view.findViewById(R.id.mentee);
mentorTextView = (TextView) view.findViewById(R.id.mentor);
participantTextView = (TextView) view.findViewById(R.id.participant);
rr_layout = (RelativeLayout) view.findViewById(R.id.rr_layout);
selected = (ImageView) view.findViewById(R.id.tic_contact_selected);
img = (HexagonMaskView) view.findViewById(R.id.contact_image);
name = (TextView) view.findViewById(R.id.contact_name);
if (isMultiSelect) {
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
multi_select(position);
if (multiselect_list.contains(contactArrayList.get(position))) {
contact.setStatus("0");
Log.e("tag", "setStatus" + contact.getStatus());
Log.e("tag", "position " + position);
rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.bg_card_selected));
selected.setVisibility(View.VISIBLE);
mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
menteeTextView.setVisibility(View.VISIBLE);
mentorTextView.setVisibility(View.VISIBLE);
participantTextView.setVisibility(View.VISIBLE);
menteeTextView.setClickable(true);
mentorTextView.setClickable(true);
participantTextView.setClickable(true);
} else {
rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.cement));
selected.setVisibility(View.GONE);
Log.e("tag", "position " + position);
menteeTextView.setVisibility(View.GONE);
mentorTextView.setVisibility(View.GONE);
participantTextView.setVisibility(View.GONE);
menteeTextView.setClickable(false);
mentorTextView.setClickable(false);
participantTextView.setClickable(false);
}
}
});
mentorTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
contact.setStatus("1");
Log.e("tag", "setStatus" + contact.getStatus());
mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
}
});
menteeTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
contact.setStatus("0");
Log.e("tag", "setStatus" + contact.getStatus());
mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
}
});
participantTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
contact.setStatus("2");
Log.e("tag", "setStatus" + contact.getStatus());
mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
}
});
name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(ContactsActivity.this, OtherProfileActivity.class);
intent.putExtra("id", Integer.parseInt(contactArrayList.get(position).getId()));
startActivity(intent);
}
});
} else {
Intent intent = new Intent(ContactsActivity.this, OtherProfileActivity.class);
intent.putExtra("id", Integer.parseInt(contactArrayList.get(position).getId()));
startActivity(intent);
}
// contactList.get(position).setStatus("1");
// contactList.get(position).setStatus("0");
}
#Override
public void onItemLongClick(View view, int position) {
contact = contactArrayList.get(position);
Log.e("tag", "" + position);
for (int i = 0; i < multiselect_list.size(); i++) {
Log.e("tag", "sss" + multiselect_list.get(i).getName());
}
menteeTextView = (TextView) view.findViewById(R.id.mentee);
mentorTextView = (TextView) view.findViewById(R.id.mentor);
participantTextView = (TextView) view.findViewById(R.id.participant);
rr_layout = (RelativeLayout) view.findViewById(R.id.rr_layout);
selected = (ImageView) view.findViewById(R.id.tic_contact_selected);
img = (HexagonMaskView) view.findViewById(R.id.contact_image);
name = (TextView) view.findViewById(R.id.contact_name);
if (!isMultiSelect) {
multiselect_list = new ArrayList<>();
isMultiSelect = true;
if (mActionMode == null) {
mActionMode = startActionMode(mActionModeCallback);
}
}
multi_select(position);
if (multiselect_list.contains(contactArrayList.get(position))) {
rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.bg_card_selected));
selected.setVisibility(View.VISIBLE);
contact.setStatus("0");
Log.e("tag", "setStatus" + contact.getStatus());
Log.e("tag", "position " + position);
mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
menteeTextView.setVisibility(View.VISIBLE);
mentorTextView.setVisibility(View.VISIBLE);
participantTextView.setVisibility(View.VISIBLE);
menteeTextView.setClickable(true);
mentorTextView.setClickable(true);
participantTextView.setClickable(true);
} else {
rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.cement));
selected.setVisibility(View.GONE);
Log.e("tag", "position " + position);
menteeTextView.setVisibility(View.GONE);
mentorTextView.setVisibility(View.GONE);
participantTextView.setVisibility(View.GONE);
menteeTextView.setClickable(false);
mentorTextView.setClickable(false);
participantTextView.setClickable(false);
}
}
}));
ArrayList<AlphabetItem> mAlphabetItems = new ArrayList<>();
List<String> strAlphabets = new ArrayList<>();
for (int i = 0; i < contactArrayList.size(); i++) {
Contact contact = contactArrayList.get(i);
String name = contact.getName();
if (name == null || name.trim().isEmpty())
continue;
String word = name.substring(0, 1);
if (!strAlphabets.contains(word)) {
strAlphabets.add(word);
mAlphabetItems.add(new AlphabetItem(i, word, false));
}
}
}
add boolena array
boolean [] itemcheck;
initialize in constructor wit your arraylist.
itemcheck = new boolean[feedItemList.size()];
check in bindview holder like this
if(itemcheck[position]==true){
holder.row_linearlayout.setBackgroundColor(Color.parseColor("#b7c5ea"));
}else {
holder.row_linearlayout.setBackgroundColor(0xFFFFFFFF);
//holder.row_linearlayout.setBackgroundResource(R.drawable.blurback);
}
and set ture or false onclick of your relativelayout controle instead of any other controle .
holder.row_linearlayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LinearLayout Lout = (LinearLayout) v.findViewById(R.id.selectlinear);
if(model.isSelected()){
Lout.setBackgroundColor(0xFFFFFFFF);
itemcheck[position]=false;
//get all other controle value here
}else{
Lout.setBackgroundColor(Color.parseColor("#b7c5ea"));
itemcheck[position]=true;
//get all other controle value here
}
}
});
You are doing most of the view manipulation in Onclick listener, you should move that to you adapter onBindView, because even if you set in Onclick listener, it will modify when user scroll.
I am not giving complete view manipulation, I am just giving the hint how we should do.
#Override
public void onBindViewHolder(final ContactHolder holder, int position) {
pos = position;
final Contact contact = contactList.get(pos);
holder.colg.setText(contact.getColg());
holder.name.setText(contact.getName());
holder.job.setText(contact.getJob());
if (contact.getImage() != null)
holder.img.setImageBitmap(Utility.getPhoto(contact.getImage()));
if (multiselect_list.contains(contactArrayList.get(position))) { // May be you should check form your fragment or actvity using listeners
holder.mentee.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
holder.participant.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
holder.mentee.setVisibility(View.VISIBLE);
holder.participant.setVisibility(View.VISIBLE);
} else {
holder.mentee.setVisibility(View.GONE);
holder.participant.setVisibility(View.GONE);
}
}
I have it clicked and it gets up to it and shows the right getText() method but the setText method is not working...
userAdapter.setOnEntryClickListener(new UserAdapter.OnEntryClickListener() {
#Override
public void onEntryClick(View view, int position) {
DatabaseUser user = dbUsersList.get(position);
TextView clickedView = (TextView) view.findViewById(R.id.userAdapterFollowBtn);
if(view == clickedView) {
if (clickedView.getText().equals("following")) {
Log.d(Constants.DEBUG, " THE CLICK VIEW IS " + clickedView.getText());
//APPLY Following
String txtFollow = "follow";
clickedView.setText(txtFollow);
if (user.getIsChanged() == 0) {
user.setIsChanged(1);
} else {
user.setIsChanged(0);
}
user.setIsType(3);
db.updateFollow(user);
userAdapter.notifyDataSetChanged();
} else {
clickedView.setText("following");
if (user.getIsChanged() == 0) {
user.setIsChanged(1);
} else {
user.setIsChanged(0);
}
user.setIsType(0);
db.updateFollow(user);
userAdapter.notifyDataSetChanged();
}
} else {
Toast.makeText(getApplicationContext(), user.getUsername() + " is selected!", Toast.LENGTH_SHORT).show();
takeToUserProfile(dbUsersList.get(position));
}
}
});
Here is the adapter class:
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.MyViewHolder> {
private List<DatabaseUser> dbUsersList, followingList;
private DatabaseHelper db;
private Context context;
private Typeface typeFace, italicTypeface, boldTypeface;
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView userAdapterUsername, userAdapterFollowBtn;
public ImageView userAdapterUserPicture;
public MyViewHolder(View view) {
super(view);
userAdapterUsername = (TextView) view.findViewById(R.id.userAdapterUsername);
userAdapterFollowBtn = (TextView) view.findViewById(R.id.userAdapterFollowBtn);
userAdapterUserPicture = (ImageView) view.findViewById(R.id.userAdapterUserPicture);
Log.d(Constants.DEBUG, "IN MY VIEW HOLDER");
view.setOnClickListener(this);
userAdapterFollowBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (mOnEntryClickListener != null) {
Log.d(Constants.DEBUG, "IN On click");
mOnEntryClickListener.onEntryClick(v, getAdapterPosition());
}
}
}
private static OnEntryClickListener mOnEntryClickListener;
public interface OnEntryClickListener {
void onEntryClick(View view, int position);
}
public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
mOnEntryClickListener = onEntryClickListener;
}
public UserAdapter(Context mContext, List<DatabaseUser> usersList, List<DatabaseUser> passedFollowing, Typeface myTypeface, Typeface myTypefaceItalic, Typeface myTypefaceBold) {
context = mContext;
dbUsersList = usersList;
followingList = passedFollowing;
typeFace = myTypeface;
italicTypeface = myTypefaceItalic;
boldTypeface = myTypefaceBold;
Log.d(Constants.DEBUG, "IN MY User ADAPTER CONSTRUCTOR");
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.follow_item, parent, false);
Log.d(Constants.DEBUG, "RETURN ITEM VIEW HOLDER");
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
DatabaseUser user = dbUsersList.get(position);
holder.userAdapterUsername.setTypeface(boldTypeface);
holder.userAdapterUsername.setText(user.getUsername());
final int pos = getItemViewType(position);
//TODO Create pic link
if(containsId(dbUsersList.get(pos), followingList)) {
//Then show following
holder.userAdapterFollowBtn.setText("following");
} else {
//show follow
holder.userAdapterFollowBtn.setText("follow");
}
String userspic = dbUsersList.get(pos).getPicture();
if(userspic == null) {
//SET DEFAULT OR PUT DEFAULT IN XML AND DO NOTHING IT SHOULD SHOW DEFAULT PIC
} else {
//TODO setupUser Pic
String img1 = "http://www.hindustantimes.com/Images/popup/2015/6/kungfu2.jpg";
Picasso.with(context).load(img1).transform(new RoundedTransformation()).into(holder.userAdapterUserPicture);
}
}
#Override
public int getItemCount() {
return dbUsersList.size();
}
public static boolean containsId(DatabaseUser currentUser, List<DatabaseUser> list) {
for (DatabaseUser object : list) {
if (currentUser.getUserId().equals(object.getUserId())) {
return true;
}
}
return false;
}
#Override
public int getItemViewType(int position) {
return position;
}
}
your dbUsersList is not updating. please check your user object in dbUsersList after notify data set change.
What ended up being the problem is that I had passed in the followingList, so I never re-called to grab the new following from the db on update. The update was happening I just had to re-grab the followingList from the db to have an updated list to check against like so in a new method that was passing the list back to the contains method.
db.grabFollowersList();
I need to change the color for selected listview item for different color. I had to implemented for the below code for changing list item color, but if I select the 1st item of the visible Item after scrolling it had to change the color every newly visibled item. Anyone can suggest me for the best solution.
Code snippet.
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
PlayListItem nature = mItems.get(i);
try {
if (nature.getmInnerTitle() != null && nature.getmInnerTVName() != null) {
viewHolder.tvInnerTitle.setText(nature.getmInnerTitle());
mVideoID = nature.getmInnerVideoID();
Picasso.with(activity)
.load(nature.getmInnerThumpnailURL())
/* .placeholder(R.drawable.my_thumnail_small)*/
.into(viewHolder.imgInnerThumbnail);
viewHolder.tvInnerTVName.setText("by " + nature.getmInnerTVName());
}
} catch (NullPointerException e) {
e.printStackTrace();
}
viewHolder.item_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Save Value------Inner-------->" + save);
Toast.makeText(activity, "Position---->" + i + " Playlist ID : ", Toast.LENGTH_LONG).show();
// Change BG color for selected List Item
VideoPlayActivity.mRecyclerView.getChildAt(i).setBackgroundColor(
Color.parseColor("#EEEEEE"));
System.out.println("Save Value------1-------->" + save);
if (save != -1 && save != i) {
VideoPlayActivity.mRecyclerView.getChildAt(save).setBackgroundColor(
Color.parseColor("#FFFFFF"));
System.out.println("Save Value------2-------->" + save);
}
save = i;
System.out.println("Save Value------3-------->" + save);
}
});
viewHolder.itemView.post(new Runnable() {
#Override
public void run() {
int cellWidth = viewHolder.itemView.getWidth();// this will give you cell width dynamically
int cellHeight = viewHolder.itemView.getHeight();// this will give you cell height dynamically
mdynamicHeight.HeightChange(i, cellHeight); //call your iterface hear
}
});
}
Yes Finally I got the answer. Here the working code snippet.
private int focusedItem = 0;
#Override
public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
// Handle key up and key down and attempt to move selection
recyclerView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
// Return false if scrolled to the bounds and allow focus to move off the list
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
return tryMoveSelection(lm, 1);
} else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
return tryMoveSelection(lm, -1);
}
}
return false;
}
});
}
private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) {
int tryFocusItem = focusedItem + direction;
// If still within valid bounds, move the selection, notify to redraw, and scroll
if (tryFocusItem >= 0 && tryFocusItem < getItemCount()) {
notifyItemChanged(focusedItem);
focusedItem = tryFocusItem;
notifyItemChanged(focusedItem);
lm.scrollToPosition(focusedItem);
return true;
}
return false;
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
PlayListItem nature = mItems.get(i);
try {
if (nature.getmInnerTitle() != null && nature.getmInnerTVName() != null) {
viewHolder.tvInnerTitle.setText(nature.getmInnerTitle());
mVideoID = nature.getmInnerVideoID();
Picasso.with(activity)
.load(nature.getmInnerThumpnailURL())
/* .placeholder(R.drawable.my_thumnail_small)*/
.into(viewHolder.imgInnerThumbnail);
viewHolder.tvInnerTVName.setText("by " + nature.getmInnerTVName());
}
} catch (NullPointerException e) {
e.printStackTrace();
}
viewHolder.itemView.setSelected(focusedItem == i);
viewHolder.itemView.post(new Runnable() {
#Override
public void run() {
int cellWidth = viewHolder.itemView.getWidth();// this will give you cell width dynamically
int cellHeight = viewHolder.itemView.getHeight();// this will give you cell height dynamically
mdynamicHeight.HeightChange(i, cellHeight); //call your iterface hear
}
});
}
#Override
public int getItemCount() {
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imgInnerThumbnail;
public TextView tvInnerTitle;
public TextView tvInnerVideoID;
public TextView tvInnerCount;
public TextView tvInnerTVName;
public View item_view;
public ViewHolder(View itemView) {
super(itemView);
imgInnerThumbnail = (ImageView) itemView.findViewById(R.id.img_innerView);
tvInnerTitle = (TextView) itemView.findViewById(R.id.txt_InnerTitle);
//tvInnerID = (TextView) itemView.findViewById(R.id.);
tvInnerTVName = (TextView) itemView.findViewById(R.id.txt_InnerTVName);
item_view = itemView;
item_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
notifyItemChanged(focusedItem);
focusedItem = getLayoutPosition();
notifyItemChanged(focusedItem);
}
});
}
}