自定义 ListView 重复一行

Posted

技术标签:

【中文标题】自定义 ListView 重复一行【英文标题】:Custom ListView is repeating one row 【发布时间】:2017-01-11 17:51:12 【问题描述】:

我创建了一个 自定义 ListView,其中包含一个 ImageView 和一个 TextView。我还从 ArrayAdapter 创建了 自定义适配器,并且我正在使用 类数组 (MonsterLink[]) 来获取适配器的所有信息。但 ListView 仍在重复一行。我试图在这里找到解决方案(我确实做到了,使用 setTag、getTag)但它没有帮助,我也不太明白。这是我的第一个应用程序。

CreateView 我调用适配器的地方: @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) //加载视图 this.MyView = inflater.inflate(R.layout.fragment_list, container,false);

    //Change the category label
    SetCategoryLabel();

    //Load DB;
    LoadDatabase();

    //Create list for MonsterList
    MonsterLink[] MonsterLinkList = LoadMonsterLinkList();
    MonsterAdapter monsteradapter = new MonsterAdapter(this.getContext(), MonsterLinkList);
    ListView MonsterList = (ListView) MyView.findViewById(R.id.list_Monsters);
    MonsterList.setAdapter(monsteradapter);

    // Inflate the layout for this fragment
    return this.MyView; //inflater.inflate(R.layout.fragment_list, container, false);

我的适配器:

 public class MonsterAdapter extends ArrayAdapter<MonsterLink> 

public MonsterAdapter(Context context, MonsterLink[] MonsterNames) 
    super(context, R.layout.monster_row, MonsterNames);


@Override
public View getView(int position, View convertView, ViewGroup parent) 
    final ViewHolder mHolder;

    // Get the data item for this position
    MonsterLink monster = getItem(position);
    // Check if an existing view is being reused, otherwise inflate the view
    if (convertView == null)
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.monster_row,parent,false);
        mHolder = new ViewHolder();

        /**TextView MonsterName = (TextView) convertView.findViewById(R.id.txt_MonsterName);
        ImageView MonsterPic = (ImageView) convertView.findViewById(R.id.img_MonsterPic);**/

        mHolder.mName = (TextView) convertView.findViewById(R.id.txt_MonsterName);
        mHolder.mPic = (ImageView) convertView.findViewById(R.id.img_MonsterPic);

        convertView.setTag(mHolder);


    else 
        mHolder = (ViewHolder) convertView.getTag();
    



    mHolder.mName.setText(monster.getName());

    return convertView;



private class ViewHolder
    private TextView mName;
    private ImageView mPic;

正如我所说,这是我在 android 上的第一个应用程序,我真的不明白适配器中的 ViewHolder 是如何工作的。

编辑 - 新适配器 我的适配器现在看起来像这样:

public class MonsterAdapter extends BaseAdapter 
@Override
public int getCount() 
    return monsterList.size();


@Override
public long getItemId(int position) 
    return 0;


@Override
public Object getItem(int position) 
    return null;


ArrayList<MonsterLink> monsterList;
Context context;

public MonsterAdapter(Context context, ArrayList<MonsterLink> MonsterNames) 
    this.monsterList = MonsterNames;
    this.context = context;


@Override
public View getView(int position, View convertView, ViewGroup parent) 
    // Get the data item for this position
    MonsterLink monster = monsterList.get(position);
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.monster_row,parent,false);

    TextView name = (TextView) convertView.findViewById(R.id.txt_MonsterName);
    ImageView pic = (ImageView) convertView.findViewById(R.id.img_MonsterPic);
    name.setText(monster.getName());
    return convertView;


我现在看不到任何行

【问题讨论】:

【参考方案1】:

尝试从类中扩展您的适配器

基础适配器

另外,尝试制作一个本地 MonsterLink 数组列表以包含适配器中的列表 猜你不会显示大量数据,如果你不回收你的视图也没关系,因为如果那是你想要的,我强烈推荐你 RecyclerView。

尝试以下(未测试):

    public class MonsterAdapter extends BaseAdapter 

        ArrayList<MonsterLink> monsterList;
        Context context;
        public MonsterAdapter(Context context, MonsterLink[] MonsterNames) 
            this.monsterList = MonsterNames;
            this.context = context;
        

       @Override
       public View getView(int position, View convertView, ViewGroup parent) 
    // Get the data item for this position
            MonsterLink monster = monsterList.get(position);
           LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.monster_row,parent,false);

        /**TextView MonsterName = (TextView) convertView.findViewById(R.id.txt_MonsterName);
        ImageView MonsterPic = (ImageView) convertView.findViewById(R.id.img_MonsterPic);**/

        TextView name = (TextView) convertView.findViewById(R.id.txt_MonsterName);
        ImageView pic = (ImageView) convertView.findViewById(R.id.img_MonsterPic);
        //name.setText('bla bla')
        //name.setText(monster.getName())
        return convertView;

       


       @Override
       public int getCount() 
          return monsterList.size();
       

【讨论】:

什么意思?您可以看到我将 MonsterLink[] MonsterNames 作为参数发送到适配器。这个数组已经被填满了。在 MonsterLink[] 我有两个对象(两个名称),但 ListView 在每一行都显示相同的名称。 有效吗? @Somachr 不,我打不通super(context); 它说我不能在这里使用上下文。 对不起,删除超级。不需要调用父构造函数 已编辑问题现在我看不到任何 ListView(无行)。我已将 MonsterLink[] 更改为 ArrayList 并检查它是否已填充。【参考方案2】:

感谢@Firecat,我(我们)发现错误不在适配器中,而是在创建项目列表时。然后将该列表发送到适配器。

while (cursor.moveToNext())
            List.add(new MonsterLink(cursor.getString(0),cursor.getString(1),cursor.getString(2)));
        
        cursor.close();

这通常可以正常工作,但我的对象 MonsterLink 包含以下内容:

public class MonsterLink 

private Static String Name;
private Static String PicPath;
private Static String MonsterID;

我不应该使用静态变量! 每次我创建新的 MonsterLink 时,我都会为数组中的每个对象更改这三个变量。

【讨论】:

以上是关于自定义 ListView 重复一行的主要内容,如果未能解决你的问题,请参考以下文章

自定义单选 ListView

Ellipsize 不适用于自定义 listView 中的 textView

处理自定义列表项单击导航抽屉 ListView 内

listView中带有复选框的自定义布局:当我删除一行时,如果选中它(checkBox = true),则下一行将获得检查

Android - ListView 中的 EditTexts 绑定到自定义 ArrayAdapter - 跟踪更改

使用自定义适配器刷新可见 ListView