i used multiple viewholder in DataListAdapter.
each holder have a adapter.
my adapter :
public class DataListAdapter extends BaseAdapter<HomeListItem> {
private RecyclerView.RecycledViewPool pool;
public static final int ADS = 10, DATA = 11, PIC = 13, QUE=14;
public DataListAdapter(ArrayList<HomeListItem> dataList, AdapterListener<HomeListItem> listener) {
this.dataList = dataList;
this.listener = listener;
pool = new RecyclerView.RecycledViewPool();
}
#Override
public void onViewRecycled(#NonNull BaseViewHolder holder) {
super.onViewRecycled(holder);
}
#NonNull
#Override
public BaseViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == ADS){
return new ADSDataHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_home_ads, parent, false));
}else if (viewType == PIC) {
return new PictureHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_home, parent, false));
}else if (viewType == QUE) {
return new QuestionHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_home, parent, false));
}else
return new DataHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_home, parent, false));
}
#Override
public int getItemViewType(int position) {
if (dataList.get(position).getType() == ContentType.ADS)
return ADS;
if (dataList.get(position).getType() == ContentType.GALLERY)
return PIC;
if (dataList.get(position).getType() == ContentType.LIBS )
return DATA;
return QUE;
}
#Override
public void onBindViewHolder(#NonNull BaseViewHolder holder, int position) {
if (holder instanceof DataHolder){
((DataHolder) holder).bind(dataList.get(position));
} else if (holder instanceof ADSDataHolder) {
((ADSDataHolder) holder).bind(dataList.get(position));
} else if (holder instanceof PictureHolder) {
((PictureHolder) holder).bind(dataList.get(position));
}else if (holder instanceof QuestionHolder) {
((QuestionHolder) holder).bind(dataList.get(position));
}
}
class ADSDataHolder extends BaseViewHolder {
...
}
class PictureHolder extends BaseViewHolder {
...
}
class QuestionHolder extends BaseViewHolder{
private RecyclerView recyclerView;
private TextView title;
private View more;
public QuestionHolder(View itemView) {
super(itemView);
setType(QUE);
more = itemView.findViewById(R.id.more);
title = itemView.findViewById(R.id.title);
recyclerView = itemView.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(itemView.getContext(),RecyclerView.HORIZONTAL,false));
recyclerView.hasFixedSize();
recyclerView.setRecycledViewPool(pool);
}
public void bind(HomeListItem data) {
Collections.reverse(data.getData());
title.setText(data.getType().getVisibleName());
HomeQuestionAdapter adapter = new HomeQuestionAdapter((ArrayList<MainPageItem>) (ArrayList<?>) data.getData(),
new AdapterListener<MainPageItem>() {
#Override
public void onItemClick(MainPageItem item) {
onListItemClick(itemView.getContext(), data.getType(), item.getItemId());
}
});
recyclerView.setAdapter(adapter);
more.setOnClickListener(v -> listener.onItemClick(data));
}
}
class DataHolder extends BaseViewHolder {
private RecyclerView recyclerView;
private TextView title;
private View more;
DataHolder(View itemView) {
super(itemView);
setType(DATA);
more = itemView.findViewById(R.id.more);
title = itemView.findViewById(R.id.title);
recyclerView = itemView.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(itemView.getContext(),
LinearLayoutManager.HORIZONTAL, true));
recyclerView.hasFixedSize();
recyclerView.setRecycledViewPool(pool);
}
public void bind(HomeListItem data) {
Collections.reverse(data.getData());
title.setText(data.getType().getVisibleName());
SmallItemAdapter adapter = new SmallItemAdapter((ArrayList<MainPageItem>)
(ArrayList<?>) data.getData(),
new AdapterListener<MainPageItem>() {
#Override
public void onItemClick(MainPageItem item) {
onListItemClick(itemView.getContext(), data.getType(), item.getItemId());
}
});
recyclerView.setAdapter(adapter);
recyclerView.scrollToPosition(data.getData().size() - 1);
more.setOnClickListener(v -> listener.onItemClick(data));
}
}
private void onListItemClick(Context context, ContentType contentType, long id) {
// click
}
}
BaseAdapter:
public abstract class BaseAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
protected List<T> dataList;
protected final int DATA_TYPE = 1;
protected boolean isLoading = false, isMoreDataAvailable = false;
protected AdapterListener<T> listener;
#Override
public int getItemViewType(int position) {
if (dataList.get(position) == null)
return -1;
else return DATA_TYPE;
}
#Override
public int getItemCount() {
return dataList.size();
}
public void setMoreDataAvailable(boolean isMoreDataAvailable) {
this.isMoreDataAvailable = isMoreDataAvailable;
}
public void removeLoadingItem() {
if (dataList.size() > 0 && dataList.get(dataList.size() - 1) == null) {
dataList.remove(dataList.size() - 1);
notifyItemRemoved(dataList.size() - 1);
}
}
public void notifyDataChanged() {
isLoading = false;
notifyDataSetChanged();
}
}
and BaseViewHolder:
public class BaseViewHolder extends RecyclerView.ViewHolder {
private int type;
public BaseViewHolder(View itemView) {
super(itemView);
}
}
when i scroll the recyclerview gives me an error
my error:
:00:26.247 4194-4194/ir.hnfadak.shahidezendeh E/PushPole:Exception caught
java.lang.ClassCastException: ir.hfadak.fadakmedia.UI.Main.Home.Picture.SmallItemAdapter$DataHolder cannot be cast to ir.hfadak.fadakmedia.UI.Main.Question.HomeQuestionAdapter$DataQueHolder
at ir.hfadak.fadakmedia.UI.Main.Question.HomeQuestionAdapter.onBindViewHolder(HomeQuestionAdapter.java:31)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:345)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:368)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:399)
at android.os.Handler.handleCallback(Handler.java:754)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6238)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
and my HomeQuestionAdapter
public class HomeQuestionAdapter extends RecyclerView.Adapter<HomeQuestionAdapter.DataQueHolder> {
private RoundedCorners roundedCorners;
protected List<MainPageItem> dataList;
protected final int DATA_TYPE = 1;
protected boolean isLoading = false, isMoreDataAvailable = false;
protected AdapterListener<MainPageItem> listener;
public HomeQuestionAdapter(ArrayList<MainPageItem> dataList, AdapterListener<MainPageItem> listener) {
this.dataList = dataList;
this.listener = listener;
roundedCorners = new RoundedCorners(16);
}
#Override
public int getItemViewType(int position) {
if (dataList.get(position) == null)
return -1;
else return DATA_TYPE;
}
#Override
public int getItemCount() {
return dataList.size();
}
public void setMoreDataAvailable(boolean isMoreDataAvailable) {
this.isMoreDataAvailable = isMoreDataAvailable;
}
public void removeLoadingItem() {
if (dataList.size() > 0 && dataList.get(dataList.size() - 1) == null) {
dataList.remove(dataList.size() - 1);
notifyItemRemoved(dataList.size() - 1);
}
}
public void notifyDataChanged() {
isLoading = false;
notifyDataSetChanged();
}
#NonNull
#Override
public HomeQuestionAdapter.DataQueHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new DataQueHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_list_simple_question, parent, false));
}
#Override
public void onBindViewHolder(#NonNull HomeQuestionAdapter.DataQueHolder holder, int position) {
if (!isLoading && isMoreDataAvailable && position >= getItemCount() - 1) {
isLoading = true;
listener.onLoadMore();
} else {
holder.bind(dataList.get(position));
}
}
class DataQueHolder extends RecyclerView.ViewHolder {
private ImageView image;
private ImageView share,faivorid;
private TextView question,answer,view;
DataQueHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imageQue);
question = itemView.findViewById(R.id.titleQue);
answer = itemView.findViewById(R.id.answerQue);
share = itemView.findViewById(R.id.share);
faivorid = itemView.findViewById(R.id.favorite);
view = itemView.findViewById(R.id.viewtxt);
}
void bind(MainPageItem data) {
Glide.with(itemView)
.load(data.getItemSmallImageAddress())
.apply(bitmapTransform(roundedCorners))
.apply(new RequestOptions().error(R.drawable.img_list_def)
.placeholder(R.drawable.img_list_def))
.into(image);
question.setText(data.getItemTitle());
answer.setText(data.getItemDescription());
share.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ContextUtil.share(itemView.getContext(),
data.getItemTitle() + "\n\n"
+ data.getItemDescription() + "\n\n"
+ data.getItemSmallImageAddress());
}
});
itemView.setOnClickListener(v -> listener.onItemClick(data));
}
}
}
Where does the code is wrong?
Your are type casting instance of super class to a reference of sub class which is causing this error.
Instead create something like this:-
public void onBindViewHolder(#NonNull BaseViewHolder holder, int position) {
if (holder instanceof DataQueHolder){
((DataQueHolder) holder).bind(dataList.get(position));
}else if (holder instanceof DataHolder){
((DataHolder) holder).bind(dataList.get(position));
}else if (holder instanceof ADSDataHolder) {
((ADSDataHolder) holder).bind(dataList.get(position));
} else if (holder instanceof PictureHolder) {
((PictureHolder) holder).bind(dataList.get(position));
}else if (holder instanceof QuestionHolder) {
((QuestionHolder) holder).bind(dataList.get(position));
}
}
Please remove this below line from DataListAdapter
recyclerView.setRecycledViewPool(pool);
It works for me..
Related
I want to create a cart which has Nested array.
Like my parent array has items and child array has item's respective toppings but when i add toppings to my item array it automatically add same toppings to all index of items array. Here is my image:
Here i'm attaching my code below
Item_Array
private void addNewToppinDialoge(ProductsModel.Datum datum, int adapterPosition) {
ProductOrderModel.Datum productOrderModel = new ProductOrderModel.Datum();
productOrderModel.setCategoryID(datum.getProductID());
productOrderModel.setCategory(datum.getProductName());
int i = productActivity.productOrderModelArrayList.size();
int j = i + 1;
productOrderModel.setSrNO(String.valueOf(j));
productActivity.productOrderModelArrayList.add(productOrderModel);
productActivity.refreshOrderAdapter();
productActivity.changeTitleToolbar(datum.getProductName());
}
Toppings_array
private void addToppingToCart(ToppingsModel.Datum.LookupValue lookupValue, int adapterPosition) {
ProductOrderModel.Datum datum = new ProductOrderModel.Datum();
ProductOrderModel.Datum.SubCategory subCategory = new ProductOrderModel.Datum.SubCategory();
subCategory.setCategory(lookupValue.getLookupvalue());
int pos = productActivity.productOrderModelArrayList.size() - 1;
Log.e("POS", String.valueOf(ProductActivity.productOrderModelArrayList.size() - 1));
productActivity.productOrderModelArrayListSub.add(subCategory);
int subPos = productActivity.productOrderModelArrayListSub.size() - 1;
productActivity.productOrderModelArrayListSub.get(subPos).setCategory(lookupValue.getLookupvalue());
productActivity.productOrderModelArrayList.get(pos).setSubCategory(productActivity.productOrderModelArrayListSub);
productActivity.refreshOrderAdapter();
}
Adapter For Cart
public class MyOrderAdapter extends RecyclerView.Adapter<MyOrderAdapter.ViewHolder> {
public static ToppingsListAdapter toppingsListAdapter;
static Context mContext;
ArrayList<ProductOrderModel.Datum> orderModelArrayList;
public MyOrderAdapter(Context mContext, ArrayList<ProductOrderModel.Datum> orderModelArrayList) {
MyOrderAdapter.mContext = mContext;
this.orderModelArrayList = orderModelArrayList;
}
#NonNull
#Override
public MyOrderAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View mView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.myorder_layout, viewGroup, false);
return new MyOrderAdapter.ViewHolder(mView);
}
#Override
public void onBindViewHolder(#NonNull MyOrderAdapter.ViewHolder holder, int i) {
holder.mTextOrderName.setText(orderModelArrayList.get(i).getCategory());
holder.mImageRemove.setOnClickListener(v -> removeItem(orderModelArrayList.get(i), holder.getAdapterPosition()));
holder.mTextSerialNo.setText(orderModelArrayList.get(i).getSrNO() + ".");
ArrayList<ProductOrderModel.Datum.SubCategory> arrayItem = (ArrayList<ProductOrderModel.Datum.SubCategory>) orderModelArrayList.get(i).getSubCategory();
if (arrayItem == null) {
} else {
toppingsListAdapter = new ToppingsListAdapter(mContext, arrayItem);
holder.mRecyclerToppings.setAdapter(toppingsListAdapter);
}
}
protected void removeItem(ProductOrderModel.Datum productOrderModel, int adapterPosition) {
}
#Override
public int getItemCount() {
return orderModelArrayList.size();
}
public void refreshAdapter() {
toppingsListAdapter.notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public RecyclerView mRecyclerToppings;
private TextView mTextOrderName, mTextSerialNo;
private ImageView mImageRemove;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mTextOrderName = itemView.findViewById(R.id.orderItemName);
mImageRemove = itemView.findViewById(R.id.orderRemove);
mTextSerialNo = itemView.findViewById(R.id.srno);
mRecyclerToppings = itemView.findViewById(R.id.text_toppings);
RecyclerView.LayoutManager manager = new LinearLayoutManager(mContext, LinearLayout.VERTICAL, false);
mRecyclerToppings.setLayoutManager(manager);
}
public int getAdapterPosition(ProductOrderModel.Datum.SubCategory remove) {
return 0;
}
}
}
strong text:
I guess you need to header and footer of RecyclerView. Here is the code.
Try this one:
public class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
String[] data;
public HeaderAdapter(String[] data) {
this.data = data;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
//inflate your layout and pass it to view holder
return new VHItem(null);
} else if (viewType == TYPE_HEADER) {
//inflate your layout and pass it to view holder
return new VHHeader(null);
}
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 position) {
if (holder instanceof VHItem) {
String dataItem = getItem(position);
//cast holder to VHItem and set data
} else if (holder instanceof VHHeader) {
//cast holder to VHHeader and set data for header.
}
}
#Override
public int getItemCount() {
return data.length + 1;
}
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
private String getItem(int position) {
return data[position - 1];
}
class VHItem extends RecyclerView.ViewHolder {
TextView title;
public VHItem(View itemView) {
super(itemView);
}
}
class VHHeader extends RecyclerView.ViewHolder {
Button button;
public VHHeader(View itemView) {
super(itemView);
}
}
}
After implementing a custom animation for these CardViews, the first two are not behaving in the way they are supposed to. Item A and Item B won't expand upon the 2nd click, but yet Item C works perfectly fine.
public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private Context mContext;
RecyclerViewHeader header;
List<MyRecyclerViewItem> listItems;
ValueAnimator mAnimator;
public MyRecyclerAdapter(Context context, RecyclerViewHeader header, List<MyRecyclerViewItem> listItems)
{
this.mContext = context;
this.header = header;
this.listItems = listItems;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_header, parent, false);
return new MyRecyclerAdapter.VHHeader(v);
}
else if(viewType == TYPE_ITEM)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
return new MyRecyclerAdapter.VHItem(v);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
private MyRecyclerViewItem getItem(int position)
{
return listItems.get(position);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Typeface iconFont = FontManager.getTypeface(mContext, FontManager.FONTAWESOME);
if (holder instanceof VHHeader)
{
final VHHeader vhHeader = (VHHeader)holder;
}
else if (holder instanceof VHItem)
{
MyRecyclerViewItem currentItem = getItem(position-1);
final VHItem vhItem = (VHItem)holder;
vhItem.txtA.setText(currentItem.getContinent());
vhItem.txtB.setText(currentItem.getCountry());
vhItem.txtB.setVisibility(View.GONE);
vhItem.txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
vhItem.txtExpandCollapse.setTypeface(iconFont);
//Add onPreDrawListener
vhItem.txtB.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
vhItem.txtB.getViewTreeObserver().removeOnPreDrawListener(this);
vhItem.txtB.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
vhItem.txtB.measure(widthSpec, heightSpec);
mAnimator = vhItem.slideAnimator(0, vhItem.txtB.getMeasuredHeight());
return true;
}
});
vhItem.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItem.txtB.getVisibility() == View.GONE){
vhItem.expand();
} else {
vhItem.collapse();
}
}
});
}
}
#Override
public int getItemViewType(int position) {
if(isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEM;
}
private boolean isPositionHeader(int position)
{
return position == 0;
}
// increasing getItemcount to 1. This will be the row of header.
#Override
public int getItemCount() {
return listItems.size()+1;
}
class VHHeader extends RecyclerView.ViewHolder{
Button btnCollapseAll, btnExpandAll;
public VHHeader(View headerView) {
super(headerView);
this.btnCollapseAll = headerView.findViewById(R.id.btn_collapseall);
this.btnExpandAll = headerView.findViewById(R.id.btn_expandall);
}
}
public class VHItem extends RecyclerView.ViewHolder{
CardView cardView;
RelativeLayout mRelativeLayout;
TextView txtExpandCollapse, txtA, txtB;
public VHItem(View itemView) {
super(itemView);
this.cardView = itemView.findViewById(R.id.cv);
this.mRelativeLayout = itemView.findViewById(R.id.tv_rv_relativelayout);
this.txtExpandCollapse = itemView.findViewById(R.id.tv_rv_expandcollapse);
this.txtA = itemView.findViewById(R.id.tv_rv_A);
this.txtB = itemView.findViewById(R.id.tv_rv_B);
}
private void expand() {
// set Visible
txtB.setVisibility(View.VISIBLE);
// change direction of chevron to 'up'
txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
mAnimator.start();
}
private void collapse() {
// change direction of chevron to 'down'
txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
int finalHeight = txtB.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animator) {
//Height=0, but it set visibility to GONE
txtB.setVisibility(View.GONE);
}
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
mAnimator.start();
}
public ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//Update Height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = txtB.getLayoutParams();
layoutParams.height = value;
txtB.setLayoutParams(layoutParams);
}
});
return animator;
}
}
}
You need to re-initialize mAnimator object.
Try below,
Defind one more member variable in VHItem class to keep the textB height
public class VHItem extends RecyclerView.ViewHolder{
CardView cardView;
RelativeLayout mRelativeLayout;
TextView txtExpandCollapse, txtA, txtB;
int textBHeight; // new variable
}
Then initialize it from onPreDraw method
public boolean onPreDraw() {
vhItem.txtB.getViewTreeObserver().removeOnPreDrawListener(this);
vhItem.txtB.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
vhItem.txtB.measure(widthSpec, heightSpec);
vhItem.textBHeight = vhItem.txtB.getMeasuredHeight();
return true;
}
Then initialize the animator before starting
private void expand() {
txtB.setVisibility(View.VISIBLE);
txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
mAnimator = slideAnimator(0,textBHeight);
mAnimator.start();
}
Change the object CardView for View.
Instead of generating the event on the cardview try to do the following on the inner class VHItem:
View view;
RelativeLayout mRelativeLayout;
TextView txtExpandCollapse, txtA, txtB;
public VHItem(View itemView) {
super(itemView);
this.view = itemView;
this.mRelativeLayout = itemView.findViewById(R.id.tv_rv_relativelayout);
this.txtExpandCollapse = itemView.findViewById(R.id.tv_rv_expandcollapse);
this.txtA = itemView.findViewById(R.id.tv_rv_A);
this.txtB = itemView.findViewById(R.id.tv_rv_B);
}
now, on the method onBindViewHolder:
vhItem.view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItem.txtB.getVisibility() == View.GONE){
vhItem.expand();
} else {
vhItem.collapse();
}
}
});
I have a problem. When I update one view of the ListView, I notify one item. Data have 2 items.
But when I call notifyItem with payload, but payload return array none. I don't know why before I call success with a view different.
RecyclerView with call update one item at updateStatusIconCheckLanguage. I check normal update button no have value payload. Can help you? Thanks.
This is the code :
public class HistoryAdapter
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<HistoryModel> mDataLists;
private ViewHolder mViewHolder;
private IViewCallback mCallback;
public HistoryAdapter() {
mDataLists = new ArrayList<>();
}
public void fillData(List<HistoryModel> modelList) {
if (modelList == null) {
return;
}
//remember order item.
mDataLists = new ArrayList<>();
mDataLists.addAll(modelList);
notifyDataSetChanged();
updateStatusIconCheckLanguage(KEY_TYPE_LANGUAGE.KEY_VN);
}
public void updateStatusIconCheckLanguage(KEY_TYPE_LANGUAGE keyTypeLanguage) {
if (keyTypeLanguage != null) {
if (mDataLists != null) {
for (int i = 0; i < mDataLists.size(); i++) {
notifyItemChanged(i, 34444);
CommonUtils.showLogDebug("notifyItemChanged");
}
}
}
}
public void cleanupResources() {
if (mViewHolder != null) {
mViewHolder.cleanupResources();
mViewHolder = null;
}
mDataLists = null;
// Refresh your adapter.
notifyDataSetChanged();
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent,
int viewType) {
mViewHolder = new ViewHolder(mCallback, LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history, parent, false));
return mViewHolder;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder,
int position) {
CommonUtils.showLogDebug("onBindViewHolder");
HistoryModel model = mDataLists.get(position);
if (holder instanceof ViewHolder) {
((ViewHolder) holder).fillData(model);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder,
final int position,
#NonNull final List<Object> payloads) {
CommonUtils.showLogDebug("ssss.size()" + payloads + holder);
if (payloads.size() > 0) {
} else {
onBindViewHolder(holder, position);
}
}
public void setOnClickItemViewListener(IViewCallback callback) {
mCallback = callback;
}
public interface IViewCallback {
void onViewClicked(HistoryModel model);
}
#Override
public int getItemCount() {
// add them 1 vi co header.
// return mNormalWithExoPlayerModelList.size();
return mDataLists == null ? 0 : mDataLists.size();
}
#Override
public int getItemViewType(final int position) {
return super.getItemViewType(position);
}
#Override
public void onViewAttachedToWindow(#NonNull final RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
}
static class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.clItemHistory)
ConstraintLayout clItemHistory;
#BindView(R.id.tvItemHistory)
TextView tvItemHistory;
private Unbinder mUnbinder;
private HistoryModel mModel;
private IViewCallback mCallback;
ViewHolder(IViewCallback callback,
View view) {
super(view);
mCallback = callback;
mUnbinder = ButterKnife.bind(this, view);
}
#OnClick(R.id.clItemHistory)
protected void onViewClicked() {
if (mCallback != null) {
mCallback.onViewClicked(mModel);
}
}
void fillData(HistoryModel model) {
if ((model != null)) {
mModel = model;
tvItemHistory.setText(String.format("%s-%s-%s",
model.getDayOfHistory(),
model.getMonthOfHistory(),
model.getYearOfHistory()));
}
}
void cleanupResources() {
mModel = null;
if (clItemHistory != null) {
clItemHistory.removeAllViews();
}
if (mUnbinder != null) {
mUnbinder.unbind();
mUnbinder = null;
}
}
}
}
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.
i have a recyclerView with two sections regular and Favourites and for populating my RecyclerView i have List<Object> my object class :
public class Object {
String id,channelName;
boolean isFavorite;
}
now i want to put the values which have isfavorite == true to top of my recyclerView inside my Favourite section but i don't know where to start or exactly what to do ? do i have to sort the List<Object> with booleans ? if anybody can give me a little hint or guidance then it'll be so helpful for me,
please this image for better understanding ,
this is what i'm trying to get
i added the Section in my RecyclerView by SimpleSectionedRecyclerViewAdapter
class DataModal
{
public String title;
public boolean isFavourite;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isFavourite() {
return isFavourite;
}
public void setIsFavourite(boolean isFavourite) {
this.isFavourite = isFavourite;
}
}
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> {
private final Context mContext;
private List<DataModal> mData;
public void add(DataModal s,int position) {
position = position == -1 ? getItemCount() : position;
mData.add(position,s);
notifyItemInserted(position);
}
public void remove(int position){
if (position < getItemCount() ) {
mData.remove(position);
notifyItemRemoved(position);
}
}
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public final TextView title;
public SimpleViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.simple_text);
}
}
public SimpleAdapter(Context context, ArrayList<DataModal> data) {
mContext = context;
if (data != null)
mData = data;
else mData = new ArrayList<DataModal>();
}
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.simple_item, parent, false);
return new SimpleViewHolder(view);
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, final int position) {
DataModal data = mData.get(position);
holder.title.setText(data.getTitle());
holder.title.setOnClickListener(new Listener(position,mData.get(position)));
}
class Listener implements View.OnClickListener
{
DataModal Data;
int position;
Listener(int position,DataModal Data)
{
this.Data = Data;
this.position = position;
}
#Override
public void onClick(View view) {
if(Data.isFavourite())
{
//mark the view as unfavorite
}
else{
//mark the view as favorite
}
Toast.makeText(mContext,"Position ="+position,Toast.LENGTH_SHORT).show();
}
}
#Override
public int getItemCount() {
return mData.size();
}
}
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> {
private final Context mContext;
private List<String> mData;
public void add(String s,int position) {
position = position == -1 ? getItemCount() : position;
mData.add(position,s);
notifyItemInserted(position);
}
public void remove(int position){
if (position < getItemCount() ) {
mData.remove(position);
notifyItemRemoved(position);
}
}
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public final TextView title;
public SimpleViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.simple_text);
}
}
public SimpleAdapter(Context context, String[] data) {
mContext = context;
if (data != null)
mData = new ArrayList<String>(Arrays.asList(data));
else mData = new ArrayList<String>();
}
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.simple_item, parent, false);
return new SimpleViewHolder(view);
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, final int position) {
holder.title.setText(mData.get(position));
holder.title.setOnClickListener(new Listener(position,mData.get(position),false,favview));
}
class Listener implements View.OnClickListener
{
ImageView favoriteView;
int position;
Listener(int position,String Data,boolean isFavourite,ImageView favoriteView)
{
this.favoriteView = favoriteView;
this.position = position;
}
#Override
public void onClick(View view) {
if(isFavourite)
{
//mark the view as unfavorite
}
else{
//mark the view as favorite
}
Toast.makeText(mContext,"Position ="+position,Toast.LENGTH_SHORT).show();
}
}
#Override
public int getItemCount() {
return mData.size();
}
}