When scroll recyclerview some items mixes. After I add ads after every 15 items, holder get wrong data. Some items are vip items. I will change background color of these items. But when I scroll it dublicates mixes. How can I solve?
This is my adapter
private Context mCtx;
private List<Car> carList;
private RecyclerViewAnimator mAnimator;
private int AD_TYPE=1;
private int CONTENT_TYPE=2;
private int LIST_AD_DELTA=15;
public ProductAllCarAdapter(RecyclerView recyclerView,Context mCtx, List<Car> carList) {
this.mCtx = mCtx;
this.carList = carList;
mAnimator = new RecyclerViewAnimator(recyclerView);
}
#Override
public ProductAllCarAdapter.ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == AD_TYPE){
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_add_item, null);
ProductAllCarAdapter.ProductViewHolder vh = new ProductAllCarAdapter.ProductViewHolder(itemView);
mAnimator.onCreateViewHolder(itemView);
return vh;
} else {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_car_item, null);
ProductAllCarAdapter.ProductViewHolder vh = new ProductAllCarAdapter.ProductViewHolder(itemView);
mAnimator.onCreateViewHolder(itemView);
return vh;
}
}
#Override
public int getItemViewType(int position) {
if (position>0 && position % LIST_AD_DELTA == 0)
return AD_TYPE;
return CONTENT_TYPE;
}
#Override
public void onBindViewHolder(ProductAllCarAdapter.ProductViewHolder holder, int position) {
if (getItemViewType(position) == CONTENT_TYPE) {
final Car car = carList.get(holder.getAdapterPosition());
GlideApp.with(mCtx).load(car.getImg()).into(holder.imageView);
if (car.getVip() == 1) {
holder.relativeLayout.setBackgroundColor(ContextCompat.getColor(mCtx, R.color.colorVip));
holder.imageViewVIP.setVisibility(View.VISIBLE);
}
final String carid = String.valueOf(car.getCarid());
mAnimator.onBindViewHolder(holder.itemView, position);
} else {
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Context mcontext = view.getContext();
Bundle bundle = ActivityOptionsCompat.makeCustomAnimation(mcontext, android.R.anim.fade_in, android.R.anim.fade_out).toBundle();
Intent intent = new Intent(mcontext, AdsItem.class);
mcontext.startActivity(intent, bundle);
}
});
mAnimator.onBindViewHolder(holder.itemView, position);
}
}
private int getRealPosition(int position) {
if (LIST_AD_DELTA == 0) {
return position;
} else {
return position - position / LIST_AD_DELTA;
}
}
#Override
public long getItemId(int position) { return position; }
#Override
public int getItemCount() {
int additionalContent = 0;
if (carList.size() > 0 && carList.size() > LIST_AD_DELTA) {
additionalContent = ( carList.size() / LIST_AD_DELTA);
}
return carList.size() + additionalContent;
}
public static class ProductViewHolder extends RecyclerView.ViewHolder {
private View mView;
ImageView imageView, imageViewVIP;
RelativeLayout relativeLayout;
public ProductViewHolder(View itemView) {
super(itemView);
mView = itemView;
imageView = itemView.findViewById(R.id.imageView);
imageViewVIP = itemView.findViewById(R.id.imageViewVIP);
relativeLayout = itemView.findViewById(R.id.relativeLayoutpc);
}
public void setOnClickListener(View.OnClickListener listener) {
mView.setOnClickListener(listener);
}
}
I think problem onBindViewHolder function use wrong holder. ArrayList also return true value but on scroll it mixes.
You just have to add the corresponding else of the following if statement block.
if (car.getVip() == 1) {
holder.relativeLayout.setBackgroundColor(ContextCompat.getColor(mCtx, R.color.colorVip));
holder.imageViewVIP.setVisibility(View.VISIBLE);
} else {
holder.relativeLayout.setBackgroundColor(ContextCompat.getColor(mCtx, R.color.colorNormal));
holder.imageViewVIP.setVisibility(View.GONE);
}
This is inside your onBindViewHolder function where the view type is CONTENT_TYPE.
Hope that solves your problem.
Related
I got a weird exception in the function onCreateViewHolder inside my custom adapter. Probably because getItemViewType function returns different values as expected.
This is how getItemViewType function looks like:
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
#Override
public int getItemViewType(int position) {
if (position == 0)
return TYPE_HEADER;
return TYPE_ITEM;
}
As you can see, it returns 0 or 1 only, no other option.
This is how onCreateViewHolder function looks like:
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_groups, null);
return new HeaderHolder(view);
} else if(viewType == TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.explore_group_row, null);
return new ItemHolder(view);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " make sure your using types correctly");
}
However, I got some crashes from crashlytics that there is no type that matches with viewTypes of 6, 7, 8, 11, etc.. Not sure where it gets from...
In addition, I can't reproduce this issue, no idea how it happens.
I saw a similar issue in this thread but no solution.
Here you can see the exception from crashlytics:
Fatal Exception: java.lang.RuntimeException: there is no type that matches the type 6 make sure your using types correctly
at com.example.eliran.forum.GroupsFragment$GroupsAdapter.onCreateViewHolder(GroupsFragment.java:72)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5)
at androidx.recyclerview.widget.RecyclerView$Recycler.a(RecyclerView.java:295)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:14)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:15)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:22)
at androidx.recyclerview.widget.GapWorker.a(GapWorker.java:3)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:71)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7078)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
Here's the full code of the adapter:
private class GroupsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_groups, null);
return new HeaderHolder(view);
} else if(viewType == TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.explore_group_row, null);
return new ItemHolder(view);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " make sure your using types correctly");
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) {
if (holder instanceof ItemHolder) {
ItemHolder theHolder = (ItemHolder) holder;
Group group = groups.get(i - 1);
theHolder.title.setText(group.getTitle());
theHolder.description.setText(group.getDescription());
if(group.getImage() != null) {
Picasso.get()
.load(group.getImage())
.fit()
.into(theHolder.image);
} else {
Picasso.get()
.load(R.drawable.profile_picture_holder)
.fit()
.into(theHolder.image);
}
} else if (holder instanceof HeaderHolder){
HeaderHolder theHolder = (HeaderHolder) holder;
if (showMyGroupsPb) {
theHolder.myGroupsPb.setVisibility(View.VISIBLE);
theHolder.myGroupSectionHeader.setOnBtnListener(null);
} else {
theHolder.myGroupsPb.setVisibility(View.GONE);
theHolder.myGroupSectionHeader.setOnBtnListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(rootView.getContext(), MyGroupsActivity.class);
intent.putExtra("groups", myGroups);
startActivityForResult(intent, TheFinals.JOIN_LEAVE_GROUP_CODE);
}
});
}
}
}
#Override
public int getItemViewType(int position) {
if (position == 0)
return TYPE_HEADER;
return TYPE_ITEM;
}
#Override
public int getItemCount() {
return groups.size() + 1;
}
class HeaderHolder extends RecyclerView.ViewHolder {
private ProgressBar myGroupsPb;
private SectionHeader myGroupSectionHeader;
public HeaderHolder(View view) {
super(view);
myGroupsRv = view.findViewById(R.id.groupsRecyclerView);
myGroupsPb = view.findViewById(R.id.pb);
LinearLayoutManager horizontalLayoutManager
= new LinearLayoutManager(rootView.getContext(), LinearLayoutManager.HORIZONTAL, false);
myGroupsRv.setLayoutManager(horizontalLayoutManager);
myGroupsRv.setAdapter(myGroupAdapter);
myGroupSectionHeader = view.findViewById(R.id.myGroupSectionHeader);
}
}
class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected TextView title;
protected ImageView image;
protected TextView description;
public ItemHolder(View view) {
super(view);
this.title = view.findViewById(R.id.title);
this.image = view.findViewById(R.id.image);
this.description = view.findViewById(R.id.description);
view.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int itemPosition = groupsRecyclerView.getChildLayoutPosition(view) - 1;
selectedGroupIndex = itemPosition;
Intent intent = new Intent(rootView.getContext(), GroupActivity.class);
intent.putExtra("group", groups.get(itemPosition));
startActivityForResult(intent, TheFinals.JOIN_LEAVE_GROUP_CODE);
}
}
}
I have a horizontal RecyclerView that displays 7 images from the users device (changing as user keeps taking pictures). I would like to add a default icon at the end of the 7 images, with an onclick capability. How can I go about doing this?
Something like this:
In the image above the plus icon should be the default icon, however it should be at the end of the images.
UPDATED:
RecentPhotosAdapter.java
public class RecentPhotosAdapter extends RecyclerView.Adapter<RecentPhotosAdapter.ViewHolder> {
// Variables
private Context mContext;
private ArrayList<String> mImage;
private int VIEW_TYPE_DEFAULT = 0;
private int VIEW_TYPE_IMAGE = 1;
// Limit the recent photo selection
int RECENT_PHOTO_LIMIT = 7;
public RecentPhotosAdapter(Context mContext, ArrayList<String> mImage) {
this.mContext = mContext;
this.mImage = mImage;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_IMAGE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recent_photos_item, parent, false);
return new ViewHolder(view);
}
else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.default_select_photos_item, parent, false);
return new ViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
if(position < Math.min(mImage.size(), RECENT_PHOTO_LIMIT)){
String images = mImage.get(position);
// Recent Photos
Glide.with(mContext)
.load(images)
.placeholder(R.drawable.background_gallery_placeholder)
.transform(new CenterCrop(), new RoundedCorners(30))
.into(holder.recent_photos_iv);
// Default select photos
holder.recent_photos_iv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do something here
// Take user to image select slider
}
});
}
else {
//code for default view
}
}
#Override
public int getItemViewType(int position) {
return (position == mImage.size()) ? VIEW_TYPE_DEFAULT : VIEW_TYPE_IMAGE;
}
#Override
public int getItemCount() {
return Math.min(mImage.size(), RECENT_PHOTO_LIMIT) + 1;
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView recent_photos_iv;
ImageView default_select_photo_iv;
public ViewHolder(View itemView) {
super(itemView);
recent_photos_iv = itemView.findViewById(R.id.recent_photos_iv);
default_select_photo_iv = itemView.findViewById(R.id.default_select_photo_iv);
}
}
}
You can achieve this by making the default icon as a "ViewType" of your adapter.
Override getItemViewType to return a different value for your last item.
#Override
public int getItemViewType(int position) {
return (position == mData.size()) ? VIEW_TYPE_DEFAULT : VIEW_TYPE_IMAGE;
}
Now in the onCreateViewHolder, handle both the view Types.
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_IMAGE) {
//Create viewholder for your images
}
else {
//Create viewholder for default view
}
}
Add 1 to your ItemList size to accomodate this extra view:
#Override
public int getItemCount() {
return mData.size() + 1;
}
Your Updated code:
public class RecentPhotosAdapter extends RecyclerView.Adapter<RecentPhotosAdapter.ViewHolder> {
// Variables
private Context mContext;
private ArrayList<String> mImage;
private int VIEW_TYPE_DEFAULT=0;
private int VIEW_TYPE_IMAGE=1;
public RecentPhotosAdapter(Context mContext, ArrayList<String> mImage) {
this.mContext = mContext;
this.mImage = mImage;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_IMAGE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recent_photos_item, parent, false);
return new ViewHolder(view);
}
else {
//Create viewholder for default view
}
}
#Override
public int getItemViewType(int position) {
return (position == Math.min(mImage.size(), RECENT_PHOTO_LIMIT)) ?VIEW_TYPE_DEFAULT : VIEW_TYPE_IMAGE;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
if(position < Math.min(mImage.size(), RECENT_PHOTO_LIMIT)){
String images = mImage.get(position);
Glide.with(mContext)
.load(images)
.placeholder(R.drawable.background_gallery_placeholder)
.transform(new CenterCrop(), new RoundedCorners(30))
.into(holder.recent_photos_iv);
holder.recent_photos_iv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do something here
// Take user to image select slider
}
});
}
else {
//code for default view
}
}
#Override
public int getItemCount() {
// Limit the recent photo selection
int RECENT_PHOTO_LIMIT = 7;
return Math.min(mImage.size(), RECENT_PHOTO_LIMIT)+1;
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView recent_photos_iv;
public ViewHolder(View itemView) {
super(itemView);
recent_photos_iv = itemView.findViewById(R.id.recent_photos_iv);
}
}
}
I have a fragment with a recyclerView.
A user is allowed to delete an exercise logEntry by swiping right.
A user can also update a logEntry by clicking on the recyclerView item.
(This highlights the current selected item green, hides the clear button and converts the save button to an update button.)
To deselect the item , the user can click on the recyclerView a second time.
Unfortunately, if a user was to select an item and then decides to swipe to delete an item, the recyclerView item which takes the same position as the originally selected item is remains highlighted green.
When a user swipes to delete an item, I would like the background of all recyclerView items to be reset to grey.
How could this be done?
Relevant Fragment Code
OnExerciseClicked
#Override
public void onExerciseClicked(int position) {
if (recyclerItemClicked == false) {
saveBtn.setText("Update");
clearBtn.setVisibility(View.GONE);
recyclerItemClicked = true;
double selectedWeight = adapter.getWeight(position);
String selectedWeightString = Double.toString(selectedWeight);
editTextWeight.setText(selectedWeightString);
int selectedReps = adapter.getReps(position);
String selectedRepsString = Integer.toString(selectedReps);
editTextReps.setText(selectedRepsString);
} else {
clearBtn.setVisibility(View.VISIBLE);
saveBtn.setText("Save");
recyclerItemClicked = false;
}
}
OnSwiped
ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int logID = allExercises.get(viewHolder.getAdapterPosition()).getLog_id();
logViewModel.deleteByID(logID);
clearBtn.setVisibility(View.VISIBLE);
saveBtn.setText("Save");
adapter.notifyDataSetChanged();
}
};
Adapter
public class CompletedExercisesListAdapter2 extends RecyclerView.Adapter {
private OnExerciseClickListener onExerciseClickListener;
private List<Log_Entries> allCompletedExercises = new ArrayList<>();
private int adapterPos = -1;
public boolean flag = false;
public CompletedExercisesListAdapter2(ArrayList<Log_Entries> allCompletedExercises, OnExerciseClickListener onExerciseClickListener) {
this.allCompletedExercises = allCompletedExercises;
this.onExerciseClickListener = onExerciseClickListener;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view;
if (viewType == 0) {
view = layoutInflater.inflate(R.layout.new_completed_exercise_item, parent, false);
return new ViewHolderOne(view, onExerciseClickListener);
}
view = layoutInflater.inflate(R.layout.completed_exercise_item, parent, false);
return new ViewHolderTwo(view, onExerciseClickListener);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == 0) {
ViewHolderOne viewHolderOne = (ViewHolderOne) holder;
if (adapterPos == position) {
viewHolderOne.relativeLayout.setBackgroundColor(Color.parseColor("#567845"));
} else {
viewHolderOne.relativeLayout.setBackgroundResource(R.color.dark_grey);
}
viewHolderOne.textViewExerciseName.setText(String.valueOf(allCompletedExercises.get(position).getChildExerciseName()));
//viewHolderOne.textViewSetNumber.setText(String.valueOf(allCompletedExercises.get(position).getSet_number()));
viewHolderOne.textViewSetNumber.setText(String.valueOf(viewHolderOne.getAdapterPosition() + 1));
viewHolderOne.textViewWeight.setText(String.valueOf(allCompletedExercises.get(position).getTotal_weight_lifted()));
viewHolderOne.textViewReps.setText(String.valueOf(allCompletedExercises.get(position).getReps()));
} else if (getItemViewType(position) == 1) {
ViewHolderTwo viewHolderTwo = (ViewHolderTwo) holder;
if (adapterPos == position) {
viewHolderTwo.relativeLayout.setBackgroundColor(Color.parseColor("#567845"));
} else {
viewHolderTwo.relativeLayout.setBackgroundResource(R.color.dark_grey);
}
// viewHolderTwo.textViewSetNumber.setText(String.valueOf(allCompletedExercises.get(position).getSet_number()));
viewHolderTwo.textViewSetNumber.setText(String.valueOf(viewHolderTwo.getAdapterPosition() + 1));
viewHolderTwo.textViewWeight.setText(String.valueOf(allCompletedExercises.get(position).getTotal_weight_lifted()));
viewHolderTwo.textViewReps.setText(String.valueOf(allCompletedExercises.get(position).getReps()));
}
}
#Override
public int getItemCount() {
return allCompletedExercises.size();
}
#Override
public int getItemViewType(int position) {
// if list is sorted chronologically
if (position == 0) {
return 0;
}
if (allCompletedExercises.get(position).getChildExerciseName().equals(allCompletedExercises.get(position - 1).getChildExerciseName())) {
return 1;
} else {
return 0;
}
}
class ViewHolderOne extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView textViewExerciseName;
private TextView textViewSetNumber;
private TextView textViewWeight;
private TextView textViewReps;
OnExerciseClickListener mOnExerciseClickListener;
private RelativeLayout relativeLayout;
public ViewHolderOne(#NonNull View itemView, OnExerciseClickListener onExerciseClickListener) {
super(itemView);
textViewExerciseName = itemView.findViewById(R.id.textView_ExerciseName3);
textViewSetNumber = itemView.findViewById(R.id.textView_Set_Number56);
textViewWeight = itemView.findViewById(R.id.textView_weight78);
textViewReps = itemView.findViewById(R.id.textView_repss0);
mOnExerciseClickListener = onExerciseClickListener;
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.exercise_item_relative);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onExerciseClickListener.onExerciseClicked(getAdapterPosition());
if (flag) {
adapterPos = -1;
flag = false;
} else {
adapterPos = getAdapterPosition();
flag = true;
}
notifyDataSetChanged();
}
}
class ViewHolderTwo extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView textViewSetNumber;
private TextView textViewWeight;
private TextView textViewReps;
OnExerciseClickListener mOnExerciseClickListener;
private RelativeLayout relativeLayout;
public ViewHolderTwo(#NonNull View itemView, OnExerciseClickListener onExerciseClickListener) {
super(itemView);
textViewSetNumber = itemView.findViewById(R.id.textView_Set_Number);
textViewWeight = itemView.findViewById(R.id.textView_weight);
textViewReps = itemView.findViewById(R.id.textView_repss);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.exercise_item_rel);
mOnExerciseClickListener = onExerciseClickListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onExerciseClickListener.onExerciseClicked(getAdapterPosition());
if (!flag) {
adapterPos = getAdapterPosition();
flag = true;
} else {
adapterPos = -1;
flag = false;
}
notifyDataSetChanged();
}
}
public interface OnExerciseClickListener {
void onExerciseClicked(int position);
}
public double getWeight(int position) {
double weight = allCompletedExercises.get(position).getTotal_weight_lifted();
return weight;
}
public int getReps(int position) {
int reps = allCompletedExercises.get(position).getReps();
return reps;
}
}
I highly recommend using a library like Groupie to abstract away the complicated state management of RecyclerView. Otherwise you'll find this imperative style quickly becomes unmaintainable. The future is declarative UI (Compose etc). This way it is much easier to keep track of Items rather than positions.
It's quite hard to follow your code (you should use descriptive names for things, like isSelected instead of flag). However I think your problem lies in your bind function not returning false here:
if (adapterPos == position)
after you swipe. Use break points to work out why
I have a little bit problem.In my activity there is two Adapter one is for color selection and another is for size selection. While i clicked one of the item of color then recently the available size adapter should be change but i got problem in size adapter. it changes only when i click the size item. I research and try to solve problem but it doesnt works for me.
Here is my code.
AddToCartActivity.java
public class AddToCartActivity extends BaseActivity{
#Override
protected int getLayout() {
return R.layout.activity_add_to_cart;
}
#Override
protected void init() {
//api called here
}
// response of api
#Override
public void productDetail(ProductCommonModel productCommonModel,
ArrayList<ProductChildModel> productChildModels, HashMap<Integer,
ArrayList<ChildAttributeModel>> childWithAttribute, HashMap<Integer,
ArrayList<ChildImageModel>> childWithImages,
ArrayList<com.hazesoft.dokan.singleproductdetail.model.ColorModel>
colorModels, ArrayList<SizeModel> sizeModels,
ArrayList<RelatedProductModel> relatedProductModels) {
this.productCommonModel = productCommonModel;
this.productChildModels = productChildModels;
this.childWithAttribute = childWithAttribute;
this.childWithImages = childWithImages;
this.colorModels = colorModels;
this.sizeModels = sizeModels;
this.relatedProductModels = relatedProductModels;
tvProductName.setText(productCommonModel.getName());
if (productCommonModel.getSpecialPrice() == 0) {
tvSellingPrice.setText(getString(R.string.rs) + productCommonModel.getSellingPrice());
tvDiscount.setVisibility(View.GONE);
tvSpecialPrice.setVisibility(View.GONE);
} else {
tvSpecialPrice.setText(getString(R.string.rs) + productCommonModel.getSpecialPrice());
tvSellingPrice.setText(getString(R.string.rs) + productCommonModel.getSellingPrice());
tvSellingPrice.setPaintFlags(tvSellingPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
tvDiscount.setText(productCommonModel.getDiscount() + getString(R.string.percentage));
}
setChildDetail(childWithAttribute, productChildModels);
setColorModel(colorModels);
setSizeModel(sizeModels);
quantity = Integer.parseInt(tvQuantityCart.getText().toString());
}
// setcolor adapter
private void setColorModel(ArrayList<ColorModel> colorModels) {
MyColorGridViewAdapter adapter = new MyColorGridViewAdapter(this, colorModels);
gvColor.setAdapter(adapter);
gvColor.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
adapter.setSelectedPostion(position);
adapter.notifyDataSetChanged();
}
});
}
// set size adapter
private void setSizeModel(ArrayList<SizeModel> sizeModels) {
sizeCustomModels = new ArrayList<>();
for(int i=0;i<sizeModels.size();i++){
sizeCustomModels.add(new SizeCustomModel(sizeModels.get(i).getAttName(),0));
}
setCustomSizeModelToAdapter(sizeCustomModels);
}
// this is code when i click color and change the size adapter but size doesnt change recently only changes when i click any item of the size
public void getSelectedC0lor(String color) {
selectedColor = color;
selectedSize=null;
sizeCustomModels = new ArrayList<>();
availableSize = new ArrayList<>();
for (int i = 0; i < skuColorSIzeList.size(); i++) {
if (skuColorSIzeList.get(i).getColor().equals(selectedColor)) {
availableSize.add(skuColorSIzeList.get(i).getSize());
}
}
for(int i=0;i<sizeModels.size();i++){
String size = null;
int status=0;
for(int j=0;j<availableSize.size();j++){
if(sizeModels.get(i).getAttName().equals(availableSize.get(j))){
size = sizeModels.get(i).getAttName();
status = 1;
break;
}else {
size = sizeModels.get(i).getAttName();
status = 0;
}
}
sizeCustomModels.add(new SizeCustomModel(size,status));
}
sizeRecylerAdapter.getNewModel(sizeCustomModels);
/*sizeRecylerAdapter = new MyCustomSizeRecylerAdapter(sizeCustomModels,this);
rvSize.setAdapter(sizeRecylerAdapter);
sizeRecylerAdapter.notifyDataSetChanged();*/
/*setCustomSizeModelToAdapter(sizeCustomModels);*/
}
}
MyColorGridViewAdapter.java
public class MyColorGridViewAdapter extends BaseAdapter {
Context context;
List<ColorModel> colorModelList;
String select_color;
boolean ch =false;
int checkPosition = -1;
public MyColorGridViewAdapter(Context context, List<ColorModel> colorModelList) {
this.context = context;
this.colorModelList = colorModelList;
}
public void setSelectedPostion(int postion){
this.checkPosition = postion;
}
#Override
public int getCount() {
return colorModelList.size();
}
#Override
public Object getItem(int position) {
return colorModelList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView==null){
convertView = LayoutInflater.from(context).inflate(R.layout.custom_color_list_item,null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
Picasso.with(context).load(colorModelList.get(position).getImage()).into(holder.ivImage);
holder.tvColorName.setText(colorModelList.get(position).getAttName());
if(checkPosition==position){
holder.ivChecked.setVisibility(View.VISIBLE);
select_color = colorModelList.get(position).getAttName();
if( context instanceof AddToCartActivity){
((AddToCartActivity) context).getSelectedC0lor(select_color);
}
}else {
holder.ivChecked.setVisibility(View.GONE);
}
if(colorModelList.size()==1){
holder.ivChecked.setVisibility(View.VISIBLE);
select_color = colorModelList.get(position).getAttName();
if( context instanceof AddToCartActivity){
((AddToCartActivity) context).getSelectedC0lor(select_color);
}
}
return convertView;
}
class ViewHolder{
#BindView(R.id.view)
LinearLayout view;
#BindView(R.id.tv_color_name)
TextViewHelper tvColorName;
#BindView(R.id.iv_image)
ImageView ivImage;
#BindView(R.id.iv_checked)
ImageView ivChecked;
public ViewHolder(View view) {
ButterKnife.bind(this,view);
}
}
}
MyCustomSizeRecylerAdapter.java
public class MyCustomSizeRecylerAdapter extends RecyclerView.Adapter<MyCustomSizeRecylerAdapter.MyViewHolder> {
ArrayList<SizeCustomModel> sizeModels;
Context context;
int checkPosition = -1;
String selectedSize;
public MyCustomSizeRecylerAdapter(ArrayList<SizeCustomModel> sizeModels, Context context) {
this.sizeModels = sizeModels;
this.context = context;
}
public void getNewModel(ArrayList<SizeCustomModel> customModels) {
sizeModels.clear();
this.sizeModels = customModels;
selectedSize = null;
Log.d("sizemodel", "getNewModel: " + new Gson().toJson(sizeModels));
notifyDataSetChanged();
}
public void getSelectedPosition(int position) {
checkPosition = position;
notifyDataSetChanged();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.size_adapter, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tv_sizeName.setText(sizeModels.get(position).getSize());
holder.ll_sizeAdapter.setBackgroundResource(R.drawable.ellipse_register);
if (sizeModels.get(position).getStock_Status() == 0) {
holder.ll_mainview.setClickable(false);
holder.ll_sizeAdapter.setBackgroundResource(R.color.blue_700);
} else if (sizeModels.get(position).getStock_Status() == 1) {
holder.ll_sizeAdapter.setBackgroundResource(R.drawable.ellipse_register);
if (checkPosition == position) {
holder.ll_sizeAdapter.setBackgroundResource(R.drawable.ellipse_green);
holder.tv_sizeName.setTextColor(context.getResources().getColor(R.color.white));
selectedSize = sizeModels.get(position).getSize();
if (context instanceof AddToCartActivity) {
((AddToCartActivity) context).getSelectSize(selectedSize);
}
} else {
holder.ll_sizeAdapter.setBackgroundResource(R.drawable.ellipse_register);
holder.tv_sizeName.setTextColor(context.getResources().getColor(R.color.tv_black));
}
if (sizeModels.size() == 1) {
holder.ll_sizeAdapter.setBackgroundResource(R.drawable.ellipse_green);
holder.tv_sizeName.setTextColor(context.getResources().getColor(R.color.white));
selectedSize = sizeModels.get(position).getSize();
if (context instanceof AddToCartActivity) {
((AddToCartActivity) context).getSelectSize(selectedSize);
}
}
}
}
#Override
public int getItemCount() {
return sizeModels.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.tv_sizeName)
TextView tv_sizeName;
#BindView(R.id.ll_sizeAdapter)
LinearLayout ll_sizeAdapter;
#BindView(R.id.main_view)
LinearLayout ll_mainview;
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
At first both adapter will set data and after click color item the size adapter must be change but it only changes when i click any of the item. adapter.notifyDataSetChanged() doesnt work here for me.
Both Adapter set
When i click color item but doesnt change size adapter
when i click size item only change size adapter
Use Interface to bridge with two adapter and communicate with each other.
I have a created this design. Which consists of list of list.
Now I wanted to add a view as "See All" in every section at the end of every recycler view. I wanted like this which is done by paytm.
Here is my code. I have two recyclerview one is vertical and another is horizontal. Here is my BaseRowAdapter which contains another recyclerview.
BaseRowAdapter.java
public class BaseRowAdapter extends RecyclerView.Adapter<BaseRowAdapter.ViewHolder> {
public ArrayList<MainType> types;
private Context context;
private LayoutInflater layoutInflater;
public BaseRowAdapter(ArrayList<MainType> types, Context context) {
this.types = types;
this.context = context;
this.layoutInflater = LayoutInflater.from(context);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.vertical_scroll_single_entry, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.recyclerView.setAdapter(new BaseRowItemAdapter(context, types.get(position).list));
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView.setHasFixedSize(true);
holder.tvHeading.setText(types.get(position).name);
}
#Override
public int getItemCount() {
return types.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RecyclerView recyclerView;
TextView tvHeading;
public ViewHolder(View itemView) {
super(itemView);
recyclerView = (RecyclerView) itemView.findViewById(R.id.rvItems);
tvHeading = (TextView) itemView.findViewById(R.id.tvHeading);
}
}
}
And for Inner recyclerview I have to show see more layout at the end. I have done something like this. which result into crashing app.
BaseRowItemAdapter.java
public class BaseRowItemAdapter extends RecyclerView.Adapter<BaseRowItemAdapter.CustomViewHolder> {
private Context context;
private ArrayList<SubType> subTypes;
private LayoutInflater inflater;
public BaseRowItemAdapter(Context context, ArrayList<SubType> subTypes) {
this.context = context;
this.subTypes = subTypes;
this.inflater = LayoutInflater.from(context);
}
#Override
public int getItemViewType(int position) {
return (position == subTypes.size()) ? R.layout.see_more : R.layout.single_item_card;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
if (viewType == R.layout.single_item_card) {
view = inflater.inflate(R.layout.single_item_card, parent, false);
} else {
view = inflater.inflate(R.layout.see_more, parent, false);
}
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
SubType subType = subTypes.get(position);
if (position != subTypes.size()) {
holder.tvProductName.setText(subType.name);
Picasso.with(context).load(subType.image).into(holder.ivProduct);
if (!subType.disc.equals("0")) {
holder.tvDiscountPercentage.setText(subType.disc + "%");
holder.tvActualAmount.setPaintFlags(holder.tvActualAmount.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
int a = Integer.parseInt(subType.amount);
float b = Float.parseFloat(subType.disc) / 100;
holder.tvActualAmount.setText("₹ " + subType.amount);
int c = (int) (a * b);
holder.tvDiscountAmount.setText("₹ " + c);
} else {
holder.tvDiscountPercentage.setBackgroundColor(Color.parseColor("#ffffff"));
holder.tvActualAmount.setText("₹ " + subType.amount);
}
} else {
holder.seeMore.setText("See More >>");
}
}
#Override
public int getItemCount() {
return subTypes.size()+1;
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public ImageView ivProduct;
public TextView tvProductName, tvActualAmount, tvDiscountAmount, tvDiscountPercentage, seeMore;
public CustomViewHolder(View itemView) {
super(itemView);
tvProductName = (TextView) itemView.findViewById(R.id.tvProductName);
tvActualAmount = (TextView) itemView.findViewById(R.id.tvActualAmount);
tvDiscountAmount = (TextView) itemView.findViewById(R.id.tvDiscountAmount);
tvDiscountPercentage = (TextView) itemView.findViewById(R.id.tvDiscountPercentage);
ivProduct = (ImageView) itemView.findViewById(R.id.ivProduct);
seeMore = (TextView) itemView.findViewById(R.id.seeMore);
}
}
}
Here are my both model classes.
public class SubType {
public int id;
public String typeId;
public String name;
public String image;
public String unit;
public String amount;
public String disc;
}
public class MainType {
public int id;
public String name;
public ArrayList<SubType> list;
}
My few logcat details
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.ashishkudale.linksolution.adapters.BaseRowItemAdapter.onBindViewHolder(BaseRowItemAdapter.java:54)
at com.ashishkudale.linksolution.adapters.BaseRowItemAdapter.onBindViewHolder(BaseRowItemAdapter.java:23)
It is crashing because of IndexOutOfBoundsException. I don't know how to solve this please help.
Change your onBindViewHolder
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
if (position != subTypes.size()) {
SubType subType = subTypes.get(position);
holder.tvProductName.setText(subType.name);
Picasso.with(context).load(subType.image).into(holder.ivProduct);
if (!subType.disc.equals("0")) {
holder.tvDiscountPercentage.setText(subType.disc + "%");
holder.tvActualAmount.setPaintFlags(holder.tvActualAmount.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
int a = Integer.parseInt(subType.amount);
float b = Float.parseFloat(subType.disc) / 100;
holder.tvActualAmount.setText("₹ " + subType.amount);
int c = (int) (a * b);
holder.tvDiscountAmount.setText("₹ " + c);
} else {
holder.tvDiscountPercentage.setBackgroundColor(Color.parseColor("#ffffff"));
holder.tvActualAmount.setText("₹ " + subType.amount);
}
} else {
holder.seeMore.setText("See More >>");
}
}