简体   繁体   中英

Android how to inflate ListView with two different items

I am trying to inflate listView with two different layouts using ArrayAdapter.

I want to show some user posts. If it contains a picture use one layout if it does not use second.

I am doing so far

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Post post = getItem(position);

    boolean noImg = post.mImgUrl1 == null && post.mImgUrl2 == null;

    if (convertView == null){

        if (noImg)
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.post_item_no_img, parent ,false);
        else
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.post_item, parent, false);
    }

    if (noImg == false) {
        mTitle = (TextView) convertView.findViewById(R.id.tv_titlePost);
        mText = (TextView) convertView.findViewById(R.id.tv_textPost);
        mImage = (ImageView) convertView.findViewById(R.id.iv_postimg);
    }

    else {
        mNoImgTitle = (TextView) convertView.findViewById(R.id.tv_noImgTitle);
        mNoImgText = (TextView) convertView.findViewById(R.id.tv_noImgText);
    }

    if (noImg) {
        mNoImgTitle.setText(post.mTitle);
        mNoImgText.setText(post.mText);

        if (post.mImgUrl1 != null)
            Glide.with(mImage.getContext()).load(post.mImgUrl1).into(mImage);

        else  Glide.with(mImage.getContext()).load(post.mImgUrl2).into(mImage);
    }
    else {
        mNoImgTitle.setText(post.mTitle);
        mNoImgText.setText(post.mText);
    }

    return convertView;
}

But i realized that textviews from second layout cannot be found by findViewById function. And it always returns a null-pointer.

What are my solutions ? Should i make only one Layout and somehow trick it using visibility ? Or there is a way ?

With BaseAdapter you can create more complex layouts. Try using it.

Here is the example of use for your situation:

Activity:

public class TestActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    String[] data={"false","false","true","true","false","true"};
    ListView listViewTest=(ListView)findViewById(R.id.listViewTest);
    TestAdapter testAdapter=new TestAdapter(data);
    listViewTest.setAdapter(testAdapter);
}
}

Adapter:

public class TestAdapter extends BaseAdapter {
private String[] data;


TestAdapter(String data[]) {
    this.data = data;
}

@Override
public int getCount() {
    return data.length;
}

@Override
public Object getItem(int i) {
    return data[i];
}

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


public View getView(int position, View convertView, ViewGroup parent) {
    if (data[position].equals("false")) {
        convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_no_img, parent, false);
    } else if (data[position].equals("true")) {
        convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_img, parent, false);
    }
    return convertView;
}
}

Layouts:

activity_main

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
    android:id="@+id/listViewTest"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</ListView>

list_item_no_img

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/textViewTest"
    android:gravity="center"
    android:layout_centerInParent="true"
    android:textSize="32sp"
    android:text="Test"/>
</RelativeLayout>

list_item_img

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/textViewTest"
    android:gravity="center"
    android:layout_centerInParent="true"
    android:textSize="32sp"
    android:text="Test"/>
<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/ic_launcher"
    android:layout_marginStart="5dp"
    android:layout_marginLeft="5dp"
    android:layout_centerVertical="true"
    android:layout_toRightOf="@+id/textViewTest"
    android:layout_toEndOf="@+id/textViewTest" />
</RelativeLayout>

Result:

There are a few different scenarios that you will see when getView() is called:

  1. convertView is null: In this case just create the layout that you need depending upon noImg ;

  2. convertView is defined but is of the wrong type. In this case, you will need to discard the old view and create the one you need;

  3. convertView is defined but is of the correct type, in which case, we do nothing with it.

The following code is one approach to making sure that you are always working with the right layout and can find the ids that you expect. This code uses a tag in the inflated layout to identify the layout type that can be checked.

if (convertView == null || noImg != (boolean) convertView.getTag()) {
    // Either there is no view defined or it is the wrong type. Create
    // the type we need.
    if (noImg) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.post_item_no_img, parent, false);
    } else {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.post_item, parent, false);
    }
    convertView.setTag(noImg);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM