0

リストビューに小さな問題があります。すべてのアイテムには、いくつかの情報とチェックボックスがあります。これは問題なく表示され、チェックボックスなどを選択および選択解除できます。

しかし、私はいくつかの奇妙な行動を発見しました。最初の行の最初のチェックボックスをクリックするとします。ListView が小さいため、下にスクロールする必要がない場合、これは正常に機能します。しかし、ListView が大きいため、下にスクロールしてすべてのアイテムを表示する必要がある場合、下部にあるランダムなアイテムもクリックされます。リストビューの下部にあるチェックボックスをクリックして上にスクロールすると、上部のランダムなチェックボックスもクリックされます。どこかでいくつかのチェックボックスをクリックすると、同じ量のクリックされたチェックボックスがある他の場所があります。これは、GetView(...) が呼び出されたとき、つまり更新時に発生すると考えました。その後、いくつかの新しいチェックボックスがクリックされますが、その理由はわかりません。

ここでいくつかの助けに感謝します! :)

私のアダプターの SSSCE:

public class ListViewAdapterSSCCE : BaseAdapter
{
    private Activity myActivity;
    private string[] someData;
    private int numberOfElements;
    private CheckBox[] boxes;

    public ListViewAdapterSSCCE(Activity activity)
    {
        this.myActivity = activity;

        for (int i = 0; i < numberOfElements; i++)
            this.boxes[i] = new CheckBox(myActivity);
    }

    public void SetData(string[] someData)
    {
        this.someData = someData;
        this.numberOfElements = someData.Length;
    }

    public void CheckAllBoxes(bool isChecked)
    {
        for (int i = 0; i < numberOfElements; i++)
            this.boxes[i].Checked = isChecked;
    }

    public override Java.Lang.Object GetItem(int position)
    {
        return null;
    }

    public override long GetItemId(int position)
    {
        return 10;
    }

    public override int Count
    {
        get { return numberOfElements; }
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        if (convertView == null)
        {
            LayoutInflater inflater = (LayoutInflater)myActivity.GetSystemService(Context.LayoutInflaterService);
            convertView = inflater.Inflate(Resource.Layout.ChildrenList_item, null);
        }

        var itemBox = convertView.FindViewById<CheckBox>(Resource.Id.checkbox);
        this.boxes[position] = itemBox;

        var textView = convertView.FindViewById<TextView>(Resource.Id.item_data);
        textView.Text = this.someData[position];

        return convertView;
    }
}
4

5 に答える 5

3

前述のように、問題は getView でチェックボックスの値を設定していないことです。

また、コードの効率をかなり改善できます。最初にすべきことは、チェックボックスの配列を作成する代わりに、子ビュー xml にチェックボックスを追加することです。代わりにブール配列を作成して値を格納します。

Javaの場合と同じようにこれを修正しているため、C#で変更する必要がある場合があることに注意してください。

 public class ListViewAdapterSSCCE : BaseAdapter
    {
    private string[] someData;
    private int numberOfElements;
    private boolean[] checkValue;
    private LayoutInflater inflater;

    public ListViewAdapterSSCCE(Context context)
    {

        inflater = LayoutInflater.from(context);
    }

    public void SetData(string[] someData)
    {
        this.someData = someData;
        this.numberOfElements = someData.Length;
    }

    public void CheckAllBoxes(bool isChecked)
    {
        for (int i = 0; i < numberOfElements; i++)
            checkValue[i] = true;
    }

    public override Java.Lang.Object GetItem(int position)
    {
        return null;
    }

    public override long GetItemId(int position)
    {
        return 10;
    }

    public override int Count
    {
        get { return numberOfElements; }
    }

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

        final ViewHolder holder; 

        if (convertView == null)
        {            
            convertView = inflater.Inflate(Resource.Layout.ChildrenList_item, null);

            holder = new ViewHolder();
            holder.itemBox = convertView.FindViewById<CheckBox>(Resource.Id.checkbox);
            holder.textView = convertView.FindViewById<TextView>(Resource.Id.item_data);

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

        itemBox = checkValue[position];    

        itemBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

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

                        checkValue[positon] = isChecked;

            }

        });

        textView.Text = this.someData[position];

        return convertView;
    }

    class ViewHolder
    {
        CheckBox itemBox;
        TextView textView; 
    }
}
于 2012-04-24T13:29:31.057 に答える
2

ここでサンプル コードを参照して、チェックボックスの状態の代替修正を行うことができます。

Androidでのカスタムチェックボックスの難しさ

この投稿が役に立った場合は、この投稿を回答としてマークしてください。

ありがとう。

于 2012-04-24T13:27:56.693 に答える
1

この問題は、アダプターでリサイクルされたビューを処理する方法に関連している可能性があります。を見て、getView返される各アイテムのチェックボックスが「モデル」に従って正しく設定されているかどうかを確認してください。

編集:確認します。テキストビューのテキストと同じように、チェックボックスの状態を設定する必要があります。ところで、チェックボックスを自分のやり方で扱うのは悪い考えだと思います。あなたができる最善のことは、チェックボックスの「モデル」を定義することです(つまり、単純なブール値[]でうまくいくことができます)、あまりにも多くのチェックボックスをインスタンス化しないようにします。getViewで、対応するブール値をチェックし、それに応じてチェックボックスを設定できます。

それらすべてをチェック/チェック解除するには、checkAllBoxesのブール配列を変更してからnotifyDatasetChanged()を呼び出し、リストビューで更新をトリガーしますが、実際に表示されているアイテムのみを操作します:)

于 2012-04-24T13:04:47.213 に答える
1

mr_archano は正しいです。これは、ビューに表示されなくなったビューを再利用/リサイクルできる convertView を使用しているために発生します。これを適切に行うために必要なものは次のとおりです。

各チェックボックスの状態を保持するオブジェクト

リストビュー項目はリサイクルされているため、チェックボックスの正しい状態を保持するためにそれらに依存することはできません. したがって、各リスト項目のチェックボックスの正しい状態を保持するには、ある種のオブジェクト/配列が必要になります。

状態管理オブジェクトからの読み取り

次に、GetView を呼び出すときに、そのオブジェクト/配列の状態に基づいてチェックボックスの値をチェック/チェック解除に設定する必要があります。

状態管理オブジェクトへの書き込み

ステートメント管理オブジェクト/配列でそのチェックボックスの値を正しく設定できるように、チェックボックスごとにある種の OnChecked リスナーを実装する必要があります。

ViewHolder の

ViewHolder は非常に単純です。最初にビューを作成するとき (変換ビューを使用しない)、"FindViewByID" を呼び出して、テキスト ボックスとチェックボックスへの参照を取得する必要があります。それらをViewHolderに保存すると、ConvertViewオブジェクトを使用するときにそれらを直接参照できるはずです。これにより、「FindViewByID」への追加の呼び出しが節約されます。それを実際に見る方がはるかに簡単です。

このチュートリアルでは、必要なことのほとんどを行います: http://windrealm.org/tutorials/android/listview-with-checkboxes-without-listactivity.php

于 2012-04-24T13:30:45.897 に答える
0

大きなリストを扱うのと同じ問題があります。私のような人がここでグーグルで見つけたので、私は私の解決策を与えたいと思います、私はそれがより理解しやすいと思います。みんなが指摘したように、ListViewビューを再利用しました。したがって、ビューにデータ状態を保持させないでください。

私はSimpleAdapter、カスタマイズされた設定を使用して、ViewBinderこの問題を修正するのは簡単であることがわかりました。

listItemAdapter.setViewBinder(new SimpleAdapter.ViewBinder() {

    public boolean setViewValue(View view, Object obj, String s) {

    if(view instanceof CheckBox){
        ((CheckBox)view).setChecked((Boolean)obj);
        return true;
    }
    return false;
}
});

チェック済み/チェックなしの状態を独自の方法で維持する必要があります。

于 2012-07-26T07:11:14.540 に答える