0

내 listview에 약간의 문제가 있습니다. 모든 항목에는 몇 가지 정보와 확인란이 있습니다. 이것은 잘 나타나고 체크 박스를 선택하거나 해제 할 수 있습니다.많은 체크 박스가있는 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 : 간단한 부울 []이 트릭을 할 수 있습니다). 너무 많은 CheckBox를 인스턴스화하지 않아야합니다. getView에서 해당 부울을 검사하고 그에 따라 체크 박스를 설정할 수 있습니다./모두의 선택을 취소하면 다음 목록보기에 업데이 트를 유발하지만, 실제로

+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 이런 일이 발생, 권리보기에 더 이상 재 사용/재활용 뷰의.귀하의 목록보기 항목의 재활용되고있다

때문에, 당신의 정확한 상태를 유지하기 위해 그들에 의존 할 수

객체를 각각의 체크 박스의 상태를 유지하기 위해 다음은 제대로이 작업을 수행해야한다 무엇 당신의 체크 박스. 따라서 각 목록 항목에 대한 올바른 체크 상태를 유지하기 위해 일종의 객체/배열이 필요합니다. 당신의 getView를 호출 할 때 상태 관리 객체

에서 읽기

그런 다음, 해당 객체/배열의 상태에 따라 선택/선택 해제에 체크 박스의 값을 설정해야합니다. 상태 관리 개체 당신은 제대로 문 관리 객체/배열이 체크 박스의 값을 설정할 수 있도록 각각의 체크 박스 OnChecked 청취자의 일종을 구현해야

에 쓰기

.

당신이 시도하고 ViewHolder의

ViewHolder은 아주 간단 사용해야합니다. 변환보기를 사용하지 않고 처음으로보기를 만들 때 "FindViewByID"를 호출하여 텍스트 상자 및 확인란에 대한 참조를 가져와야합니다. ViewHolder에 저장하면 ViewViewByID에 대한 추가 호출을 저장하는 ConvertView 객체를 사용할 때이를 직접 참조 할 수 있어야합니다. 연습하는 것이 훨씬 쉽습니다.

이 튜토리얼 않습니다 꽤 많이 당신이 필요 :

+0

더 자세히 설명해 주셔서 감사합니다. 그가 처음이기 때문에 대답을주는 archano –

0

http://windrealm.org/tutorials/android/listview-with-checkboxes-without-listactivity.php 내가 큰 목록을 처리 같은 문제가 있습니다. 나를 좋아하는 사람들을 위해 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; 
} 
}); 

당신은 당신의 자신의 방식으로 확인/체크되지 않은 상태를 유지해야합니다.

관련 문제