Android 如何用两个不同的项目扩充 ListView

Android how to inflate ListView with two different items

我正在尝试使用 ArrayAdapter 将 listView 扩展为两种不同的布局。

我想显示一些用户帖子。如果它包含图片,则使用一种布局,如果不使用第二种布局。

我目前正在做

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

但我意识到 findViewById 函数无法找到第二个布局中的文本视图。它总是 returns 一个空指针。

我的解决方案是什么?我应该只制作一个布局并以某种方式使用可见性来欺骗它吗?或者有办法吗?

使用 BaseAdapter,您可以创建更复杂的布局。尝试使用它。

以下是适用于您的情况的示例:

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

适配器:

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

布局:

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>

结果:

调用 getView() 时,您会看到几种不同的情况:

  1. convertView 为空:在这种情况下,只需根据 noImg;

  2. 创建您需要的布局
  3. convertView 已定义但类型错误。在这种情况下,您需要丢弃旧视图并创建您需要的视图;

  4. convertView 已定义但类型正确,在这种情况下,我们不对其进行任何操作。

以下代码是确保您始终使用正确布局并可以找到您期望的 ID 的一种方法。此代码在扩充布局中使用标记来标识可以检查的布局类型。

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