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

备注:

  1. usersAdapter 的搜索文本扩展了 ArrayAdapter。
  2. getView()中,代码User user = getItem(position)获取对象。在您的情况下,对象的类型为 Item.
  3. 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)

感谢对我的帮助:)!