RecyclerView卡片在滚动时随机改变大小



我的问题如下:
我想动态地改变recyclerView card的大小,也与textViews之间的空白在里面。
三种情况:
1.Amount是空的,所以两个textview中的recyclerView卡需要稍微挤压。
我是这样做的:

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
holder1.amount.setText(String.valueOf(currentItem.getAmount()));
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout_A);
constraintSet.connect(R.id.amount,ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START,70);
constraintSet.connect(R.id.type, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END,70);
constraintSet.applyTo(constraintLayout_A);
}

2。数额是非常大的,所以两个textview将被转移到两行。
我是这样做的:

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
holder2.amount.setText(String.valueOf(currentItem.getAmount()));
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout_A);
constraintSet.connect(R.id.amount,ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP,0);
constraintSet.connect(R.id.amount,ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START,0);
constraintSet.connect(R.id.amount,ConstraintSet.END, ConstraintSet.PARENT_ID,ConstraintSet.END,0);
constraintSet.connect(R.id.amount,ConstraintSet.BOTTOM, R.id.type,ConstraintSet.TOP,0);
constraintSet.connect(R.id.type, ConstraintSet.BOTTOM, R.id.info, ConstraintSet.TOP, 0);
constraintSet.connect(R.id.type, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START,0);
constraintSet.connect(R.id.type, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END,0);
constraintSet.connect(R.id.type, ConstraintSet.TOP, R.id.amount, ConstraintSet.BOTTOM,0);
constraintSet.connect(R.id.info, ConstraintSet.START,ConstraintSet.PARENT_ID,ConstraintSet.START,0);
constraintSet.connect(R.id.info, ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END,0);
constraintSet.connect(R.id.info, ConstraintSet.TOP, R.id.type,ConstraintSet.BOTTOM,5);
constraintSet.applyTo(constraintLayout_A);
}

3。金额"正常";大约需要2-3个"位置"。
这里我保持代码不变。

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
holder3.amount.setText(String.valueOf(currentItem.getAmount()));
}

问题是:
当我上下滚动recyclerView时,它会发生那些不需要修改的行。
例如,amount为'0',文本出现在两行中。
它来自recylerView恢复Views(这就是我如何理解它)。
只有在适配器中设置holder.setIsRecyclable(false);才能解决问题,但这不是有效的解决方案。
我试着把它分成三个独立的holder。
但问题仍然是一样的,也许我做错了什么?
我认为这将解决问题。
这是正确的方法吗?还是我必须这样做?

编辑

package com.example.appName.Adapters;
public class Recycler_Adapter_2 extends ListAdapter<Item_get, RecyclerView.ViewHolder> implements Filterable {
public Recycler_Adapters_items clickListener;
private Item_get currentItem;
private ConstraintLayout constraintLayout_A;
private Context context;
private RecHolder holder1BASIC;
private RecHolder2 holder2EXTENDED;
private RecHolder4 holder4EXTENDED;
public Recycler_Adapter_2(String className, RecyclerView recyclerView) {
super(DIFF_CALLBACK);
this.className = className;
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(recyclerView.getLayoutParams());
params.setMarginEnd(5);
context = recyclerView.getContext();
}
private static final DiffUtil.ItemCallback<Item_get> DIFF_CALLBACK = new DiffUtil.ItemCallback<Item_get>() {
@Override
public boolean areItemsTheSame(@NonNull Item_get oldItem, @NonNull Item_get newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(@NonNull Item_get oldItem, @NonNull Item_get newItem) {
if(oldItem.getBuy_place() != null){
return oldItem.getname_product().equals(newItem.getname_product()) &&
oldItem.getAmount().equals(newItem.getAmount()) && oldItem.getBuy_place().equals(newItem.getBuy_place());
}else {
return oldItem.getname_product().equals(newItem.getname_product()) &&
oldItem.getAmount().equals(newItem.getAmount());
}
}
};
public void setOnItemClickListener(Recycler_Adapters_items clickListener){
this.clickListener = clickListener;
}
class RecHolder extends RecyclerView.ViewHolder {
public TextView name_product;
public TextView amountBuy;
public TextView typePackage;
public RecHolder(@NonNull final View itemView, final Recycler_Adapters_items listener) {
super(itemView);
name_product = itemView.findViewById(R.id.name_field);
amountBuy = itemView.findViewById(R.id.amountBuy);
typePackage = itemView.findViewById(R.id.typeP);
constraintLayout_A = itemView.findViewById(R.id.ConstrainLayoutShop1_A);
initAllNeededArrays();
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null){
int position = getAbsoluteAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(getItem(position), getAbsoluteAdapterPosition());
}
}
}
});
}
}
class RecHolder2 extends RecyclerView.ViewHolder {
public TextView name_product;
public TextView amountBuy;
public TextView typePackage;
public RecHolder2(@NonNull final View itemView, final Recycler_Adapters_items listener) {
super(itemView);
name_product = itemView.findViewById(R.id.name_field);
amountBuy = itemView.findViewById(R.id.amountBuy);
typePackage = itemView.findViewById(R.id.typeP);
constraintLayout_A = itemView.findViewById(R.id.ConstrainLayoutShop1_A);
initAllNeededArrays();
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null){
int position = getAbsoluteAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(getItem(position), getAbsoluteAdapterPosition());
}
}
}
});
}
}
class RecHolder4 extends RecyclerView.ViewHolder {
public TextView name_product;
public TextView amountBuy;
public TextView typePackage;
public RecHolder4(@NonNull final View itemView, final Recycler_Adapters_items listener) {
super(itemView);
name_product = itemView.findViewById(R.id.name_field);
amountBuy = itemView.findViewById(R.id.amountBuy);
typePackage = itemView.findViewById(R.id.typeP);
constraintLayout_A = itemView.findViewById(R.id.ConstrainLayoutShop1_A);
initAllNeededArrays();
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(listener != null){
int position = getAbsoluteAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(getItem(position), getAbsoluteAdapterPosition());
}
}
}
});
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = null;
if(className.equals(ShoppList.class.getName())) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_template2,parent,false);
switch (viewType){
case 0:
return new RecHolder(v,clickListener);
case 2:
return new RecHolder2(v,clickListener);
case 4:
return new RecHolder4(v,clickListener);
}
}
return new RecHolder(v,clickListener);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
holder1BASIC = (RecHolder) holder;
if (className.equals(ShoppList.class.getName())) {
currentItem = getItem(position);
holder1BASIC.name_product.setText(currentItem.getname_product());
holder1BASIC.amountToBuy.setText(String.valueOf(currentItem.getAmount()));
setPackageText0(holder1BASIC, currentItem.getType(), currentItem.getAmount());
}
break;
case 2:
holder2EXTENDED = (RecHolder2) holder;
if (className.equals(ShoppList.class.getName())) {
currentItem = getItem(position);
holder2EXTENDED.name_product.setText(currentItem.getname_product());
holder2EXTENDED.amountToBuy.setText(String.valueOf(currentItem.getAmount()));
setPackageText2(holder2EXTENDED, currentItem.getType(), currentItem.getAmount());
}
break;
case 4:
holder4EXTENDED = (RecHolder4) holder;
if (className.equals(ShoppList.class.getName())) {
currentItem = getItem(position);
holder4EXTENDED.name_product.setText(currentItem.getname_product());
holder4EXTENDED.amountToBuy.setText(String.valueOf(currentItem.getAmount()));
setPackageText4(holder4EXTENDED, currentItem.getType(), currentItem.getAmount());
}
}
}

public void nextLineText(){
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout_A);
constraintSet.connect(R.id.amount,ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP,0);
constraintSet.connect(R.id.amount,ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START,0);
constraintSet.connect(R.id.amount,ConstraintSet.END, ConstraintSet.PARENT_ID,ConstraintSet.END,0);
constraintSet.connect(R.id.amount,ConstraintSet.BOTTOM, R.id.type,ConstraintSet.TOP,0);
constraintSet.connect(R.id.type, ConstraintSet.BOTTOM, R.id.info, ConstraintSet.TOP, 0);
constraintSet.connect(R.id.type, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START,0);
constraintSet.connect(R.id.type, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END,0);
constraintSet.connect(R.id.type, ConstraintSet.TOP, R.id.amount, ConstraintSet.BOTTOM,0);
constraintSet.connect(R.id.info, ConstraintSet.START,ConstraintSet.PARENT_ID,ConstraintSet.START,0);
constraintSet.connect(R.id.info, ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END,0);
constraintSet.connect(R.id.info, ConstraintSet.TOP, R.id.type,ConstraintSet.BOTTOM,5);
constraintSet.applyTo(constraintLayout_A);
}
public void setPackageText0( RecHolder holder, int packageTypeCode, int amount){
if(packageTypeCode == 1){
if(amount == 0){
holder.typePackage.setText(packTypeTextResources[2]);
}else if(amount == 1){
holder.typePackage.setText(packTypeTextResources[0]);
}else if(amount >= 2 && amount <= 4){
holder.typePackage.setText(packTypeTextResources[1]);
}else if(amount >= 5){
holder.typePackage.setText(packTypeTextResources[2]);
}
}
}
public void setPackageText2( RecHolder2 holder2, int packageTypeCode, int amount){
if(packageTypeCode == 1){
if(amount == 0){
holder2.typePackage.setText(packTypeTextResources[2]);
changeMarginDistance();
}else if(amount == 1){
holder2.typePackage.setText(packTypeTextResources[0]);
changeMarginDistance();
}else if(amount >= 2 && amount <= 4){
holder2.typePackage.setText(packTypeTextResources[1]);
changeMarginDistance();
}else if(amount >= 5){
holder2.typePackage.setText(packTypeTextResources[2]);
changeMarginDistance();
}
}else {
holder2.typePackage.setText(packTypeTextResources[12]);
changeMarginDistance();
}
}
public void setPackageText4( RecHolder4 holder4, int packageTypeCode, int amount){
nextLineText();
if(packageTypeCode == 1){
if(amount == 0){
holder4.typePackage.setText(packTypeTextResources[2]);
}else if(amount == 1){
holder4.typePackage.setText(packTypeTextResources[0]);
}else if(amount >= 2 && amount <= 4){
holder4.typePackage.setText(packTypeTextResources[1]);
}else if(amount >= 5){
holder4.typePackage.setText(packTypeTextResources[2]);
}
}else {
holder4.typePackage.setText(packTypeTextResources[12]);
}
}
public Item_get getItemPos(int position){
return getItem(position);
}
private void initPackageArrays(){
packTypeTextResources = context.getResources().getStringArray(R.array.Package_Type_Diffrent_varieties);
}
private void initAllNeededArrays(){
initPackageArrays();
}
@Override
public int getItemViewType(int position) {
// return super.getItemViewType(position);
Item_get actualItem = getItem(position);
if(actualItem.getAmount() == 0 || actualItem.getAmount() == null){
return 2;
}else if (actualItem.getAmount() > 999){
return 4;
}
return 0;
}
public void changeMarginDistance(){
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout_A);
constraintSet.connect(R.id.amount,ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START,70);
constraintSet.connect(R.id.type, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END,70);
constraintSet.applyTo(constraintLayout_A);
}
}

我粘贴了来自适配器的代码(简而言之),以澄清问题。

TL;DR要解决这个问题,你应该:

  • 为每个行类型使用单独的XML布局文件,并在XML中设置约束,而不是试图调整代码中的约束
  • 不要将视图或视图持有人作为类成员存储在适配器中,使用onBindViewHolder
  • 中的传入持有人。
  • 只定义一个onBindViewHolder,并使用持有人的行类型整数来正确转换它,并在那里设置它的视图

问题

目前尚不清楚holder1,holder2,holder3constrainLayout_A在您的示例中定义的位置,但您没有在onBindViewHolder中使用holder实例中传递的内容,并且显然已经定义了onBindViewHolder三次(?)这一事实可能是您所看到的问题的根本原因。将行视图作为类成员直接存储在RecyclerView适配器中几乎总是一个错误——行视图应该只存储在ViewHolder中,并且RecyclerView基类应该管理ViewHolder实例的存储和使用。

<<p>

解决方案/strong>您可以对RecyclerView中的不同行使用不同的视图类型。要做到这一点,您不需要在代码中手动调整约束。只需为不同的行类型设置不同的XML布局,并在XML中设置约束。然后选择在onCreateViewHolder中使用的正确的XML和holder。

一旦您定义了getItemViewType来根据某些标准设置行类型,您就需要在onCreateViewHolder(膨胀正确的XML布局并创建正确的holder)和onBindViewHolder(将holder转换为正确的类型并设置正确的数据)中使用该类型整数。例如:

private final int ROW_TYPE_TITLE = 1;
private final int ROW_TYPE_ITEM = 0;
// Step 1: let the RecyclerView know what "type" each row is
@Override
public int getItemViewType(int position) {
return mData.get(position).isTitle ? ROW_TYPE_TITLE : ROW_TYPE_ITEM;
}
// Step 2: Define different view holders to use for each row type
class TitleViewHolder extends RecyclerView.ViewHolder {
public TitleViewHolder(View v) {
super(v);
title = v.findViewById(R.id.title);
icon = v.findViewById(R.id.icon);
}

public TextView title;
public ImageView icon;
}
class ItemViewHolder extends RecyclerView.ViewHolder {
public ItemViewHolder(View v) {
super(v);
item = v.findViewById(R.id.item);
}

public TextView item;
}
// Step 3: when creating the view holder, use the provided type to create
// the correct holder. Each holder can have its own XML file defined, so
// you can set constraints appropriately in the XML
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ROW_TYPE_TITLE: 
View view = mInflater.inflate(R.layout.list_title, parent, false);
return new TitleViewHolder(view);

case ROW_TYPE_ITEM: 
View view = mInflater.inflate(R.layout.list_row, parent, false);
return new ItemViewHolder(view);
}
}
// Step 4: When binding a holder, cast the passed in holder to the correct
// type then set its data (in a *single* call to onBindViewHolder). Since you
// set the constraints for each type in its XML, you don't need to adjust them
// here.
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holderBase, int position) {
MyData row_data = mData.get(position);
switch(holder.getItemViewType())
case ROW_TYPE_TITLE: 
TitleViewHolder holderT = (TitleViewHolder)holderBase;
holderT.title.setText(row_data.title);
break;

case ROW_TYPE_ITEM: 
ItemViewHolder holderI = (ItemViewHolder)holderBase;
holderI.item.setText(row_data.item);
break;
}
}

最新更新