具有多种布局的Android ListView
Posted
技术标签:
【中文标题】具有多种布局的Android ListView【英文标题】:Android ListView with multiple layouts 【发布时间】:2015-06-10 15:00:28 【问题描述】:我必须显示一个包含不同类型视图的列表。所以我必须用一个适配器定义一个 ListView,我必须在其中膨胀多个视图。我已经通过example 给出,但问题是我的列表不是对称的,就像每次在 4 个项目后重复标题的示例一样。所以我在getView()
中面临重复使用项目的问题@
public View getView(int position, View convertView, ViewGroup parent)
int type = getItemViewType(position);
if (convertView == null)
holder = new ViewHolder();
switch (type)
case TYPE_1:
convertView = mInflater.inflate(R.layout.item1, null);
.......
break;
case TYPE_2:
convertView = mInflater.inflate(R.layout.item2, null);
.......
break;
convertView.setTag(holder);
else
holder = (ViewHolder)convertView.getTag();
............
............
现在如果convertView 不为null,但之前使用的item 类型不同,那么布局将不匹配。这段代码将如何处理这个问题?
【问题讨论】:
不要为 convertview 检查 null 条件,这将始终使项目布局膨胀。 您需要为 item1 和 item2 布局创建 2 个ViewHolder
,并且在 else
中 convertView !=null
您需要检查 type
并转换为 ViewHolder1
或 ViewHolder2
。 ..你怎么看?
如果列表视图项具有非对称布局,那么您可以拥有包含所有必需元素的单个列表项 xml,并且在基于类型的 getView 方法中您可以设置可见性显示/隐藏/消失。
假设第一项是类型 1(具有 layout_1),它将在第 8 个元素中重用,即类型 2(具有 layout_2)。现在,如果第一个项目的标签(实际上是 ViewHolder1 的对象)将其转换为 ViewHolder2,它会起作用吗?此外,布局也会有所不同。它将如何运作?
【参考方案1】:
您可以查看此示例适配器。 getViewTypeCount 方法返回您的不同类型行。 getItemViewType 方法,如果位置等于 0,则膨胀第一行布局,否则膨胀其他行布局。您可以自定义此代码示例。
import java.util.List;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
/**
* Created by MustafaS on 9.2.2015.
*/
public class CustomArrayAdapter extends ArrayAdapter<YourModel>
@Override
public int getItemViewType(int position)
if (position == 0)
return 0;
else
return 1;
@Override
public int getViewTypeCount()
return 2;
@Override
public View getView(int position, View convertView, ViewGroup parent)
int type = getItemViewType(position);
if (type == 0)
if (convertView == null)
convertView = LayoutInflater.from(activity).inflate(R.layout.listview_first_row, parent, false);
viewHolderFirst = new ViewHolderFirst();
convertView.setTag(viewHolderFirst);
else
viewHolderFirst = (ViewHolderFirst) convertView.getTag();
else
if (convertView == null)
convertView = LayoutInflater.from(activity).inflate(R.layout.listview_other_row, parent, false);
viewHolder = new ViewHolder();
else
viewHolder = (ViewHolder) convertView.getTag();
return convertView;
protected class ViewHolderFirst
private RunnableViewPager pager;
private CircleIndicator indicator;
protected class ViewHolder
private ImageView imageviewRestaurant;
private TextView textviewRestaurantName;
private TextView textviewType;
private TextView textviewPrice;
private TextView textviewDistance;
private ImageView imageviewCall;
private ImageView imageviewCalendar;
【讨论】:
假设第一项是类型 1(具有 layout_1),它将在第 8 个元素中重用,即类型 2(具有 layout_2)。现在,如果第一个项目的标签(实际上是 ViewHolderFirst 的对象)将其转换为 ViewHolder,它会起作用吗?此外,布局也会有所不同。它将如何运作? 如果你的第一行有很多不同的其他行,你应该这样。但是如果你的行相似,你可以一排xml和一个viewholder layout_1 和 layout_2 不同。如何将它用于之前使用类型 1 的类型 2?【参考方案2】:您可以通过覆盖方法 getViewCount()
和 getItemViewType(int position)
来做到这一点
首先,您只需返回您拥有的不同视图的数量。
在第二个中,您为每个不同的视图返回一个唯一标识符。
在您的getView()
方法中,您检查视图类型并为其添加正确的布局。
有关该主题的更多信息:Android ListView with different layouts for each row
Android ListView with different layouts for each row
【讨论】:
【参考方案3】:这是您在 ListView 或 RecyclerView 中使用不同类型的视图时需要使用的:-
getItemViewType() and getViewTypeCount()
首先,您需要使用 getViewTypeCount() 并返回列表中所需的唯一视图数。然后覆盖 getItemViewType() 并根据您希望视图在 ListView 内更改的任何条件返回视图类型。
希望它会有所帮助。
【讨论】:
以上是关于具有多种布局的Android ListView的主要内容,如果未能解决你的问题,请参考以下文章
Android自定义FlowLayout,支持多种布局优化--android-flowlayout