Android:不确定为什么我的列表视图会变得混乱?

时间:2015-06-23 20:05:11

标签: android android-listview fragment

我实现了一个正常工作的ListView,直到我添加了超过5个项目和2个标题。我不完全确定为什么有些物品没有出现而其他物品出现多次。任何帮助解决这个问题将非常感谢。代码包含在下面。

Toolbox.java

public class Toolbox extends Fragment {
    private ListView lstView;
    private View rootView;
    List<Tools> tools;

    public static Toolbox newInstance(Context context) {
        Toolbox fragment = new Toolbox();
        return fragment;
    }

    public Toolbox() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        ((MainActivity) getActivity()).setActionBarTitle("Technical Toolbox");
        rootView = inflater.inflate(R.layout.fragment_toolbox, container, false);
        lstView =(ListView) rootView.findViewById(R.id.list);
        final FragmentActivity c = getActivity();
        //final RecyclerView recyclerView = (RecyclerView) recView.findViewById(R.id.reView);


        setToolBoxData();
        setToolBoxAdapter();
        return rootView;
    }

    private void setToolBoxAdapter() {
        ListArrayAdapter adapter = new ListArrayAdapter(getActivity(),tools);
        lstView.setAdapter(adapter);
    }

    private void setToolBoxData(){
        tools=new ArrayList<>();
        tools.add(new Header("Languages"));
        tools.add(new ListItem("Android",R.drawable.ic_android));
        tools.add(new ListItem("XML", R.drawable.ic_xml));
        tools.add(new ListItem("Java",R.drawable.ic_java));
        tools.add(new ListItem("JavaScript", R.drawable.ic_javascript));
        tools.add(new ListItem("C++", R.drawable.ic_cpp));
        tools.add(new ListItem("Visual Basic", R.drawable.ic_vb));
        tools.add(new ListItem("HTML", R.drawable.ic_html));
        tools.add(new ListItem("CSS", R.drawable.ic_css));
        tools.add(new Header("Source Control"));
        tools.add(new ListItem("Git", R.drawable.ic_git));
        tools.add(new ListItem("GitHub", R.drawable.ic_github_cat));
        tools.add(new ListItem("SourceTree", R.drawable.ic_sourcetree));
        tools.add(new ListItem("BitBucket", R.drawable.ic_bitbucket));
        tools.add(new Header("DataBase"));
        tools.add(new ListItem("Parse", R.drawable.ic_parse));
        tools.add(new ListItem("MS Access", R.drawable.ic_access));
        tools.add(new ListItem("SQL", R.drawable.ic_sql));
        tools.add(new Header("Design & IDE Tools"));
        tools.add(new ListItem("Android Studio", R.drawable.ic_androidstudio));
        tools.add(new ListItem("Visual Studio", R.drawable.ic_visual_studio));
        tools.add(new ListItem("Genymotion", R.drawable.ic_genymotion));
        tools.add(new ListItem("Ionic", R.drawable.ic_ionic));
        tools.add(new Header("Office Tools"));
        tools.add(new ListItem("MS Project", R.drawable.ic_project));
        tools.add(new ListItem("MS Visio", R.drawable.ic_visio));
        tools.add(new ListItem("MS Excel", R.drawable.ic_excel));
        tools.add(new ListItem("MS Word", R.drawable.ic_word));
    }
}

ListArrayAdapter.java

public class ListArrayAdapter extends ArrayAdapter<Tools> {
    private LayoutInflater mInflater;

    public enum RowType{ LIST_ITEM, HEADER_ITEM }

    public ListArrayAdapter(Context context, List<Tools> tools){
        super(context, 0, tools);
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getViewTypeCount(){return RowType.values().length;}

    @Override
    public int getItemViewType(int pos){return getItem(pos).getViewType();}

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_SEPARATOR = 1;

    public View getView(int position, View convertView, ViewGroup parent)  {
        ViewHolder holder = null;
        int rowType = getItemViewType(position);
        View View;
        if (convertView == null) {
            holder = new ViewHolder();
            switch (rowType) {
                case TYPE_ITEM:
                    convertView = mInflater.inflate(R.layout.listview_item, null);
                    holder.View=getItem(position).getView(mInflater, convertView);
                    break;
                case TYPE_SEPARATOR:
                    convertView = mInflater.inflate(R.layout.list_title, 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;
    }
}

Tools.java

public interface Tools {
    public int getViewType();
    public View getView(LayoutInflater inflater, View convertView);
}

ListItem.java

public class ListItem implements Tools {
    private final String str1;
    private final int pic1;

    public ListItem(String text1, int pic1) {
        this.str1 = text1;
        this.pic1 = pic1;
    }

    @Override
    public int getViewType() {
        return ListArrayAdapter.RowType.LIST_ITEM.ordinal();
    }

    @Override
    public View getView(LayoutInflater inflater, View convertView) {
        View view;
        if (convertView == null) {
            view = (View) inflater.inflate(R.layout.listview_item, null);
            // Do some initialization
        } else {
            view = convertView;
        }

        TextView text1 = (TextView) view.findViewById(R.id.listText);
        ImageView picture1 = (ImageView) view.findViewById(R.id.listIcon);
        text1.setText(str1);
        picture1.setImageResource(pic1);

        return view;
    }
}

Header.java

public class Header implements Tools {
    private final String         name;

    public Header(String name) {
        this.name = name;
    }

    @Override
    public int getViewType() {
        return ListArrayAdapter.RowType.HEADER_ITEM.ordinal();
    }

    @Override
    public View getView(LayoutInflater inflater, View convertView) {
        View view;
        if (convertView == null) {
            view = (View) inflater.inflate(R.layout.header, null);
            // Do some initialization
        } else {
            view = convertView;
        }

        TextView text = (TextView) view.findViewById(R.id.separator);
        text.setText(name);

        return view;
    }
}

3 个答案:

答案 0 :(得分:1)

您只是在if (convertView == null)案例中填充行小部件。如果convertView不是null,则只是将其保持不变,这意味着它将包含来自某些先前position的数据,而不是正在请求的position

IOW,您需要在每次 setText()调用上调用setImageResource()getView()等方法,以填充行的小部件请求position的数据。

答案 1 :(得分:1)

不应使用职位,而应使用某种形式的唯一性ID。

此外,当视图被回收时,您需要使用新数据更新它们。

if (convertView == null) {
        holder = new ViewHolder();
        switch (rowType) {
            case TYPE_ITEM:
                convertView = mInflater.inflate(R.layout.listview_item, null);
                holder.View=getItem(position).getView(mInflater, convertView);
                break;
            case TYPE_SEPARATOR:
                convertView = mInflater.inflate(R.layout.list_title, null);
                holder.View=getItem(position).getView(mInflater, convertView);
                break;
        }
        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    //here update the holder in else case also.
    }

    return convertView;

答案 2 :(得分:1)

简要背景:

其实我今天遇到了同样的错误。如上所述,我也完成了90-95%的相同实现。但是我也看到了这个Q&amp; A线程的接受答案。但我不能同意你的看法!所以我搜索并搜索了为什么我的简单ArrayAdapter实现无法正常工作。第一次加载好了。但是在我滚动一次之后不久?所有类型的行都混乱不堪!

摘要答案:
阅读Android Developer Doc以获取您可能直接找到线索的更多信息。要为Views行实现多种ListView行,我们必须实现getItemViewType()getViewTypeCount()方法。 getItemViewType()文档为我们提供了如下注释:

  

注意:整数必须在0getViewTypeCount() - 1的范围内。   IGNORE_ITEM_VIEW_TYPE也可以退回。

因此,在getItemViewType()中,您应该返回视图类型的值,从0开始,最后一个类型为(类型数 - 1)。例如,假设您只有两种类型的视图?因此,根据视图的数据对象,您只能在getItemViewType()方法中返回0或1。

如果您没有得到线索或无法解决并需要进一步的信息,请阅读下面的信息:

详细说明:

  

根据Android开发者文档或API Doc,它   已经提到过要在其中实现多种类型的视图   ListView适配器,我们必须实现以下方法:

public int getItemViewType (int position)
public int getViewTypeCount ()
  

在上述两种方法中,getItemViewType对我们来说至关重要   case(我们有多种视图类型)。那是对的吗?那是什么?

     

这就是我和 @ 8BitYoda 出错的地方。 OP的错误之处在于他定义了一个Enum,它不会在0到integers的范围内给出类型(getViewTypeCount() - 1)的范围。

我所做的是,我已经定义了以下类型:

private static final int TYPE_ITEM = 1;
private static final int TYPE_ITEM = 2;

起初我还没有实现getViewTypeCount(),所以我按如下方式实现了它:

public int getViewTypeCount() {
      return 2;
}

然后很快我运行应用程序并尝试使用ListView加载该视图后,它崩溃了,给我以下异常:

  

java.lang.ArrayIndexOutOfBoundsException:length = 2;索引= 2                                                                                在   android.widget.AbsListView $ RecycleBin.addScrapView(AbsListView.java:6643)                                                                                在android.widget.ListView.measureHeightOfChildren(ListView.java:1292)                                                                                在android.widget.ListView.onMeasure(ListView.java:1188)   :
  :
  :
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

说什么? :O

它间接地说它与我从方法getViewTypeCount()返回的整数相关,因为我正在返回2.我返回2因为我只有两种类型。所以我回到Android文档寻求最后的帮助。通过阅读与我实施的方法相关的文档,它确实帮助了我并解决了我的问题。

快速拍摄,请看下面的图像: enter image description here

With a tiny little font, it has given a NOTE for us.


getItemViewType (int position)方法的注释是什么?

  

注意:整数必须在0getViewTypeCount() - 1的范围内。   IGNORE_ITEM_VIEW_TYPE也可以退回。

所以在看到这个之后我明白我需要重新分配我从0开始发送的type integers到我拥有的任何类型的数量,比如基于零的数组索引。所以我重新纠正了这两条线,之后就像魅力一样!

private static final int TYPE_ITEM = 0;
private static final int TYPE_ITEM = 1;

抱歉,我知道我的答案比我预期的要长一点,几乎就像一个迷你教程。但是对我来说没关系我花了大约一个小时+来写这个因为我花了大约5个小时来弄清楚这个愚蠢的错误。谁认为类型应该从0开始分配,比如基于0的数组索引?

所以我希望我的回答可能会对那些解决此错误的人有所帮助。

干杯!!!