我实现了一个正常工作的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;
}
}
答案 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()
文档为我们提供了如下注释:
注意:整数必须在
0
到getViewTypeCount() - 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文档寻求最后的帮助。通过阅读与我实施的方法相关的文档,它确实帮助了我并解决了我的问题。
With a tiny little font, it has given a NOTE for us.
getItemViewType (int position)
方法的注释是什么?
注意:整数必须在
0
到getViewTypeCount() - 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的数组索引?
所以我希望我的回答可能会对那些解决此错误的人有所帮助。
干杯!!!