问题
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