android 自定义列表视图项目混乱
android custom Listview items are jumbled
大家好 :) 我创建了自定义列表视图,但是如果项目超过一定数量,列表视图就会变得奇怪。物品乱七八糟
我添加了这样的项目:
mItems.add(new VenuesListHeader("Barra"));
mItems.add(new VenuesListItem("Olympic gold course"));
mItems.add(new VenuesListItem("Pontal"));
mItems.add(new VenuesListItem("Barra olympic park"));
mItems.add(new VenuesListItem("Riocentro"));
mItems.add(new VenuesListHeader("Copacabana"));
mItems.add(new VenuesListItem("Beach volleyball arena"));
mItems.add(new VenuesListItem("Flamengo park"));
mItems.add(new VenuesListItem("Fort copacabana"));
mItems.add(new VenuesListItem("Lagoa stadium"));
mItems.add(new VenuesListItem("Marina da gloria"));
mItems.add(new VenuesListHeader("Deodora"));
mItems.add(new VenuesListItem("Drodora aquatics centre"));
mItems.add(new VenuesListItem("Drodora stadium"));
mItems.add(new VenuesListItem("Olympic equestrian centre"));
mItems.add(new VenuesListItem("Olympic hockey centre"));
mItems.add(new VenuesListItem("Olympic shooting centre"));
mItems.add(new VenuesListItem("Youth arena"));
mItems.add(new VenuesListItem("X-park"));
mItems.add(new VenuesListHeader("Maracana"));
mItems.add(new VenuesListItem("Olympic stadium"));
mItems.add(new VenuesListItem("Sambodromo"));
mItems.add(new VenuesListItem("Maracana"));
但是从第三个header开始就乱了。(试了好几次,header的个数不重要。)
这是我的代码:
View mHeader;
ListView mListView;
ArrayList<Item> mItems;
VenuesListAdapter mAdapter;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//listview set list
mListView = (ListView)rootView.findViewById(R.id.venues_list);
mHeader = inflater.inflate(R.layout.rio2016_venues_map, mListView, false);
mItems = new ArrayList<>();
setList("all");
mAdapter = new VenuesListAdapter(getActivity(), mItems);
mListView.addHeaderView(mHeader);
mListView.setAdapter(mAdapter);
}
void setList(String type){
switch (type){
case "barra":
mItems.clear();
case "all_barra":
mItems.add(new VenuesListHeader("Barra"));
mItems.add(new VenuesListItem("Olympic gold course"));
mItems.add(new VenuesListItem("Pontal"));
mItems.add(new VenuesListItem("Barra olympic park"));
mItems.add(new VenuesListItem("Riocentro"));
break;
case "copacabana":
mItems.clear();
case "all_copacabana":
mItems.add(new VenuesListHeader("Copacabana"));
mItems.add(new VenuesListItem("Beach volleyball arena"));
mItems.add(new VenuesListItem("Flamengo park"));
mItems.add(new VenuesListItem("Fort copacabana"));
mItems.add(new VenuesListItem("Lagoa stadium"));
mItems.add(new VenuesListItem("Marina da gloria"));
break;
case "deodoro":
mItems.clear();
case "all_deodoro":
mItems.add(new VenuesListHeader("Deodora"));
mItems.add(new VenuesListItem("Drodora aquatics centre"));
mItems.add(new VenuesListItem("Drodora stadium"));
mItems.add(new VenuesListItem("Olympic equestrian centre"));
mItems.add(new VenuesListItem("Olympic hockey centre"));
mItems.add(new VenuesListItem("Olympic shooting centre"));
mItems.add(new VenuesListItem("Youth arena"));
mItems.add(new VenuesListItem("X-park"));
break;
case "maracana":
mItems.clear();
case "all_maracana":
mItems.add(new VenuesListHeader("Maracana"));
mItems.add(new VenuesListItem("Olympic stadium"));
mItems.add(new VenuesListItem("Sambodromo"));
mItems.add(new VenuesListItem("Maracana"));
break;
case "all":
mItems.clear();
setList("all_barra");
setList("all_copacabana");
setList("all_copacabana");
setList("all_maracana");
break;
}
}
如果需要,这是自定义适配器
public class VenuesListAdapter extends ArrayAdapter<Item>{
private static final int TYPE_ITEM = 0;
private static final int TYPE_HEADER = 1;
private LayoutInflater mInflater;
public VenuesListAdapter(Context context, List<Item> items) {
super(context, 0, items);
mInflater = LayoutInflater.from(context);
}
public enum RowType {
LIST_ITEM, HEADER_ITEM
}
@Override
public int getItemViewType(int position) {
return getItem(position).getViewType();
}
@Override
public int getViewTypeCount() {
return RowType.values().length;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if(convertView == null){
holder = new ViewHolder();
switch (rowType){
case TYPE_ITEM :
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
case TYPE_HEADER :
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
public static class ViewHolder {
public View View;
}
}
(即使不使用递归函数也会出现同样的问题。)
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">
<ListView
android:id="@+id/venues_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
物品适配器
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:background="@color/white"
android:padding="15dp">
<TextView
android:id="@+id/venues_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:layout_centerVertical="true"/>
</RelativeLayout>
头适配器:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:background="@color/nav_header_background">
<TextView
android:id="@+id/venues_list_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:layout_centerVertical="true"/>
</RelativeLayout>
这种现象为什么会发生呢?我该怎么做才能解决这个问题?
更改您的代码并尝试以下操作:
public class VenuesListAdapter extends ArrayAdapter<Item>{
private static final int TYPE_ITEM = 0;
private static final int TYPE_HEADER = 1;
private LayoutInflater mInflater;
public VenuesListAdapter(Context context, List<Item> items) {
super(context, 0, items);
mInflater = LayoutInflater.from(context);
}
public enum RowType {
LIST_ITEM, HEADER_ITEM
}
@Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return 2;
}
@Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
if(position == TYPE_ITEM)
{return 1;}
else{return 0;}
}
@Override
public int getViewTypeCount() {
return RowType.values().length;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
int type=getItemViewType(position);
if(type==1){
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
holder.View = getItem(position).getView(mInflater, convertView);
}else{
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
holder.View = getItem(position).getView(mInflater, convertView);
}
return convertView;
}
public static class ViewHolder {
public View View;
}
}
这是长列表视图的常见问题,可以通过以下方式解决:
@Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return integer(number of different cases in your list);
}
@Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
}
在您的 getView()
中,您似乎正在缓存 View
对象,这将无法可靠地工作。我的代码风格与你的完全不同,因为我喜欢用我的 custom adapter
来控制 ListView
中的所有数据。但是,我相信,如果您调用 setText
方法来填写 ListView
.
,您的代码风格也可以工作
请查看代码示例@Using an ArrayAdapter with ListView。
备注:
- usersAdapter 的搜索文本扩展了 ArrayAdapter。
- 在
getView()
中,代码User user = getItem(position)
获取对象。在您的情况下,对象的类型为 Item.
tvName.setText(user.name)
。在你的情况下,也许 setText(getItem(position).getText()
.
我希望这有点清楚。
我自己解决了,很简单(所以气死我了。。。)我编辑CustomAdapter
.
之前:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if(convertView == null){
holder = new ViewHolder();
switch (rowType){
case TYPE_ITEM :
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
case TYPE_HEADER :
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
之后:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if(convertView == null){
holder = new ViewHolder();
switch (rowType){
case TYPE_ITEM :
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
break;
case TYPE_HEADER :
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.View = getItem(position).getView(mInflater, convertView);
return convertView;
}
我只把holder.View = getItem(position).getView(mInflater, convertView);
从里面if(convertView == null)
移到外面if(convertView == null)
。
感谢对我的帮助:)!
大家好 :) 我创建了自定义列表视图,但是如果项目超过一定数量,列表视图就会变得奇怪。物品乱七八糟
我添加了这样的项目:
mItems.add(new VenuesListHeader("Barra"));
mItems.add(new VenuesListItem("Olympic gold course"));
mItems.add(new VenuesListItem("Pontal"));
mItems.add(new VenuesListItem("Barra olympic park"));
mItems.add(new VenuesListItem("Riocentro"));
mItems.add(new VenuesListHeader("Copacabana"));
mItems.add(new VenuesListItem("Beach volleyball arena"));
mItems.add(new VenuesListItem("Flamengo park"));
mItems.add(new VenuesListItem("Fort copacabana"));
mItems.add(new VenuesListItem("Lagoa stadium"));
mItems.add(new VenuesListItem("Marina da gloria"));
mItems.add(new VenuesListHeader("Deodora"));
mItems.add(new VenuesListItem("Drodora aquatics centre"));
mItems.add(new VenuesListItem("Drodora stadium"));
mItems.add(new VenuesListItem("Olympic equestrian centre"));
mItems.add(new VenuesListItem("Olympic hockey centre"));
mItems.add(new VenuesListItem("Olympic shooting centre"));
mItems.add(new VenuesListItem("Youth arena"));
mItems.add(new VenuesListItem("X-park"));
mItems.add(new VenuesListHeader("Maracana"));
mItems.add(new VenuesListItem("Olympic stadium"));
mItems.add(new VenuesListItem("Sambodromo"));
mItems.add(new VenuesListItem("Maracana"));
但是从第三个header开始就乱了。(试了好几次,header的个数不重要。)
这是我的代码:
View mHeader;
ListView mListView;
ArrayList<Item> mItems;
VenuesListAdapter mAdapter;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//listview set list
mListView = (ListView)rootView.findViewById(R.id.venues_list);
mHeader = inflater.inflate(R.layout.rio2016_venues_map, mListView, false);
mItems = new ArrayList<>();
setList("all");
mAdapter = new VenuesListAdapter(getActivity(), mItems);
mListView.addHeaderView(mHeader);
mListView.setAdapter(mAdapter);
}
void setList(String type){
switch (type){
case "barra":
mItems.clear();
case "all_barra":
mItems.add(new VenuesListHeader("Barra"));
mItems.add(new VenuesListItem("Olympic gold course"));
mItems.add(new VenuesListItem("Pontal"));
mItems.add(new VenuesListItem("Barra olympic park"));
mItems.add(new VenuesListItem("Riocentro"));
break;
case "copacabana":
mItems.clear();
case "all_copacabana":
mItems.add(new VenuesListHeader("Copacabana"));
mItems.add(new VenuesListItem("Beach volleyball arena"));
mItems.add(new VenuesListItem("Flamengo park"));
mItems.add(new VenuesListItem("Fort copacabana"));
mItems.add(new VenuesListItem("Lagoa stadium"));
mItems.add(new VenuesListItem("Marina da gloria"));
break;
case "deodoro":
mItems.clear();
case "all_deodoro":
mItems.add(new VenuesListHeader("Deodora"));
mItems.add(new VenuesListItem("Drodora aquatics centre"));
mItems.add(new VenuesListItem("Drodora stadium"));
mItems.add(new VenuesListItem("Olympic equestrian centre"));
mItems.add(new VenuesListItem("Olympic hockey centre"));
mItems.add(new VenuesListItem("Olympic shooting centre"));
mItems.add(new VenuesListItem("Youth arena"));
mItems.add(new VenuesListItem("X-park"));
break;
case "maracana":
mItems.clear();
case "all_maracana":
mItems.add(new VenuesListHeader("Maracana"));
mItems.add(new VenuesListItem("Olympic stadium"));
mItems.add(new VenuesListItem("Sambodromo"));
mItems.add(new VenuesListItem("Maracana"));
break;
case "all":
mItems.clear();
setList("all_barra");
setList("all_copacabana");
setList("all_copacabana");
setList("all_maracana");
break;
}
}
如果需要,这是自定义适配器
public class VenuesListAdapter extends ArrayAdapter<Item>{
private static final int TYPE_ITEM = 0;
private static final int TYPE_HEADER = 1;
private LayoutInflater mInflater;
public VenuesListAdapter(Context context, List<Item> items) {
super(context, 0, items);
mInflater = LayoutInflater.from(context);
}
public enum RowType {
LIST_ITEM, HEADER_ITEM
}
@Override
public int getItemViewType(int position) {
return getItem(position).getViewType();
}
@Override
public int getViewTypeCount() {
return RowType.values().length;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if(convertView == null){
holder = new ViewHolder();
switch (rowType){
case TYPE_ITEM :
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
case TYPE_HEADER :
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
public static class ViewHolder {
public View View;
}
}
(即使不使用递归函数也会出现同样的问题。)
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">
<ListView
android:id="@+id/venues_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
物品适配器
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:background="@color/white"
android:padding="15dp">
<TextView
android:id="@+id/venues_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:layout_centerVertical="true"/>
</RelativeLayout>
头适配器:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:background="@color/nav_header_background">
<TextView
android:id="@+id/venues_list_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:layout_centerVertical="true"/>
</RelativeLayout>
这种现象为什么会发生呢?我该怎么做才能解决这个问题?
更改您的代码并尝试以下操作:
public class VenuesListAdapter extends ArrayAdapter<Item>{
private static final int TYPE_ITEM = 0;
private static final int TYPE_HEADER = 1;
private LayoutInflater mInflater;
public VenuesListAdapter(Context context, List<Item> items) {
super(context, 0, items);
mInflater = LayoutInflater.from(context);
}
public enum RowType {
LIST_ITEM, HEADER_ITEM
}
@Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return 2;
}
@Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
if(position == TYPE_ITEM)
{return 1;}
else{return 0;}
}
@Override
public int getViewTypeCount() {
return RowType.values().length;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
int type=getItemViewType(position);
if(type==1){
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
holder.View = getItem(position).getView(mInflater, convertView);
}else{
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
holder.View = getItem(position).getView(mInflater, convertView);
}
return convertView;
}
public static class ViewHolder {
public View View;
}
}
这是长列表视图的常见问题,可以通过以下方式解决:
@Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return integer(number of different cases in your list);
}
@Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
}
在您的 getView()
中,您似乎正在缓存 View
对象,这将无法可靠地工作。我的代码风格与你的完全不同,因为我喜欢用我的 custom adapter
来控制 ListView
中的所有数据。但是,我相信,如果您调用 setText
方法来填写 ListView
.
请查看代码示例@Using an ArrayAdapter with ListView。
备注:
- usersAdapter 的搜索文本扩展了 ArrayAdapter。
- 在
getView()
中,代码User user = getItem(position)
获取对象。在您的情况下,对象的类型为 Item. tvName.setText(user.name)
。在你的情况下,也许setText(getItem(position).getText()
.
我希望这有点清楚。
我自己解决了,很简单(所以气死我了。。。)我编辑CustomAdapter
.
之前:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if(convertView == null){
holder = new ViewHolder();
switch (rowType){
case TYPE_ITEM :
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
case TYPE_HEADER :
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
holder.View = getItem(position).getView(mInflater, convertView);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
之后:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
if(convertView == null){
holder = new ViewHolder();
switch (rowType){
case TYPE_ITEM :
convertView = mInflater.inflate(R.layout.rio2016_venues_item, null);
break;
case TYPE_HEADER :
convertView = mInflater.inflate(R.layout.rio2016_venues_header, null);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.View = getItem(position).getView(mInflater, convertView);
return convertView;
}
我只把holder.View = getItem(position).getView(mInflater, convertView);
从里面if(convertView == null)
移到外面if(convertView == null)
。
感谢对我的帮助:)!