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()
时,您会看到几种不同的情况:
convertView
为空:在这种情况下,只需根据 noImg
;
创建您需要的布局
convertView
已定义但类型错误。在这种情况下,您需要丢弃旧视图并创建您需要的视图;
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);
}
我正在尝试使用 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()
时,您会看到几种不同的情况:
convertView
为空:在这种情况下,只需根据noImg
; 创建您需要的布局
convertView
已定义但类型错误。在这种情况下,您需要丢弃旧视图并创建您需要的视图;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);
}