【问题标题】:Change layout screen in runtime with RecyclerView adapter使用 RecyclerView 适配器在运行时更改布局屏幕
【发布时间】:2017-04-17 07:16:29
【问题描述】:

我有两个如下所示的布局文件。

如果列表中存在数据,则显示此布局。

当列表为空时,我会显示此布局。

现在我想在运行时更改布局。当用户从列表中删除最后一项时,我想将布局更改为第二张图片中显示的“空购物车布局”。

在 RecyclerView 适配器的 getItemCount() 方法中,如果列表为空或 null,则返回计数为 1,否则返回 list.size()

这是我的适配器代码。

public class CheckOutAdapter extends RecyclerView.Adapter<CheckOutAdapter.ViewHolder> {

    public ArrayList<Design> designList;
    private Context context;
    private LayoutInflater layoutInflater;

    public CheckOutAdapter(Context context, ArrayList<Design> designList) {
        this.designList = designList;
        this.context = context;
        this.layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(designList.isEmpty() || designList == null || designList.size() == 0) {
            View view = layoutInflater.inflate(R.layout.empty_cart, parent, false);
            return new ViewHolder(view);
        } else {
            View view = layoutInflater.inflate(R.layout.checkout_single_design, parent, false);
            return new ViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {

        final Design design = designList.get(position);
        holder.tvQuality.setText(design.qualityName);
        holder.tvDesign.setText(design.designName);
        holder.tvShade.setText(design.name);
        holder.tvAmount.setText("₹ " + design.amount);
        Picasso.with(context).load(design.image).into(holder.ivDesign);
        if (design.pcs != 0) {
            holder.btPcsCount.setText(Integer.toString(design.pcs));
        }

        holder.ivDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openDialog(design);
            }
        });
        //other ClickListeners.
    }

    @Override
    public int getItemCount() {
        if (designList == null || designList.isEmpty() || designList.size() == 0) {
            return 1;
        } else {
            return designList.size();
        }
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public LinearLayout llPer;
        public Button btPlus, btMinus, btPcsCount, btAddCart;
        public ImageView ivDesign, ivDelete;
        public TextView tvDesign, tvQuality, tvShade, tvAmount, tvDiscAmt, tvDisPer;

        public ViewHolder(View itemView) {
            super(itemView);

            llPer = (LinearLayout) itemView.findViewById(R.id.llPer);
            btPlus = (Button) itemView.findViewById(R.id.btPlus);
            //other findViewByIds
        }
    }

    public void openDialog(final Design design) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("Confirm");
        builder.setMessage("Remove item from cart?");
        builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                designList.remove(design);
                notifyDataSetChanged();
                saveSharedPref(context, "cart", new Gson().toJson(designList));
                Toast.makeText(context, "deleted", Toast.LENGTH_SHORT).show();
                dialog.dismiss();
            }
        });

        builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });

        AlertDialog alert = builder.create();
        alert.show();
    }
}

onBindViewHolder 附近出现 NullPointerException。我不知道为什么它会崩溃。请提出建议。

【问题讨论】:

  • 你需要重写 getItemViewType 来设置运行时布局

标签: java android android-layout android-recyclerview


【解决方案1】:

您可以覆盖getItemViewType()

@Override
public int getItemViewType(int position) {
    if (designList.size() == 0) return R.layout.empty;
    else return R.layout.normal_layout;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
    ViewHolder viewHolder = null;
    if (viewType == R.layout.empty) {
        viewHolder = new EmptyViewHolder(view);
    } else {
        viewHolder = new NormalViewHolder(view);
    }
    return viewholder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceOf EmptyViewHolder){
        // this is empty item, update view appropriately if needed
    } else {
        // this is normal item, update view appropriately if needed
    }
}

现在,当数据集更改并且适配器中只有 1 个项目时,您将获得所需的布局。

【讨论】:

    【解决方案2】:

    看..当您重新输入 1 时,即使您的数据集没有任何数据..您的适配器正在尝试从空数据集中绑定视图,因此您得到一个空指针。

    **你可以这样做**

    @Override //add this method to your adapter
    public int getItemViewType(int position) {
        if(designList.size()==0){
            return 1;
          }else{
            return 2;
        }
    }
    

    也在你的 onCreateView 持有人中这样做..

    @Override // modify your onCreate based on viewtype
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(viewType == 1) { //for empty layout
            View view = layoutInflater.inflate(R.layout.empty_cart, parent, false);
            return new ViewHolder(view);
        } else {
            View view = layoutInflater.inflate(R.layout.checkout_single_design, parent, false);
            return new ViewHolder(view);
        }
    }
    

    现在在你的 bindView() 中这样做:

    @Override /
    public void onBindViewHolder(final ViewHolder holder, final int position) {
    
        if(designList.size()>0){
            final Design design = designList.get(position);
        holder.tvQuality.setText(design.qualityName);
        holder.tvDesign.setText(design.designName);
        holder.tvShade.setText(design.name);
        holder.tvAmount.setText("₹ " + design.amount);
        Picasso.with(context).load(design.image).into(holder.ivDesign);
        if (design.pcs != 0) {
            holder.btPcsCount.setText(Integer.toString(design.pcs));
        }
    
        holder.ivDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openDialog(design);
            }
        });
        //other ClickListeners.
         }else{
           //handle the empty layout Add button click listener
        }
    
    }
    

    希望有帮助

    【讨论】:

      【解决方案3】:
      @Override
      public int getItemViewType(int position) {
            if ((designList.isEmpty() || designList == null || designList.size() == 0) {
                          return R.layout.empty_cart;
            }
            return R.layout.checkout_single_design;
      }
      
      @Override
          public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
              if (viewType == R.layout.empty_cart) {
                  return new EmptyViewHolder(layoutInflater.inflate(viewType, parent, false));
              } else {
                  return new ViewHolder(layoutInflater.inflate(viewType, parent, false));
              }
         }
      

      【讨论】:

      • 无需复制getItemCount()的逻辑。 ViewHolders 初始化不正确。
      • 为什么你对这个答案投了反对票,而你自己的答案一开始是错误的,后来又更新了!!我还没有显示getItemCount() 方法,那么它是如何复制的?而且我的 ViewHolder 初始化并没有错。如果您看一下这个问题,A 视图正在通过 layoutInflater.inflate(R.layout.empty_cart, parent, false); 进行初始化。而这个layoutInflater 是在适配器构造函数中初始化的,该视图被传递给ViewHolder 对象,这根本不是不正确的。
      • 首先我还没有更新我的答案,仔细检查你说的话。其次,如果您尝试在onCreateViewHolder 中执行代码,您会发现Java 中没有这样的构造函数,您必须执行new EmptyViewHolder(...),其次,viewHolder 没有在任何地方声明。第三,如果它被声明,你没有执行分配,这将导致viewHolder 成为null
      • 是的...这是一个愚蠢的错误。你可以指出这一点。但我解决问题的方法没有错。
      猜你喜欢
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多