列表项在android自定义列表视图中重复

Posted

技术标签:

【中文标题】列表项在android自定义列表视图中重复【英文标题】:List item repeating in android customized listview 【发布时间】:2013-10-01 22:07:40 【问题描述】:

在我的自定义列表视图中,项目是重复的。项目的位置对于所有项目都是相同的。 代码如下

ListAdapter.java-

    public class ListAdapter extends BaseAdapter

    private List<String> mName;
private List<Drawable> mIcon;
private Context mContext;

public ListAdapter(Context mContext, List<String> Name, List<Drawable> Icon) 
    this.mContext=mContext;
    this.mName=Name;
    this.mIcon=Icon;


@Override
public int getCount() 
    // TODO Auto-generated method stub
    return mName.size();


@Override
public Object getItem(int position) 
    // TODO Auto-generated method stub
    return position;


@Override
public long getItemId(int position) 
    // TODO Auto-generated method stub
    return position;


@Override
public View getView(final int position, View v, ViewGroup parent) 

    View mLayout;
    TextView mText;
    ImageView mImage;
    CheckBox mCheckBox;

    if(v==null)
        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mLayout=new View(mContext);
        mLayout=(LinearLayout) inflater.inflate(R.layout.list_menu, null);

        mText=(TextView) mLayout.findViewById(R.id.Name);
        mImage=(ImageView) mLayout.findViewById(R.id.Icon);
        mCheckBox=(CheckBox) mLayout.findViewById(R.id.mCheckbox);

        mText.setText(mName.get(position));
        mImage.setImageDrawable(mIcon.get(position));

        mCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() 

            @Override
            public void onCheckedChanged(CompoundButton check, boolean isChecked) 
                if(check.isChecked())
                    Toast.makeText(mContext, "..."+mName.get(position)+"..."+position, Toast.LENGTH_SHORT).show();
                
            
        );
       
    else
        mLayout=(View)v;
    
    return mLayout;


  

【问题讨论】:

那么问题到底是什么? listview 项目重复。假设 A,B,C,D 是列表项,则显示 A,B,C,D,A,B,C,D 【参考方案1】:

试试这个,每个转换视图都需要setTag()

 @Override
public View getView(final int position, View convertView, ViewGroup parent) 
    final ViewHolder mHolder;
    if (convertView == null) 
        convertView = mInflater.inflate(R.layout.list_menu, null);
        mHolder = new ViewHolder();

        mHolder.mText=(TextView) convertView.findViewById(R.id.appName);
        mHolder.mImage=(ImageView) convertView.findViewById(R.id.appIcon);
        mHolder.mCheckBox=(CheckBox) convertView.findViewById(R.id.mCheckbox);

        convertView.setTag(mHolder);

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

    return convertView;


private class ViewHolder 
    private TextView mText;
    private ImageView mImage;
    private CheckBox mCheckBox;


【讨论】:

developer.android.com/training/improving-layouts/…。它的视图持有者不仅 setTag。并且视图持有者必须是静态的,为什么视图持有者是最终的? @Raghunandan 感谢您的提示 我几乎吃掉了我的牙齿。谢谢,现在我可以睡觉了;p【参考方案2】:

改变你的getView

 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mLayout=new View(mContext);
    mLayout=(LinearLayout) inflater.inflate(R.layout.list_menu, null);

在您的构造函数中初始化充气机。删除此 mLayout=new View(mContext) 因为您正在使用 mLayout=(LinearLayout) inflater.inflate(R.layout.list_menu, null) 扩展布局

在你的构造函数中

LayoutInflater inflater;
public ListAdapter(Context mContext, List<String> Name, List<Drawable> Icon) 
this.inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.mContext=mContext;
this.mName=Name;
this.mIcon=Icon;

使用 View holder 来实现平滑滚动和性能。

http://developer.android.com/training/improving-layouts/smooth-scrolling.html

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

    ViewHolder vh;
    if(convertView==null)
        vh = new ViewHolder();
        convertView =(LinearLayout) inflater.inflate(R.layout.list_menu, null);

        vh.mText=(TextView) convertView.findViewById(R.id.Name);
        vh.mImage=(ImageView) convertView.findViewById(R.id.Icon);
        vh.mCheckBox=(CheckBox) convertView.findViewById(R.id.mCheckbox);

        convertView.setTag(vh); 
     else  
        vh = (ViewHolder) convertView.getTag(); 
     

    vh.mText.setText(mName.get(position));
    vh.mImage.setImageDrawable(mIcon.get(position));
    vh.mCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() 

        @Override
        public void onCheckedChanged(CompoundButton check, boolean isChecked) 
            if(check.isChecked())
                Toast.makeText(mContext, "..."+mName.get(position)+"..."+position, Toast.LENGTH_SHORT).show();
            
        
    );
    return convertView;


static class ViewHolder

    TextView mText;
    ImageView mImage;
    CheckBox mCheckBox;

【讨论】:

【参考方案3】:
// try this
 public class ListAdapter extends BaseAdapter 

        private List<String> mName;
        private List<Drawable> mIcon;
        private Context mContext;

        public ListAdapter(Context mContext, List<String> Name, List<Drawable> Icon) 
            this.mContext=mContext;
            this.mName=Name;
            this.mIcon=Icon;
        

        @Override
        public int getCount() 
            // TODO Auto-generated method stub
            return mName.size();
        

        @Override
        public Object getItem(int position) 
            // TODO Auto-generated method stub
            return position;
        

        @Override
        public long getItemId(int position) 
            // TODO Auto-generated method stub
            return position;
        

        @Override
        public View getView(final int position, View v, ViewGroup parent) 

            ViewHolder holder;

            if(v==null)
                holder = new ViewHolder();
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v =(LinearLayout) inflater.inflate(R.layout.list_menu, null);

                holder.mText=(TextView) v.findViewById(R.id.Name);
                holder.mImage=(ImageView) v.findViewById(R.id.Icon);
                holder.mCheckBox=(CheckBox) v.findViewById(R.id.mCheckbox);

              v.setTag(holder);
            
            else
               holder = (ViewHolder) v.getTag();
            
            holder.mText.setText(mName.get(position));
            holder.mImage.setImageDrawable(mIcon.get(position));

            holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

                @Override
                public void onCheckedChanged(CompoundButton check, boolean isChecked) 
                    if(check.isChecked())
                        Toast.makeText(mContext, "..."+mName.get(position)+"..."+position, Toast.LENGTH_SHORT).show();
                    
                
            );
            v.setTag(holder);
            return v;
        

         class ViewHolder
            TextView mText;
            ImageView mImage;
            CheckBox mCheckBox;
        

    

【讨论】:

v.setTag(holder); 在您的if(v==null) 语句中将导致NPE。 @Shubham,请检查我更新的答案并感谢您强调它。【参考方案4】:

确保 convertView 不为空。因此将所有代码放在 if(convertView == null) 之后 这确保你有一个值不为 null 的 convertView,如果是的话,通过从上下文中膨胀。

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

  if (convertView == null) 
    LayoutInflater inflater = LayoutInflater.from(context);
    convertView = inflater.inflate(R.layout.list_menu, parent, false);
   

  TextView mText=(TextView) convertView.findViewById(R.id.appName);
  ImageView mImage=(ImageView) convertView.findViewById(R.id.appIcon);
  CheckBox mCheckBox=(CheckBox) convertView.findViewById(R.id.mCheckbox);

  mText.setText(mName.get(position));
  mImage.setImageDrawable(mIcon.get(position));

  return convertView;

【讨论】:

contextView 不应为空。因此在 if(convertView == null) 之后查找视图将解决问题。

以上是关于列表项在android自定义列表视图中重复的主要内容,如果未能解决你的问题,请参考以下文章

Android:自定义列表视图列表元素点击

Android:自定义列表视图无法正常工作

Android:自定义列表视图,适配器中的表格视图

如何在android中使用baseadapter刷新自定义列表视图

按钮未显示在android的自定义列表视图中

无法从android中的自定义列表视图中获取所选项目