Android的列表视图与复选框不到预期效果 [英] Android listview with checkboxes not behaving as expected

查看:123
本文介绍了Android的列表视图与复选框不到预期效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是关于回收问题。我使用的是自定义适配器来填充列表视图。在自定义行有一个形象图,两个文本框和一个复选框。在所有的元素得到填充,但没有填充复选框是否正确。

getView()我执行一个条件,如果条件为真我设置的复选框以启用状态。这工作得很好,但与被选中正确的复选框,还有其他一些复选框越来越打勾为好。我经历了很多栈溢出类似的问题,但无法找到答案。任何帮助是极大的AP preciated。

下面是我的适配器类:

 公共类LocationsListAdapter扩展了BaseAdapter {

    名单<位置>数据;
    上下文语境;
    地点userSelectedLocation;
    私人共享preferences位置preferences;
    私人共享preferences.Editor位置prefsEditor;

    公共LocationsListAdapter(名单<位置>的数据,上下文C){
        this.data =数据;
        this.context = C;
    }

    @覆盖
    公众诠释getCount将(){
        返回data.size();
    }

    @覆盖
    公共对象的getItem(INT位置){
        // TODO自动生成方法存根
        返回data.get(位置);
    }

    @覆盖
    众长getItemId(INT位置){
        // TODO自动生成方法存根
        返回的位置;
    }

    @燮pressWarnings(静态访问)
    @覆盖
    公共查看getView(最终诠释的立场,观点convertView,ViewGroup中父){


        ViewHolder支架=无效;
        Log.v(ConvertView,将String.valueOf(位置));

        如果(convertView == NULL){
            LayoutInflater VI =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.find_your_location_row,NULL);

            持有人=新ViewHolder();
            holder.LocationImage =(SmartImageView)convertView.findViewById(R.id.loca_row_image);
            holder.locationName =(TextView中)convertView.findViewById(R.id.txt_loca_name);
            holder.LocationDescription =(TextView中)convertView.findViewById(R.id.txt_loca_desc);
            holder.locationCheckText =(TextView中)convertView.findViewById(R.id.txt_check);
            holder.locationCheck =(复选框)convertView.findViewById(R.id.location_check);
            holder.locationCheck.setOnCheckedChangeListener(myCheckChangList);
            convertView.setTag(保持器);

            位置preferences = context.getShared preferences(位置preFS,context.MODE_PRIVATE);
            位置prefsEditor =位置preferences.edit();
            字符串locationID =位置preferences.getString(locationID,);

            尝试 {
                如果(locationID.contains(将String.valueOf(data.get(位置).getLocationID()))){
                    holder.locationCheck.setChecked(真正的);
                }
            }赶上(例外五){
                Log.e(致命,异常);
            }


             holder.locationCheck.setOnClickListener(新OnClickListener(){

                    @覆盖
                    公共无效的onClick(视图v){
                        userSelectedLocation = data.get(位置);
                        位置preferences = context.getShared preferences(位置preFS,context.MODE_PRIVATE);
                        位置prefsEditor =位置preferences.edit();
                        串userSelectedLocationID = userSelectedLocation.getLocationID();
                        位置prefsEditor.clear();
                        位置prefsEditor.putString(locationID,userSelectedLocationID);
                        位置prefsEditor.commit();
                        意向意图=新的意图(背景下,HomeScreen.class);
                        context.startActivity(意向);
                        Log.e(复选框,点击);
                    }
            });

        }其他 {
            支架=(ViewHolder)convertView.getTag();
           }

        最终位置位置= data.get(位置);

        holder.LocationImage.setImageUrl(location.getImagePath());
        holder.locationName.setText(location.getLocationName());
        holder.LocationDescription.setText(location.getLocationDescription());

        返回convertView;
    }

    @覆盖
    公共无效unregisterDataSetObserver(DataSetObserver观察者){
        如果(观察者!= NULL){
            super.unregisterDataSetObserver(观察员);
        }
    }

    保护类ViewHolder {
        保护SmartImageView LocationImage;
        受保护的TextView LOCATIONNAME;
        受保护的TextView LocationDescription;
        受保护的TextView locationCheckText;
        保护复选框locationCheck;
    }

    OnCheckedChangeListener myCheckChangList =新OnCheckedChangeListener(){
        公共无效onCheckedChanged(CompoundButton buttonView,
                布尔器isChecked){
            Log.e(选中,);
        }
    };
}
 

解决方案

我相信,你的问题就出在你的if / else语句。

如果convertView为null,则创建一个新的观点,并与所有正确的数据来填充它,但如果它不为空(即它是一个循环视图),只需返回完全相同的观点从标签背面。因此它保持了状态,它已经有了(其中一些被检查)

您不这样做有关于设置其属性视图什么

设置你的属性之后,你有一个有效的viewHolder。

您现在有这种模式。

 如果(convertView == NULL){
    //你的code创建视图
    //你的code设置视图属性
}其他 {
    支架=(ViewHolder)convertView.getTag();
}
 

改成这样(移动code,设置外视图属性的if / else,使视图属性可以为所有的观点,无论他们是否是回收来设置。

 如果(convertView == NULL){
        LayoutInflater VI =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.find_your_location_row,NULL);

        持有人=新ViewHolder();
        holder.LocationImage =(SmartImageView)convertView.findViewById(R.id.loca_row_image);
        holder.locationName =(TextView中)convertView.findViewById(R.id.txt_loca_name);
        holder.LocationDescription =(TextView中)convertView.findViewById(R.id.txt_loca_desc);
        holder.locationCheckText =(TextView中)convertView.findViewById(R.id.txt_check);
        holder.locationCheck =(复选框)convertView.findViewById(R.id.location_check);
        convertView.setTag(保持器);
    } 其他 {
        支架=(ViewHolder)convertView.getTag();
    }

    地点位置= data.get(位置);

    holder.LocationImage.setImageUrl(location.getImagePath());
    holder.locationName.setText(location.getLocationName());
    holder.LocationDescription.setText(location.getLocationDescription());
    布尔ShouldBoxBeChecked = //将检查这里当前框
    holder.locationCheck.setChecked(ShouldBoxBeChecked);
 

This is regarding the recycling issue. I am using a custom adapter to populate the list view. In the custom row there is an image view, two text boxes and a check box. The all the elements get populated but the check box is not populated correctly.

Inside the getView() I perform a condition and if the condition is true I set the check box to enable state. This works fine but with the correct check box which is ticked, there are some other check boxes getting ticked as well. I went through many stack overflow similar questions but was unable to find an answer. Any help is greatly appreciated.

Below is my adapter class:

public class LocationsListAdapter extends BaseAdapter {

    List<Locations> data;
    Context context;
    Locations userSelectedLocation;
    private SharedPreferences locationPreferences;
    private SharedPreferences.Editor locationPrefsEditor;

    public LocationsListAdapter(List<Locations> data, Context c) {
        this.data = data;
        this.context = c;
    }

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

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return data.get(position);
    }

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

    @SuppressWarnings("static-access")
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {


        ViewHolder holder = null;
        Log.v("ConvertView", String.valueOf(position));

        if (convertView == null) {
            LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.find_your_location_row, null);

            holder = new ViewHolder();
            holder.LocationImage = (SmartImageView) convertView.findViewById(R.id.loca_row_image);
            holder.locationName = (TextView) convertView.findViewById(R.id.txt_loca_name);
            holder.LocationDescription = (TextView) convertView.findViewById(R.id.txt_loca_desc);
            holder.locationCheckText = (TextView) convertView.findViewById(R.id.txt_check);
            holder.locationCheck = (CheckBox) convertView.findViewById(R.id.location_check);
            holder.locationCheck.setOnCheckedChangeListener(myCheckChangList);
            convertView.setTag(holder);

            locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE);
            locationPrefsEditor = locationPreferences.edit();
            String locationID  = locationPreferences.getString("locationID", "");

            try {
                if(locationID.contains(String.valueOf(data.get(position).getLocationID()))){
                    holder.locationCheck.setChecked(true);
                }
            } catch (Exception e) {
                Log.e("Fatal", " Exception");
            }


             holder.locationCheck.setOnClickListener( new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        userSelectedLocation = data.get(position);
                        locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE);
                        locationPrefsEditor = locationPreferences.edit();
                        String userSelectedLocationID = userSelectedLocation.getLocationID();
                        locationPrefsEditor.clear();
                        locationPrefsEditor.putString("locationID", userSelectedLocationID);
                        locationPrefsEditor.commit();
                        Intent intent = new Intent(context, HomeScreen.class);
                        context.startActivity(intent);
                        Log.e("Check Box ", "Clicked");
                    }
            });

        }else {
            holder = (ViewHolder) convertView.getTag();
           }

        final Locations location = data.get(position);

        holder.LocationImage.setImageUrl(location.getImagePath());
        holder.locationName.setText(location.getLocationName());
        holder.LocationDescription.setText(location.getLocationDescription());

        return convertView;
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        if (observer != null) {
            super.unregisterDataSetObserver(observer);
        }
    }

    protected class ViewHolder {
        protected SmartImageView LocationImage;
        protected TextView locationName;
        protected TextView LocationDescription;
        protected TextView locationCheckText;
        protected CheckBox locationCheck ;
    }

    OnCheckedChangeListener myCheckChangList = new OnCheckedChangeListener() {
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
            Log.e("checked", "");
        }
    };
}

解决方案

I believe your problem lies in your if/else statement.

If convertView is null then you create a new view and populate it with all the correct data but if it is not null (i.e it is a recycled view), you simply return the exact same view back from the tag. You do not do anything with the view regarding setting its properties so it maintains the state it already had (some of which were checked)

Set your properties after you have a valid viewHolder.

You currently have this model.

if (convertView == null) {
    //Your code to create the view
    // Your code to set the view properties
}else {
    holder = (ViewHolder) convertView.getTag();
}

Change it to this (move the code that sets the view properties outside the if/else so that the view properties can be set for all views regardless of whether they are recycled.

 if (convertView == null) {
        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.find_your_location_row, null);

        holder = new ViewHolder();
        holder.LocationImage = (SmartImageView) convertView.findViewById(R.id.loca_row_image);
        holder.locationName = (TextView) convertView.findViewById(R.id.txt_loca_name);
        holder.LocationDescription = (TextView) convertView.findViewById(R.id.txt_loca_desc);
        holder.locationCheckText = (TextView) convertView.findViewById(R.id.txt_check);
        holder.locationCheck = (CheckBox) convertView.findViewById(R.id.location_check);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    Locations location = data.get(position);

    holder.LocationImage.setImageUrl(location.getImagePath());
    holder.locationName.setText(location.getLocationName());
    holder.LocationDescription.setText(location.getLocationDescription());
    boolean ShouldBoxBeChecked = //Insert check for the current box here
    holder.locationCheck.setChecked(ShouldBoxBeChecked);

这篇关于Android的列表视图与复选框不到预期效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆