ListView数据在滚动时被清除[重复]

Posted

技术标签:

【中文标题】ListView数据在滚动时被清除[重复]【英文标题】:ListView Data got cleared on scrolling [duplicate] 【发布时间】:2015-05-29 06:03:02 【问题描述】:

我正在开发一个显示listViewcheckBoxes 的应用程序。 当我滚动 listView 时,CheckBoxes 的值被清除。

下面是我的代码

适配器类:

public class Conference_listViewAdapter extends BaseAdapter 
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();
    ViewHolder holder;
    int pos;

    public Conference_listViewAdapter(Activity context,List<Model> list, ArrayList<String> id_list) 
        data = list;
        this.id_list = id_list;     
        this.context = context;
    


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


    @Override
    public Object getItem(int position) 
        return data.get(position).getName();
    

    @Override
    public long getItemId(int position) 
        return Long.valueOf(id_list.get(position));
    

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

        View view = null;

        if (convertView == null) 
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);
            holder.favorite.setTag(position);
            view.setTag(holder);

            holder.favorite.setTag(data.get(position));
         else 
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        


        holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() 

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)                     
                Model element = (Model) holder.favorite.getTag();
                element.setSelected(buttonView.isChecked());     
                //notifyDataSetChanged();
            
        );


        ViewHolder holder = (ViewHolder) view.getTag();

        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());



        try 
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
         catch (Exception e) 
            e.printStackTrace();
        

        return view;
    

    class ViewHolder 
        TextView title;
        TextView model;
        ImageView image;
        CheckBox favorite;
    



数据模型类

public class Model 

    private String name;
    private boolean selected;

    public Model(String name) 
        this.name = name;
        selected = false;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public boolean isSelected() 
        return selected;
    

    public void setSelected(boolean selected) 
        this.selected = selected;
    

 

不知道我哪里做错了。

【问题讨论】:

我猜你没有使用 notifydatasetchaned() 方法 你可以这样做:***.com/a/29208904/4693713谢谢.. 出现错误 > 隐式超级构造函数 ArrayAdapter() 未定义。必须显式调用另一个构造函数 在你的构造函数中调用super(....) 感谢我解决了这个错误 【参考方案1】:

改变这个..

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

到..

  @Override
public Object getItem(int position) 
    return data.get(position);

更新:

试试这个..

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

    View view = null;

    if (convertView == null) 
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.people_list_item1, null);
        holder = new ViewHolder();
        holder.title = (TextView) view.findViewById(R.id.tv_name);
        holder.image = (ImageView) view.findViewById(R.id.avtaar);
        holder.favorite = (CheckBox) view.findViewById(R.id.fav);
        holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() 

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)                     
               //do what you want..   
            
        );

        view.setTag(holder);
     else 
       holder = (ViewHolder) view.getTag();
    

    holder.favorite.setChecked(data.get(position).isSelected());
    holder.title.setText(data.get(position).getName());



    try 
        holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
     catch (Exception e) 
        e.printStackTrace();
    

    return view;

【讨论】:

试过不适合我:(【参考方案2】:

在类似的情况下,如带有复选框、单选按钮、计数框等的列表视图,我使用如下操作 1)保持一个与listview(行数)大小相似的arraylist 2)这个数组/数组列表将在适配器类的构造函数中初始化,所有位置为零 3) 在声明复选框并将其标签设置为位置后的 getView() 内

public class Conference_listViewAdapter extends BaseAdapter 
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();
     ArrayList<String> myarray=new java.util.ArrayList<String>();   
    ViewHolder holder;
    int pos;


    public Conference_listViewAdapter(Activity context,List<Model> list, ArrayList<String> id_list) 
        data = list;
        this.id_list = id_list;
        this.context = context;
for(int i=0;i<id_list.size();i++)
myarray.add("0");
    


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


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

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

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

        View view = null;

        if (convertView == null) 
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);
            holder.favorite.setTag(position);
            view.setTag(holder);

if(myarray.get(Integer.parseInt(holder.favorite.getTag().toString()).equalsIgnoreCase("1")
//make your checkbox checked
else
//keep checkbox unchecked
            holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() 

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)                     
   if(  isChecked)                   myarray.set(Integer.parseInt(holder.favorite.getTag().toString()),"1");    

else
myarray.set(Integer.parseInt(holder.favorite.getTag().toString()),"0"); 

notifydatasetchanged();
            );

            holder.favorite.setTag(data.get(position));
         else 
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        


        ViewHolder holder = (ViewHolder) view.getTag();

        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());



        try 
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
         catch (Exception e) 
            e.printStackTrace();
        

        return view;
    

    class ViewHolder 
        TextView title;
        TextView model;
        ImageView image;
        CheckBox favorite;
        Boolean selected;
       


这总是可以解决我的列表视图滚动问题..

【讨论】:

我没有得到这个,你能在我的代码中修改它吗? @yushi 检查编辑【参考方案3】:

我认为这是一个常见错误。您需要设置此代码 holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() 在 if/else 块之外。原因是 convertView is = null 是否需要设置监听器。我意识到您的代码可能需要一些安排,但我认为您可以比我做得更好,因为我的代码风格不同。这是否足够清楚?

另一个可能的错误是holder.favorite.setTag(position)。原因是您的侦听器中的代码Model element = (Model) holder.favorite.getTag()。您正在保存 int position 并将其类型转换为 Model 类,但无法正常工作。改覆盖getItem,先做编码。示例代码总结:

@Override
    public Object getItem(int position) 
        return data.get(position);   // return the Model
    
...
holder.favorite.setTag( getItem(position) );

注意:holder.favorite.setTag 应该设置在 outside if/else 块中。 if 块中只能设置 view.setTag(holder),因为它是一个新的视图对象。

除此之外,我认为你的代码设计应该可以工作!

建议的代码更改...

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

ViewHolder holder = null;    // different

if (convertView == null) 
   ...
   holder.favorite.setTag(data.get(position));    // different
   view.setTag(holder);                           // different


else 
   view = convertView;
   holder = (ViewHolder) view.getTag();    // different

...
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
   Model element = (Model) buttonView.getTag();    // different

变化是:

    我使用 不同 的 cmets 来强调代码更改。 ViewHolder holdergetView() 中声明。删除类内顶部的持有人声明。我认为这是更好的编码风格,因为持有者更接近于找到您使用它的位置,使其成为本地 getView。 holder.favorite.setTagview.setTag 的位置已切换。我认为这是一种更安全的编码风格。我认为在将其用作对象视图的参数之前先设置持有人会更安全。我承认,这可能无关紧要。 当 convertView is not = null 时,view.getTag 是必需的。当您在同一块中使用view.getTag()).favorite.setTag 设置标签时,您实际上是在以意外行为更改持有者的内容。 在代码 (Model) buttonView.getTag() 中,使用 buttonView 代替 holder.favorite。我希望这会得到正确的模型对象。

【讨论】:

有时我会发布示例代码,但我现在需要做一些事情。 我刚刚在“建议的代码更改”下完成了我发布的更新。我希望它对你也有意义。我们都会犯错。 哦..删除代码“ViewHolder holder = (ViewHolder) view.getTag();”在 else 块下。你不再需要那个地方的代码了。 让我们continue this discussion in chat。【参考方案4】:

您必须保存ViewHolder 的状态。然后在convertView == null时设置tag,在else条件下获取。

检查我的做法:

public class Conference_listViewAdapter extends ArrayAdapter<Model> 
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();

    int pos;


    public Conference_listViewAdapter(Activity context, List<Model> list, ArrayList<String> id_list) 
        super(context, R.layout.people_list_item1, list);
        this.context = context;
        this.data = list;
        this.id_list = id_list; 
    



    public View getView(final int position, View convertView, ViewGroup parent) 
        View view = null;       
        if (convertView == null) 
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            final ViewHolder holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);

            view.setTag(holder);

            holder.favorite.setTag(data.get(position));

            holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() 

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)                     
                    Model element = (Model) holder.favorite.getTag();
                    element.setSelected(buttonView.isChecked());     
                
            );


         else 
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        





        ViewHolder holder = (ViewHolder) view.getTag();     
        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());

        try 
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
         catch (Exception e) 
            e.printStackTrace();
        

        return view;
    




    static class ViewHolder 
        protected TextView title;
        protected CheckBox favorite;
        ImageView image;
    

【讨论】:

我会尽力让你知道 你为什么要设置tag两次holder.favorite.setTag(position);&holder.favorite.setTag(data.get(position)); 我试过你的代码,但它不适合我 为什么要扩展 ArrayAdapter

以上是关于ListView数据在滚动时被清除[重复]的主要内容,如果未能解决你的问题,请参考以下文章

ListView 中的复选框在离开屏幕时被重置

ListView如何清除选择[重复]

如何使 WPF ListView 项目水平重复,如水平滚动条?

Flutter ListView.builder在滚动时结结巴巴并跳到顶部[重复]

如何在 Flutter 中自动滚动 Listview.separated 中的所有 List Tiles?

滚动时带有按钮随机选择的Listview项目[重复]