25


私が持っているもの:テキストビューとチェックボックスを備えたカスタムリストビュー。


問題:画面に一度に 6 つのリスト項目しか表示できず、他の項目は見えないとします。そこで、リストの最初の要素 (位置 0 の項目) をチェックしました。下にスクロールしてすべてのリストを表示します。最初の要素 (位置 0 の項目) で上にスクロールすると、チェックボックスが正しくチェックされます。すごい!しかし、チェックされる新しいアイテムもあります。たとえば、位置 8 のアイテムです ((Rycicling の) リストをスクロールすると、位置 0 の新しいアイテムになるためです。画面には一度に 7 つの要素しか表示されないことを思い出してください)。そして、チェックされますが、チェックしたことはありません!

質問: この問題を回避するにはどうすればよいですか? クリックしないチェックボックスのステータスを変更したくありません。
setOnCheckedChangeListener を実装した getView 関数を使用した listView のアダプターの下:

public class NewQAAdapterSelectFriends extends BaseAdapter {
private LayoutInflater mInflater;
private Person[] data;


public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context);
}

public void setData(Person[] data) {
    this.data = data;
}

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

@Override
public Object getItem(int item) {
    return data[item];
}

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



@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.item_select_friends, null);
        final ViewHolder viewHolder = new ViewHolder();
        viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
        viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
        viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
        viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);
        convertView.setTag(viewHolder);
        viewHolder.nameText.setTag(viewHolder.nameText);
        viewHolder.nameText.setTag(viewHolder.surnameText);
        viewHolder.contactImage.setTag(data[position]);
        viewHolder.checkBox.setOnCheckedChangeListener(
                new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
                        Person element = (Person) viewHolder.checkBox.getTag();

                        if(isChecked){
                            element.setCheck(buttonView.isChecked());
                            //data[position].setCheck(true); //this is equivalent to previous line

                        }
                        else{
                            //to-do

                        }

                    }
                });
        viewHolder.checkBox.setTag(data[position]);

    } else {


    }

     ViewHolder holder = (ViewHolder) convertView.getTag();
     holder.nameText.setText(data[position].getName());
     holder.surnameText.setText(data[position].getSurname());
     holder.contactImage.setImageResource(data[position].getPhotoRes());
     holder.contactImage.setScaleType(ScaleType.FIT_XY);
     holder.checkBox.setChecked(data[position].isCheck());
    return convertView;
}

static class ViewHolder {
    TextView nameText;
    TextView surnameText;
    ImageView contactImage;
    CheckBox checkBox;
}
}

答えてくれてありがとう:)

編集:提案により、getViewを以下のように変更しました:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.item_select_friends, null);
        viewHolder=new ViewHolder();
        viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
        viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
        viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
        viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);

        convertView.setTag(viewHolder);

        viewHolder.nameText.setTag(viewHolder.nameText);
        viewHolder.nameText.setTag(viewHolder.surnameText);
        viewHolder.contactImage.setTag(data[position]);
        viewHolder.checkBox.setChecked(data[position].isCheck());  
        viewHolder.checkBox.setOnClickListener(new OnClickListener() {  

            public void onClick(View arg0) {  

                if(viewHolder.checkBox.isChecked()==true)   
                    data[position].setCheck(true);  
                else  
                    data[position].setCheck(false);  
            }  
        }); 

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

    viewHolder.nameText.setText(data[position].getName());
    viewHolder.surnameText.setText(data[position].getSurname());
    viewHolder.contactImage.setImageResource(data[position].getPhotoRes());
    viewHolder.contactImage.setScaleType(ScaleType.FIT_XY);
    viewHolder.checkBox.setChecked(data[position].isCheck());
    return convertView;
}

編集後の状況: ここで、画面に表示されている最初の項目を確認してからリストをスクロールすると、それらの値が正しく保存されます。しかし、リストをスクロールすると、たとえば、リストの最後のツリーのチェックボックスをオンにしたい場合、スクロールした後、それらはチェックされなくなります....しかし、なぜ??????

解決済み: getViewの問題を次のコードで解決しました:

    public class NewQAAdapterSelectFriends extends BaseAdapter {
private LayoutInflater mInflater;
private Person[] data;
boolean[] checkBoxState;
ViewHolder viewHolder;

public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context);
}


public void setData(Person[] data) {
    this.data = data;
    checkBoxState=new boolean[data.length];
}

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

@Override
public Object getItem(int item) {
    return data[item];
}

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



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

        viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
        viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
        viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
        viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);

        convertView.setTag(viewHolder);

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

    viewHolder.nameText.setText(data[position].getName());
    viewHolder.surnameText.setText(data[position].getSurname());
    viewHolder.contactImage.setImageResource(data[position].getPhotoRes());
    viewHolder.contactImage.setScaleType(ScaleType.FIT_XY);
    viewHolder.checkBox.setChecked(checkBoxState[position]);
    viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {

           public void onClick(View v) {
               if(((CheckBox)v).isChecked()){
                   checkBoxState[position]=true;
                   data[position].setCheck(true);
               }else{
                   checkBoxState[position]=false;
                   data[position].setCheck(false);
               }
            }
        });
    return convertView;
}


static class ViewHolder {
    TextView nameText;
    TextView surnameText;
    ImageView contactImage;
    CheckBox checkBox;
}

}

getView を実行するためのこのチュートリアルを見ました: http://androidcocktail.blogspot.it/2012/04/adding-checkboxes-to-custom-listview-in.html

4

8 に答える 8

5

「setOnCheckedChangeListener」を「setOnClickListener」に変更するだけで問題を解決しました

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

    ViewHolder holder;

    if (convertView == null) {

        CheckBox cbItemChecklist = new CheckBox(context);

        holder = new ViewHolder();
        holder.cbItemChecklist = cbItemChecklist;

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

    final ItemChecklist itemChecklist = itensChecklist.get(position);

    holder.cbItemChecklist.setText(itemChecklist
            .getDescricaoItemChecklist());
    holder.cbItemChecklist.setChecked(itemChecklist.isChecked());
    holder.cbItemChecklist
            .setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    if(itemChecklist.isChecked()){
                        itemChecklist.setChecked(false);
                    } else {
                        itemChecklist.setChecked(true);                         
                    }


                }
            });
    return convertView;
}
于 2015-04-30T13:35:38.013 に答える
4

以下のコードを確認してください -

public View getView(int position, View convertView, ViewGroup parent){
            View view = convertView;
            ViewHolder holder = new ViewHolder();

            if(view == null){

                view = inflater.inflate(R.layout.list_callcycle_blue, null);                
                holder.llContainer = (LinearLayout) view.findViewById(R.id.ll_container);
                holder.lblLabel = (TextView) view.findViewById(R.id.txt_desc);
                holder.cb = (CheckBox) view.findViewById(R.id.cb_store);

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

            final Object data = getItem(position);
            holder.lblLabel.setText(data.getDescription());

            holder.cb.setTag(position);
            holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    int position = (Integer) buttonView.getTag();
                    objects.get(position).setChecked(buttonView.isChecked());
                }
            });
            holder.cb.setChecked(isChecked(position));

            return view;
        }

常に心に留めておいてください。データを設定する前に変更、holder.cb.setOnCheckedChangeListener() つまり任意のリスナーを使用してください。holder.cb.setChecked()

理由:スクロールすると、listview はビューをリサイクルするため、リスナーの前に setchecked を使用すると、古いリスナーに基づいて値が選択されます。リスナーの後に設定すると、最新の値が取得されます

于 2015-01-20T09:38:11.040 に答える
2

convertview が null の場合にのみ、チェックボックスのタグを設定しています。これは、レコードの最初の画面でのみ発生します。ユーザーが下にスクロールすると、以前の convertviews がリサイクルされます。したがって、チェックボックスには古いデータ項目がタグとして含まれています。

チェック済み変更リスナーは次のようになります。

new CompoundButton.OnCheckedChangeListener()
{
    @Override
    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked)
    {
        Person element = (Person) viewHolder.checkBox.getTag();

        data[position].setCheck(isChecked);

        if(isChecked)
        {
            // do your stuff
        }
        else
        {
            //to-do
        }

    }
}
于 2012-07-05T12:05:57.810 に答える
1

convertView != null のケースをカバーしていませんでした。これは、上下にスクロールするときに発生することです。convertView をリサイクルする方法を実装する (より良い) か、単に無視してこの場合も新しい View を返す (より悪い) 方法を実装する必要があります。

于 2012-07-05T11:59:27.827 に答える
0

このコードを確認してください

public class NewQAAdapterSelectFriends extends BaseAdapter {
private LayoutInflater mInflater;
private Person[] data;
ArrayList<String> checkedItem=new ArrayList<String>();

public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context);
}

public void setData(Person[] data) {
    this.data = data;
}

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

@Override
public Object getItem(int item) {
    return data[item];
}

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



@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.item_select_friends, null);
        final ViewHolder viewHolder = new ViewHolder();
        viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
        viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
        viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
        viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);
        convertView.setTag(viewHolder);
        viewHolder.nameText.setTag(viewHolder.nameText);
        viewHolder.nameText.setTag(viewHolder.surnameText);
        viewHolder.contactImage.setTag(data[position]);
        viewHolder.checkBox.setOnCheckedChangeListener(
                new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
                        Person element = (Person) viewHolder.checkBox.getTag();

                        if(isChecked){
                            getCheckList(data[position],isChecked);
                        }
                        else{
                            getCheckList(data[position],isChecked);    
                        }

                    }
                });
        viewHolder.checkBox.setTag(data[position]);
    } 
     ViewHolder holder = (ViewHolder) convertView.getTag();
     holder.nameText.setText(data[position].getName());
     holder.surnameText.setText(data[position].getSurname());
     holder.contactImage.setImageResource(data[position].getPhotoRes());
     holder.contactImage.setScaleType(ScaleType.FIT_XY);
     if(checkedItem != null && checkedItem.contains(data[position])){
        viewHolder.checkBox.setChecked(true);
     }else
     {
        viewHolder.checkBox.setChecked(false);
     } 
    return convertView;
}

static class ViewHolder {
    TextView nameText;
    TextView surnameText;
    ImageView contactImage;
    CheckBox checkBox;
}
public void getCheckList(String value,boolean status){
        if(!checkedItem.contains(value)  && status)
        {
            checkedItem.add(value);
        }
        if(checkedItem.contains(value)  && !status)
        {
            checkedItem.remove(value);
        }
    }
}
于 2012-07-05T12:08:48.787 に答える