0

私のリストビューには若干の問題があります。すべての項目にはいくつかの情報とチェックボックスがあります。私はいくつかの奇妙な行動を発見しかし、これは罰金、私はチェックボックスを選択し、選択解除することができますなどなど多くのチェックボックスが付いているListViewアダプタ

を示しています。最初の行の最初のチェックボックスをクリックします。 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; 
    } 
} 

答えて

2

:)示す項目にのみ動作し、notifyDatasetChanged()を呼び出して、あなたのcheckAllBoxesでブール配列を変更することができますチェックするために

あなたは、チェックボックスの状態のための代替修正を持っているためにここにサンプルコードを見ることができます:この記事はあなたを助け

custom checkbox difficulty in android

場合、答えとしてこのポストをマークしてください。

ありがとうございました。

1

おそらくあなたは、アダプタでリサイクルのビューを処理する方法に関連している問題。 getViewを見て、返す各項目のCheckBoxが「モデル」に従って正しく設定されているかどうかを確認してください。

編集:確認します。テキストビューのテキストと同じように、チェックボックスの状態を設定する必要があります。 私はあなたがやっているやり方でチェックボックスを処理することは悪い考えだと思います。あなたができる最も良いことは、チェックボックスのための "モデル"を定義することです(iE:単純なブール値[]がトリックを行うことができます)。 getViewでは、対応するbooleanをチェックし、それに応じてチェックボックスを設定することができます。 /それらをすべてオフに、あなたがして、リストビューに更新をトリガするが、実際に

+0

私はあなたの答えを見ました。私は問題を理解しました!それはこのようなものになると考えました。説明と素晴らしいソリューションをありがとう! –

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; 
    } 
} 
+0

すごくいいですね!彼の編集前にarchanosの投稿を見た後、何か類似のものを考えていたのですが、紙に書いてありがとう! –

+0

実際には、いくつかのテストの後、このアプローチは合法ではありません。問題は、チェックボックスがスクロールして見えなくなったときにonCheckedChangedが呼び出されることです。そのために状態は保存されません。私は、Joeyの答えのリンクに示されているように、代わりにOnClickを使用することにしました。 –

1

mr_archanoはあなたがすることができますconvertView使用しているbecuaseこの問題が発生し、右側で表示されなくなった再利用/リサイクルビューの。ここでは、これを適切に行う必要があるべきだ:

あなたのListView項目のがリサイクルされているので、各チェックボックス

の状態を保持するオブジェクトは、あなたが正しい状態を保持するためにそれらに頼ることはできませんあなたのチェックボックス。したがって、各リストアイテムのチェックボックスの正しい状態を保持するために、ある種のオブジェクト/配列が必要になります。あなたがgetViewメソッドを呼び出すときに、状態管理オブジェクトから

を読む

はその後、あなたはそのオブジェクト/配列の状態に基づいて確認/未チェックの横にあるチェックボックスの値を設定する必要があります。状態管理オブジェクトあなたが正しくあなたの声明管理オブジェクト/配列にそのチェックボックスの値を設定することができますように、各チェックボックスのためにOnCheckedリスナーのいくつかの並べ替えを実装する必要が

への書き込み

あなたはViewHolderの

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

このチュートリアルでは、あなたが必要なものほとんどありません:http://windrealm.org/tutorials/android/listview-with-checkboxes-without-listactivity.php

+0

さらに詳しい説明をありがとう!彼が最初だったので、しかし、archanoに答えを与える –

0

は、私は大規模なリストを扱う同じ問題を抱えています。私が好きな人は、Googleを使ってここで見つけることができます。私の解決策を教えてください。私は理解しやすいと思います。人が指摘したように、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; 
} 
}); 

あなた自身の方法であなたの未チェック/チェックを状態を保つ必要があります。

関連する問題