Change layout screen in runtime with RecyclerView adapter

我是研究僧i 提交于 2019-12-22 14:06:05

问题


I have two layout files shown below.

If data is present in list then I show this layout.

and when list is empty then I show this layout.

Now I wanted to change layout at runtime. When ever user deletes last item from list I wanted to change layout to 'Empty cart layout' shown in second image.

In getItemCount() method of RecyclerView adapter if list is empty or null then I return count as 1 otherwise I return list.size()

This is my adapter code.

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();
    }
}

I am getting NullPointerException near onBindViewHolder. I don't know why it getting crashed. please give suggestions.


回答1:


You can do that overriding 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
    }
}

Now, when dataset changes and there's only 1 item in your adapter, you'd get the desired layout shown.




回答2:


@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));
        }
   }



回答3:


Look.. when you are reutrning 1 even though you data set doesn't have any data.. you adapter is trying to bind a view from a empty data set, therefore you are getting a null pointer.

**Rather you can do this **

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

also in your onCreateView holder do this..

@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);
    }
}

now in your bindView() do this:

@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
    }

}

Hope that helps



来源:https://stackoverflow.com/questions/43446983/change-layout-screen-in-runtime-with-recyclerview-adapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!