在 Android 中重复将布局扩展为自定义适配器视图的子视图
Inflating layout a child view to view of custom adapter is repeating in Android
我正在开发 android 应用程序。在我的应用程序中。我必须使用自定义适配器来处理 Listview。即使在适配器中,我也需要膨胀子视图以查看自定义适配器。但是我像寻呼机一样逐段加载项目到列表视图。但是当加载新的项目段时,子视图会再次添加到现有的行视图中。
这是列表视图的初始状态:
但是当我将新项目绑定到滚动列表视图时,子视图是这样添加的:
这是我的自定义适配器视图:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/user_timeline_main_layout"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:gravity="center"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/civ_timeline_profile"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:id="@+id/timeline_reason_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_timeline_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_timeline_reason"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_timeline_datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/timeline_action_content_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</LinearLayout>
</LinearLayout>
这是timeline_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="This is item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
timeline_designer.xml 等同于 timeline_item.xml.
这是我的自定义适配器:
public class UserTimelineAdapter extends ArrayAdapter<TimelineItem> {
private Context context;
private ArrayList<TimelineItem> values;
static class ViewHolder{
public CircleImageView civProfile;
public TextView tvUsername;
public TextView tvReason;
public TextView tvDatetime;
public LinearLayout actionContentContainer;
public LinearLayout mainLayout;
}
public UserTimelineAdapter(Context contextParam,ArrayList<TimelineItem> valuesParam)
{
super(contextParam,-1,valuesParam);
this.context = contextParam;
this.values = valuesParam;
}
@Override
public View getView(final int position,View convertView,ViewGroup parent)
{
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = convertView;
final ViewHolder viewHolder;
if(rowView==null)
{
rowView = layoutInflater.inflate(R.layout.user_timeline_row,null);
viewHolder = new ViewHolder();
viewHolder.mainLayout = (LinearLayout)rowView.findViewById(R.id.user_timeline_main_layout);
viewHolder.civProfile = (CircleImageView)rowView.findViewById(R.id.civ_timeline_profile);
viewHolder.tvUsername = (TextView)rowView.findViewById(R.id.tv_timeline_username);
viewHolder.tvReason = (TextView)rowView.findViewById(R.id.tv_timeline_reason);
viewHolder.tvDatetime = (TextView)rowView.findViewById(R.id.tv_timeline_datetime);
viewHolder.actionContentContainer = (LinearLayout)rowView.findViewById(R.id.timeline_action_content_container);
rowView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) rowView.getTag();
}
if(values.get(position).getProfileImagePath().isEmpty())
{
viewHolder.civProfile.setImageResource(R.drawable.default_designer_profile);
}
else{
Picasso.with(context).load(values.get(position).getProfileImagePath()).into(viewHolder.civProfile);
}
viewHolder.tvUsername.setText(values.get(position).getUsername());
viewHolder.tvReason.setText(values.get(position).getReason());
viewHolder.tvDatetime.setText(values.get(position).getDatetime());
if(values.get(position).getItemId()>0)
{
View view = layoutInflater.inflate(R.layout.timeline_item,viewHolder.mainLayout,false);
viewHolder.actionContentContainer.addView(view);
}
else{
//designer
View view = layoutInflater.inflate(R.layout.timeline_designer,viewHolder.mainLayout,false);
viewHolder.actionContentContainer.addView(view);
}
return rowView;
}
}
为什么会这样?我该如何修复我的代码?
我认为您通过使用视图标签的模式重新使用了主视图,但是在重新使用的视图上您每次仍然膨胀并添加另一个视图:
if(values.get(position).getItemId()>0)
{
View view = layoutInflater.inflate(R.layout.timeline_item,viewHolder.mainLayout,false);
viewHolder.actionContentContainer.addView(view);
}
因此,如果您需要更新其文本,请尝试通过诸如 rowView.findViewById(R.id.timeline_item_id);
之类的方法查找此视图,而不是在重复使用的视图中膨胀此项目(例如,当 rowView != null
时) ,或以任何方式更改它。
如果不需要改,就不要查了,不要膨胀添加。
我正在开发 android 应用程序。在我的应用程序中。我必须使用自定义适配器来处理 Listview。即使在适配器中,我也需要膨胀子视图以查看自定义适配器。但是我像寻呼机一样逐段加载项目到列表视图。但是当加载新的项目段时,子视图会再次添加到现有的行视图中。
这是列表视图的初始状态:
但是当我将新项目绑定到滚动列表视图时,子视图是这样添加的:
这是我的自定义适配器视图:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/user_timeline_main_layout"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:gravity="center"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/civ_timeline_profile"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:id="@+id/timeline_reason_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_timeline_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_timeline_reason"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_timeline_datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/timeline_action_content_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</LinearLayout>
</LinearLayout>
这是timeline_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="This is item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
timeline_designer.xml 等同于 timeline_item.xml.
这是我的自定义适配器:
public class UserTimelineAdapter extends ArrayAdapter<TimelineItem> {
private Context context;
private ArrayList<TimelineItem> values;
static class ViewHolder{
public CircleImageView civProfile;
public TextView tvUsername;
public TextView tvReason;
public TextView tvDatetime;
public LinearLayout actionContentContainer;
public LinearLayout mainLayout;
}
public UserTimelineAdapter(Context contextParam,ArrayList<TimelineItem> valuesParam)
{
super(contextParam,-1,valuesParam);
this.context = contextParam;
this.values = valuesParam;
}
@Override
public View getView(final int position,View convertView,ViewGroup parent)
{
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = convertView;
final ViewHolder viewHolder;
if(rowView==null)
{
rowView = layoutInflater.inflate(R.layout.user_timeline_row,null);
viewHolder = new ViewHolder();
viewHolder.mainLayout = (LinearLayout)rowView.findViewById(R.id.user_timeline_main_layout);
viewHolder.civProfile = (CircleImageView)rowView.findViewById(R.id.civ_timeline_profile);
viewHolder.tvUsername = (TextView)rowView.findViewById(R.id.tv_timeline_username);
viewHolder.tvReason = (TextView)rowView.findViewById(R.id.tv_timeline_reason);
viewHolder.tvDatetime = (TextView)rowView.findViewById(R.id.tv_timeline_datetime);
viewHolder.actionContentContainer = (LinearLayout)rowView.findViewById(R.id.timeline_action_content_container);
rowView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) rowView.getTag();
}
if(values.get(position).getProfileImagePath().isEmpty())
{
viewHolder.civProfile.setImageResource(R.drawable.default_designer_profile);
}
else{
Picasso.with(context).load(values.get(position).getProfileImagePath()).into(viewHolder.civProfile);
}
viewHolder.tvUsername.setText(values.get(position).getUsername());
viewHolder.tvReason.setText(values.get(position).getReason());
viewHolder.tvDatetime.setText(values.get(position).getDatetime());
if(values.get(position).getItemId()>0)
{
View view = layoutInflater.inflate(R.layout.timeline_item,viewHolder.mainLayout,false);
viewHolder.actionContentContainer.addView(view);
}
else{
//designer
View view = layoutInflater.inflate(R.layout.timeline_designer,viewHolder.mainLayout,false);
viewHolder.actionContentContainer.addView(view);
}
return rowView;
}
}
为什么会这样?我该如何修复我的代码?
我认为您通过使用视图标签的模式重新使用了主视图,但是在重新使用的视图上您每次仍然膨胀并添加另一个视图:
if(values.get(position).getItemId()>0)
{
View view = layoutInflater.inflate(R.layout.timeline_item,viewHolder.mainLayout,false);
viewHolder.actionContentContainer.addView(view);
}
因此,如果您需要更新其文本,请尝试通过诸如 rowView.findViewById(R.id.timeline_item_id);
之类的方法查找此视图,而不是在重复使用的视图中膨胀此项目(例如,当 rowView != null
时) ,或以任何方式更改它。
如果不需要改,就不要查了,不要膨胀添加。