Android – ListView Rows with Different Layouts

androidandroid-arrayadapterandroid-listview

What I am trying to achieve is to have different layouts for each row. The code in my ArrayAdapter is as follows:

@Override
    public int getCount() {
        return contentList.size();
    }

    @Override
    public MyContents getItem(int position) {
        return content.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getViewTypeCount() {
        // TODO Auto-generated method stub
        return 2;
    }

    @Override
    public int getItemViewType(int position) {
        // TODO Auto-generated method stub
        return super.getItemViewType(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final MyContents entry = content.get(position);

        View row = convertView;
        LayoutInflater inflater = null;
        boolean _haschild_ = entry.testBoolean();
        if (row == null) {
            if (entry.testBoolean()) {
                inflater = (LayoutInflater) context
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = inflater
                        .inflate(R.layout.contents_layout, null);
            } else {
                inflater = (LayoutInflater) context
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = inflater.inflate(R.layout.test_layout, null);
            }
        } 

        if (entry.testBoolean()) {
            TextView txtView = (TextView) row
                    .findViewById(R.id.txtView);
            //.....
        } else {
            ((TextView) row.findViewById(R.id.txtView_test)) //**LOE**
                    .setText("test: " + position); //**LOE**
        }


        return row;
    }

The layout file for *test_layout.xml*:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_test"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="12dp"
    android:background="@color/grey_five"
    android:orientation="vertical"
    android:padding="@dimen/padding_small" >

    <TextView
        android:id="@+id/txtView_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:text="@string/lorem__ipsum"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@color/grey" />


</RelativeLayout>

But whenever I execute it throws a NullPointerException(check the line with the comment //LOE).

Any suggestion what to do? I am struggling with it for past one day.

Best Answer

That NullPointerException occurs because you didn't implement the getItemViewType. Right now you return the first type of row layout no matter what and this is a layout that doesn't have the *txtView_test* TextView). Your code should be something like this:

// some fields
public static final int FIRST_TYPE = 0;
public static final int SECOND_TYPE = 1;

@Override
public int getItemViewType(int position) {
     MyContents item = getItem(position);
     if (item.testBoolean()) {
          return FIRST_TYPE;
     } else {
          return SECOND_TYPE; 
     } 
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final MyContents entry = content.get(position);
    View row = convertView;
    LayoutInflater inflater = null;
    int type = getItemViewType(position);
    boolean _haschild_ = entry.testBoolean();
    if (row == null) {
        if (type == FIRST_TYPE) {
            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater
                    .inflate(R.layout.contents_layout, null);
        } else {
            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.test_layout, null);
        }
    } 
    if (type == FIRST_TYPE) {
        TextView txtView = (TextView) row
                .findViewById(R.id.txtView);
        //.....
    } else {
        ((TextView) row.findViewById(R.id.txtView_test)) //**LOE**
                .setText("test: " + position); //**LOE**
    }
Related Question