Reputation:
I have a list view. Displayed as a card view. In card view I have an image which I want to change dynamically based on object TYPE. So for that I have created two different layouts which contain small and big image. I have created an adapter and tried to inflate two different layouts in onCreateViewHolder.I am getting a Null pointer exception on these lines of code. No idea what I am missing...Please Help..
itemViewHolder.big.setImageDrawable(drawable1);
itemViewHolder.small.setImageDrawable(drawable);
public class IAdapter extends RecyclerView.Adapter<IAdapter.ItemViewHolder> {
Adapter code
public class ItemAdapter extends RecyclerView.Adapter<IAdapter.ItemViewHolder> {
List<Expense> items;
public static final int TYPE1 = 1;
public static final int TYPE2 = 2;
IAdapter(List<Expense> items) {
this.items = items;
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public int getItemViewType(int position) {
Expense e = new Expense();
if (TYPE1 == 1) {
int type = e.getExpenseType();
return type;
} else {
return TYPE2;
}
}
@Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
itemViewHolder.amount.setText(items.get(i).amount);
itemViewHolder.expense.setText(items.get(i).expense);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.withBorder(4)
.textColor(Color.BLACK)
.useFont(Typeface.DEFAULT)
.fontSize(25)
.bold()
.toUpperCase()
.endConfig()
.buildRound("11:00", Color.GRAY);
itemViewHolder.small.setImageDrawable(drawable);
TextDrawable drawable1 = TextDrawable.builder()
.beginConfig()
.withBorder(4)
.textColor(Color.BLACK)
.useFont(Typeface.DEFAULT)
.fontSize(25)
.bold()
.toUpperCase()
.endConfig()
.buildRound("10 Jan", Color.CYAN);
itemViewHolder.big.setImageDrawable(drawable1);
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if (viewType == TYPE1) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.cardlayout, viewGroup, false);
return new ItemViewHolder(itemView, viewType);
} else {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.bigcircle, viewGroup, false);
ItemViewHolder ivh = new ItemViewHolder(itemView, viewType);
return ivh;
}
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView amount;
TextView expense;
ImageView small;
ImageView big;
ItemViewHolder(View itemView, int viewType) {
super(itemView);
amount = (TextView) itemView.findViewById(R.id.txtAmount);
expense = (TextView) itemView.findViewById(R.id.txtexpense);
cv = (CardView) itemView.findViewById(R.id.card_view);
small = (ImageView) itemView.findViewById(R.id.small);
big=(ImageView)itemView.findViewById(R.id.big);
// cv1 = (CardView) itemView.findViewById(R.id.card_view);
//TextDrawable drawable1 = TextDrawable.builder()
// .buildRound("20 Jan", Color.RED);
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
cardlayout code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1"
android:orientation="vertical"
android:measureWithLargestChild="false"
android:background="@android:color/white">
<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="80dp"
card_view:cardCornerRadius="4dp"
android:background="@android:color/white">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/relativeLayout"
android:background="@android:color/white"
android:layout_alignParentTop="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/txtAmount"
android:text="text1"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/linearLayout"
android:layout_toStartOf="@+id/linearLayout"
android:layout_marginRight="24dp"
android:layout_marginEnd="24dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:weightSum="1"
android:id="@+id/linearLayout"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<ImageView
android:layout_width="40dp"
android:layout_height="25dp"
android:id="@+id/imageView2"
android:background="@drawable/line" />
<ImageView
android:id="@+id/small"
android:focusableInTouchMode="false"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/circle"/>
<ImageView
android:layout_width="40dp"
android:layout_height="25dp"
android:id="@+id/imageView3"
android:background="@drawable/line" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="@+id/txtexpense"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/linearLayout"
android:layout_toEndOf="@+id/linearLayout"
android:layout_marginLeft="24dp"
android:layout_marginStart="24dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
bigcircle card layout code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1"
android:orientation="vertical"
android:measureWithLargestChild="false">
<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view1"
android:layout_width="match_parent"
android:layout_height="80dp"
card_view:cardCornerRadius="4dp"
android:background="@android:color/white">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/relativeLayout"
android:background="@android:color/white"
android:layout_alignParentTop="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="@+id/txtAmount"
android:text="text1"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/linearLayout"
android:layout_toStartOf="@+id/linearLayout"
android:layout_marginRight="24dp"
android:layout_marginEnd="24dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:weightSum="1"
android:id="@+id/linearLayout"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<ImageView
android:layout_width="50dp"
android:layout_height="25dp"
android:id="@+id/imageView2"
android:background="@drawable/line" />
<ImageView
android:id="@+id/big"
android:focusableInTouchMode="false"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/circle1"/>
<ImageView
android:layout_width="50dp"
android:layout_height="25dp"
android:id="@+id/imageView3"
android:background="@drawable/line" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="@+id/txtexpense"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/linearLayout"
android:layout_toEndOf="@+id/linearLayout"
android:layout_marginLeft="24dp"
android:layout_marginStart="24dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
What am I missing???
Upvotes: 2
Views: 3589
Reputation:
public class IAdapter extends RecyclerView.Adapter<IAdapter.ItemViewHolder> {
List<Expense> items;
public static final int TYPE1=1;
IAdapter(List<Expense> items) {
this.items = items;
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public int getItemViewType(int position) {
return items.get(position).getExpenseType();// Assume that this return 1 0r 2
}
@Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
itemViewHolder.amount.setText(items.get(i).amount);
itemViewHolder.expense.setText(items.get(i).expense);
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup,int viewType) {
if (viewType==TYPE1) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.cardlayout, viewGroup, false);
return new ItemViewHolder(itemView,viewType);
} else {
View itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.bigcircle, viewGroup, false);
ItemViewHolder ivh = new ItemViewHolder(itemView, viewType);
return ivh;
}
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView amount;
TextView expense;
ImageView small;
ImageView big;
ItemViewHolder(View itemView, int viewType) {
super(itemView);
amount = (TextView) itemView.findViewById(R.id.txtAmount);
expense = (TextView) itemView.findViewById(R.id.txtexpense);
cv = (CardView) itemView.findViewById(R.id.card_view);
if(viewType==TYPE1) {
small = (ImageView) itemView.findViewById(R.id.small);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.withBorder(4)
.textColor(Color.BLACK)
.useFont(Typeface.DEFAULT)
.fontSize(25)
.bold()
.toUpperCase()
.endConfig()
.buildRound("11:00", Color.GRAY);
small.setImageDrawable(drawable);
}else{
big=(ImageView)itemView.findViewById(R.id.big);
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.withBorder(4)
.textColor(Color.BLACK)
.useFont(Typeface.DEFAULT)
.fontSize(25)
.bold()
.toUpperCase()
.endConfig()
.buildRound("10Jan", Color.CYAN);
big.setImageDrawable(drawable);
}
// cv1 = (CardView) itemView.findViewById(R.id.card_view);
//TextDrawable drawable1 = TextDrawable.builder()
// .buildRound("20 Jan", Color.RED);
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
this is giving the desired result..
Upvotes: 0
Reputation: 5420
It is because you are using the ItemViewHolder
that is passed from the onCreateViewHolder
method inside the onBindViewHolder
method. The reason it fails is that, You have 2 different inflated views passed one containing view element with id big
and the other with id small
. So, either itemViewHolder.big or itemViewHolder.small becomes null. That throws an NullPointerException
I think the way you approached this is correct.
Option One: This is a different way of achieving this.
if you have completely different layouts for these two, you have to do it this way. But if the layout of the cards are the same only those big and small images are changing, I suggest you to keep a single layout and change the image view grammatically.
Option Two
Your approach. I suggest you to stick to it because that is the elegant way of doing this. But you will have to do some minor tweaks.
@Override
public int getItemViewType(int position) {
return items.get(position).getExpenseType();// Assume that this return 1 0r 2
}
I suggest you to check the type before you set the value here, Assuming that you have a TYPE class variable to keep the Type for each item.
@Override
public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
itemViewHolder.amount.setText(items.get(i).amount);
itemViewHolder.expense.setText(items.get(i).expense);
if(getItemViewType(i) == 1){
TextDrawable drawable = TextDrawable.builder()
.beginConfig()
.withBorder(4)
.textColor(Color.BLACK)
.useFont(Typeface.DEFAULT)
.fontSize(25)
.bold()
.toUpperCase()
.endConfig()
.buildRound("11:00", Color.GRAY);
itemViewHolder.small.setImageDrawable(drawable);
}else{
TextDrawable drawable1 = TextDrawable.builder()
.beginConfig()
.withBorder(4)
.textColor(Color.BLACK)
.useFont(Typeface.DEFAULT)
.fontSize(25)
.bold()
.toUpperCase()
.endConfig()
.buildRound("10 Jan", Color.CYAN);
itemViewHolder.big.setImageDrawable(drawable1);
}
}
This has not changed my answer. But this will give you a good idea. The cavity thing that you are missing is in this,
public static class ItemViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView amount;
TextView expense;
ImageView small;
ImageView big;
ItemViewHolder(View itemView, int viewType) {
super(itemView);
amount = (TextView) itemView.findViewById(R.id.txtAmount);
expense = (TextView) itemView.findViewById(R.id.txtexpense);
cv = (CardView) itemView.findViewById(R.id.card_view);
small = (ImageView) itemView.findViewById(R.id.small);
big=(ImageView)itemView.findViewById(R.id.big);
// cv1 = (CardView) itemView.findViewById(R.id.card_view);
//TextDrawable drawable1 = TextDrawable.builder()
// .buildRound("20 Jan", Color.RED);
}
}
even though you do
small = (ImageView) itemView.findViewById(R.id.small);
big=(ImageView)itemView.findViewById(R.id.big);
either small or big variable will get assigned null
. But you have to check that before calling a method on it. Otherwise it will give a NullPointerException
Edit:
Or you can do,
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup,int viewType) {
View itemView;
if (getItemViewType(i)==1) {
itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.cardlayout, viewGroup, false);
} else {
itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.bigcircle, viewGroup, false);
}
return new ItemViewHolder(itemView,viewType);
}
Upvotes: 1
Reputation:
@Override public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup,int viewType) {
if (getItemViewType(i)==1) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.cardlayout, viewGroup, false);
return new ItemViewHolder(itemView,viewType);
} else {
View itemView = LayoutInflater.from(viewGroup.getContext()).
inflate(R.layout.bigcircle, viewGroup, false);
ItemViewHolder ivh = new ItemViewHolder(itemView, viewType);
return ivh;
}
}
is this right??
Upvotes: 0