2012-09-28 36 views
8

Tôi có một ListView trong đó sử dụng một bộ chuyển đổi tùy chỉnh như:listview với adapter tùy chỉnh chứa CheckBoxesfunction

private class CBAdapter extends BaseAdapter implements OnCheckedChangeListener{ 

    Context context; 
    public String[] englishNames; 
    LayoutInflater inflater; 
    CheckBox[] checkBoxArray; 
    LinearLayout[] viewArray; 
    private boolean[] checked; 

    public CBAdapter(Context con, String[] engNames){ 
     context=con; 
     englishNames=engNames; 
     inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     checked= new boolean[englishNames.length]; 
     for(int i=0; i<checked.length; i++){ 
      checked[i]=false; 
      //Toast.makeText(con, checked.toString(),Toast.LENGTH_SHORT).show(); 
     } 
     checkBoxArray = new CheckBox[checked.length]; 
     viewArray = new LinearLayout[checked.length]; 
    } 

    public int getCount() { 
     return englishNames.length; 
    } 

    public Object getItem(int position) { 
     // TODO Auto-generated method stub 
     return null; 
    } 

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

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

     if(viewArray[position] == null){ 

      viewArray[position]=(LinearLayout)inflater.inflate(R.layout.record_view_start,null); 

      TextView tv=(TextView)viewArray[position].findViewById(R.id.engName); 
      tv.setText(englishNames[position]); 

      checkBoxArray[position]=(CheckBox)viewArray[position].findViewById(R.id.checkBox1); 
     } 

     checkBoxArray[position].setChecked(checked[position]); 
     checkBoxArray[position].setOnCheckedChangeListener(this); 
     return viewArray[position]; 
    } 


    public void checkAll(boolean areChecked){ 
     for(int i=0; i<checked.length; i++){ 
      checked[i]=areChecked; 
      if(checkBoxArray[i] != null) 
       checkBoxArray[i].setChecked(areChecked); 
     } 
     notifyDataSetChanged(); 
    } 

    public void onCheckedChanged(CompoundButton cb, boolean isChecked) { 
     for(int i=0; i<checked.length; i++){ 
      if(cb == checkBoxArray[i]) 
       checked[i]=isChecked; 
     } 




    } 
    public boolean itemIsChecked(int i){ 
     return checked[i]; 
    } 

} 

Sơ đồ bố trí khá đơn giản vì vậy tôi sẽ không gửi cho họ trừ khi có ai nghĩ họ có liên quan.

Vấn đề là một số hộp kiểm tra không phản hồi. Nó có vẻ là những người có thể nhìn thấy khi bố trí được hiển thị đầu tiên. Bất kỳ thứ gì bạn phải cuộn xuống để hoạt động như mong đợi.

Bất kỳ con trỏ nào được đánh giá cao.

Trả lời

15

Mã của bạn từ câu trả lời hoạt động nhưng không hiệu quả (bạn có thể thấy điều này, chỉ cần cuộn ListView và kiểm tra xem Logcat để xem bộ thu gom rác đang hoạt động). Một cải tiến getView phương pháp mà sẽ tái chế lần xem là một trong những dưới đây:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    LinearLayout view = (LinearLayout) convertView; 
    if (view == null) { 
      view = (LinearLayout) inflater.inflate(R.layout.record_view_start, parent, false); 
    } 
    TextView tv = (TextView) view.findViewById(R.id.engName); 
    tv.setText(getItem(position)); 
    CheckBox cBox = (CheckBox) view.findViewById(R.id.checkBox1); 
    cBox.setTag(Integer.valueOf(position)); // set the tag so we can identify the correct row in the listener 
    cBox.setChecked(mChecked[position]); // set the status as we stored it   
    cBox.setOnCheckedChangeListener(mListener); // set the listener  
    return view; 
} 

OnCheckedChangeListener mListener = new OnCheckedChangeListener() { 

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
     mChecked[(Integer)buttonView.getTag()] = isChecked; // get the tag so we know the row and store the status 
    } 
}; 

Về mã của bạn từ câu hỏi của bạn, lúc đầu tôi nghĩ đó là sai vì cách bạn thiết lập các hàng nhưng tôi không thấy lý do tại sao bộ điều hợp sẽ có hành vi đó khi bạn tách chế độ xem hàng khỏi danh sách. Ngoài ra, tôi thậm chí đã kiểm tra mã và nó hoạt động khá tốt liên quan đến CheckBoxes (nhưng với xử lý bộ nhớ rất kém). Có lẽ bạn đang làm một cái gì đó khác mà làm cho bộ chuyển đổi không hoạt động?

+0

Làm thế nào để bạn làm điều này cho một hộp kiểm EcxpandableListView với con? – RicNjesh

+0

@RicNjesh Bạn sẽ muốn sử dụng phương thức 'getChildView()' được gọi bất cứ khi nào một hàng con là bắt buộc. – Luksprog

+0

những gì được kiểm tra trong trường hợp này và làm thế nào để khai báo nó? –

1

Hãy để tôi nói rằng bạn đã bỏ đi một trong những lợi ích chính của việc sử dụng bộ điều hợp: Chế độ xem có thể sử dụng lại. Giữ một tham chiếu khó khăn cho mỗi View tạo ra một nguy cơ cao đánh trần bộ nhớ. Bạn nên sử dụng lại convertView khi không rỗng và tạo chế độ xem của bạn khi convertView không có giá trị. Có nhiều hướng dẫn xung quanh cho bạn thấy cách thực hiện điều này.

Chế độ xem được sử dụng trong bộ điều hợp thường có OnClickListener được đính kèm với phụ huynh View để bạn có thể đặt OnItemClickListener trên ListView. Điều này sẽ thay thế mọi người nghe cảm ứng trên các chế độ xem riêng lẻ. Thử đặt android:clickable="true" trên CheckBox bằng XML.

+0

Cảm ơn những người đứng đầu về convertView. Tôi đã tự hỏi tham số này là gì. Tôi nghĩ rằng tôi có thể có một giải pháp cho vấn đề ban đầu nhưng tôi vẫn đang thử nghiệm. Tôi sẽ đăng lại sớm thôi. – s1ni5t3r

0

Đây có thể không phải là giải pháp thanh lịch hoặc hiệu quả nhất nhưng nó hoạt động cho trường hợp của tôi. Đối với một số lý do cố gắng sử dụng lại các khung nhìn hoặc từ một loạt các khung nhìn hoặc sử dụng convertView làm cho mọi thứ trở nên lung lay và các CheckBox không trả lời.

Điều duy nhất hoạt động là tạo một ViewView everytime() mới được gọi.

public View getView(final int position, View convertView, ViewGroup parent) { 
     LinearLayout view; 
     view=(LinearLayout)inflater.inflate(R.layout.record_view_start,null); 


     TextView tv=(TextView)view.findViewById(R.id.engName); 
     tv.setText(englishNames[position]); 

     CheckBox cBox=(CheckBox)view.findViewById(R.id.checkBox1); 
     cBox.setChecked(checked[position]); 
     cBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){ 

      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       checked[position]=isChecked; 
      } 
     }); 
     return view; 
    } 

Tìm giải pháp này cũng bị cản trở bởi thực tế là tôi đã gọi một onCheckedChangedListener xác định riêng, mà sau đó được xác định mà CheckBox bởi id, hơn là có một người biết lắng nghe mới cho mỗi CheckBox.

Tôi chưa đánh dấu câu trả lời này là câu trả lời đúng vì tôi hy vọng những người khác có thể có một số đầu vào liên quan đến việc xây dựng lại lượt xem lãng phí mỗi lần lãng phí.

+1

Có rất nhiều câu hỏi về stackoverflow liên quan đến một 'ListView' với một bộ điều hợp tùy chỉnh sử dụng một hàng với một' CheckBox', bạn nên xem xét nhiều hơn ở những giải pháp đó. Mã của bạn hoạt động nhưng nó không hiệu quả, mỗi khi 'ListView' được cuộn, bạn sẽ tạo ra các khung nhìn mới. – Luksprog

+0

Tôi hoàn toàn đồng ý với Luksprog nhưng sau nhiều lần thử việc này, sử dụng các giải pháp làm việc cho người khác, tôi không thể tìm ra giải pháp nào khác ngoài việc này. Hy vọng rằng bộ sưu tập rác sẽ theo kịp với những quan điểm lãng phí và không gây ra một vấn đề bộ nhớ và điện thoại cũ sẽ không bị chậm quá nhiều. Trong ứng dụng của tôi, trong hầu hết các trường hợp, chế độ xem danh sách sẽ không có quá nhiều mục để cuộn phải được giữ ở mức tối thiểu. – s1ni5t3r

+1

Lý do tại sao mã của bạn hoạt động ngay bây giờ là vì bạn thổi phồng hàng mỗi lần và bạn tránh 'OnCheckedChangeListener' làm rối loạn trạng thái' CheckBox'. Bạn không bao giờ nên bỏ qua chế độ xem tái chế trong phương thức 'getView'. Đây là phương thức 'getView' được cải thiện của bạn nên làm những gì bạn muốn nhưng cũng sẽ tái chế các khung nhìn. https://gist.github.com/3917222 – Luksprog

Các vấn đề liên quan