2011-08-15 30 views
7

Tôi đang tạo ứng dụng Android đầu tiên của mình và tôi đang gặp sự cố mà tôi không thể tìm thấy câu trả lời ở bất cứ đâu trên Google.Android Cách biết hộp kiểm nào được chọn

Tôi muốn danh sách các mục có hộp kiểm. Tôi muốn cả chính mục đó và hộp kiểm có thể nhấp được.

public class MyItem extends ListActivity { 
     private ArrayList<MyItem> items; 
     public void onCreate(Bundle savedInstanceState) { 
      /* code which creates instances of MyItem and inserts them on the *list* variable */ 
     MyArrayAdapter adapter = new MyArrayAdapter(this, R.layout.my_item, list); 

     setListAdapater(adapter); 
     setContentView(R.layout.items_list); 
    } 
     public onListItemClick(ListView l, View v, int position, long id){ 
      //handles the click on an item 
     } 

    public class MyArrayAdapter extends ArrayAdapter<MyItem>{ 
     private MyItem item; 
     public MyArrayAdapter(Context context, int resourceId, ArrayList<MyItem> list){ 
      //code for the constructor 
     } 
     public getView(int position, View convertView, ViewGroup parent){ 
      convertView = inflater.inflate(resourceId, null); 


      this.item = list.get(position); 
      if (this.item == null) { 
       return convertView; 
      } 
      else{ 
       if (resourceId == R.layout.my_item) { 
        final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox); 

        if(cb != null){ 
         //initially 
         if(chosen) 
          cb.setChecked(true); 
         else 
          cb.setChecked(false); 
         //set listener 
         cb.setOnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View arg0) { 
           if(cb.isChecked()) 
            chosen = true; 
           else 
            chosen = false; 
          } 
         }); 
        } 
       } 
      return convertView; 
     } 
    }  
} 

Đừng lo lắng về biến đã chọn. Tôi viết rằng chỉ đơn giản là mã. Nó thực sự tương ứng với một giá trị trong cơ sở dữ liệu. Việc nhấp vào một mục hoạt động tốt. Tuy nhiên khi tôi bấm vào một ô trống những gì xảy ra là thế này:

  • hộp kiểm trong đó tôi nhấp xuất hiện chọn (đây là công việc của giao diện người dùng của Android)
  • hộp kiểm mà trong nội bộ sẽ được kiểm tra là người cuối cùng trên màn hình bất cứ điều gì, nghĩa là nếu màn hình của tôi hiển thị 8 mục và tôi nhấp vào một trong số chúng (không quan trọng cái nào), thì dấu kiểm xuất hiện trong hộp kiểm chính xác nhưng nội bộ, mục thứ 8 là mục được chọn.

Tôi sẽ đánh giá cao bất kỳ trợ giúp nào bạn có thể cung cấp cho tôi. Cảm ơn trước.

Trả lời

6

Thực ra, phần sao lưu thực hiện chosen là khóa. Android thực hiện một số tối ưu hóa với chế độ xem danh sách để cho phép bạn sử dụng lại chế độ xem mục danh sách để tránh tạo đối tượng thừa và thu gom rác (thường sẽ dẫn đến việc cuộn giật). Như vậy, bạn phải chắc chắn rằng bất cứ khi nào có liên quan, bạn biết chính xác mục danh sách nào bạn đang làm việc.

Giả sử bạn có 100 mục danh sách. Màn hình của bạn có thể sẽ không thể hiển thị tất cả chúng. Bạn chỉ có thể hiển thị mười mục cùng một lúc. Vì vậy, 10 lượt xem (xem phân cấp thực sự) được tạo để hiển thị các mục hiển thị đó. Khi bạn cuộn xuống mười mục tiếp theo, thay vì tạo 10 lượt xem mới (với tổng số là 20), danh sách chỉ có thể tạo thêm một lần nữa (để bao gồm trường hợp một nửa của một mục đang hiển thị ở trên cùng và một nửa của một hiển thị ở cuối màn hình cho tổng số 11 mục hiển thị trên màn hình) và phần còn lại của các mục sẽ sử dụng lại các chế độ xem được tạo trước đó.

Vì vậy, một bảng khái niệm đại diện cho màn hình đầu tiên có thể trông như thế này:

 
Item  View 
------- -------- 
Item 1 View 1 
Item 2 View 2 
Item 3 View 3 
Item 4 View 4 
Item 5 View 5 
Item 6 View 6 
Item 7 View 7 
Item 8 View 8 
Item 9 View 9 
Item 10 View 10 

Và đối với sau khi di chuyển xuống mười bài, nó có thể nhìn một chút như thế này (có thể là không chính xác, nhưng điều này giúp bạn ý tưởng):

 
Item  View 
------- -------- 
Item 11 View 1 
Item 12 View 2 
Item 13 View 3 
Item 14 View 4 
Item 15 View 5 
Item 16 View 6 
Item 17 View 7 
Item 18 View 8 
Item 19 View 9 
Item 20 View 10 

Vì vậy, những gì bạn có thể thu thập từ đây là một lần xem có thể đại diện cho các mục khác nhau khi bạn di chuyển. Điều này có nghĩa là trình xử lý sự kiện của bạn phải năng động hơn một chút trong cách họ tìm thấy mục mà họ liên quan đến.

Tất cả điều này là cung cấp cho bạn một chút nền để bạn có thể thay đổi cách bạn đang triển khai phương pháp getView của mình. Đây là vấn đề thực tế của bạn: biến số item nằm trong phạm vi Adapter của bạn. Rất tiếc, tôi đoán rằng mã của bạn mà bạn chưa đăng ở đây mà bạn đã thay thế bằng chosen sử dụng item. Bạn đặt item bất cứ khi nào chế độ xem mục được tạo. Điều này có nghĩa là sau 8 lượt xem đầu tiên được tạo, item được đặt thành mục thứ 8 trong danh sách của bạn. Bất cứ khi nào bạn nhấp vào hộp kiểm, bạn đang sử dụng item là mục thứ 8 chứ không phải mục tương ứng với chế độ xem danh sách mà bạn đã nhấp vào.

Dưới đây là cấu trúc cho getView mà tôi khuyên bạn nên:

public getView(int position, View convertView, ViewGroup parent){ 
     View view = convertView; 
     if (view == null) { 
      view = inflater.inflate(R.layout.my_item, null); 
     } 

     final MyItem item = list.get(position); 
     final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox); 
     // This stores a reference to the actual item in the checkbox 
     cb.setTag(item); 

     if(item.chosen) 
      cb.setChecked(true); 
     else 
      cb.setChecked(false); 

     //set listener 
     cb.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       // This gets the correct item to work with. 
       final MyItem clickedItem = (MyItem) view.getTag(); 
       if(cb.isChecked()) 
        clickedItem.chosen = true; 
       else 
        clickedItem.chosen = false; 
      } 
     }); 

     return view; 
    } 
} 

Lưu ý rằng tôi đã gạt bỏ lớp cấp item biến.

+0

Nó làm việc như một nét duyên dáng ngoại trừ một chi tiết. SetTag/getTag phải được thực hiện không để xem nhưng để hộp kiểm. Cảm ơn bạn, cảm ơn bạn rất nhiều: D –

+1

Đã cập nhật để khắc phục lỗi mà bạn đã chỉ ra, chỉ trong trường hợp bất kỳ ai khác xảy ra trên mã này. – kabuko

0

Bạn nên lưu giá trị được kiểm tra trong đối tượng MyItem của bạn và đặt rõ ràng được chọn vào hộp kiểm trong phương thức getView của bộ điều hợp của bạn. Sử dụng onCheckedChangedListener.

+0

Tôi làm điều đó. Tôi đang sử dụng OnClickListener vì tôi đã thử với OnCheckedChangeListener nhưng nó không hoạt động và vì vậy tôi đã thử onClick. Kết quả là giống nhau. Vấn đề của tôi không phải là lưu các thay đổi (nó lưu thay đổi vào mục thứ 8 trong danh sách). Vấn đề của tôi là nó nói rằng tôi đang nhấp vào ngày 8 khi tôi thực sự nhấp vào ngày 1 hoặc bất cứ điều gì. –

0

Nếu tôi làm theo lời giải thích của bạn, có vẻ như bạn có một danh sách và mỗi hàng trong danh sách có một Hộp kiểm và một TextView. Trong ứng dụng của tôi, tôi có một cái gì đó tương tự và thay vì cố gắng để làm cho cả Checkbox và TextView có thể nhấp và phản ứng với điều đó tôi sử dụng onItemclick của ListView. Khi bạn bắt người dùng nhấn một mục trong danh sách, sau đó trong mã bạn có thể kiểm tra hoặc bỏ chọn hộp kiểm. Nó cung cấp cho ấn tượng trực quan rằng người dùng có thể kiểm tra hộp, nhưng là siêu dễ dàng để thực hiện.

+0

Tôi không hiểu câu trả lời của bạn nhưng câu trả lời từ @kabuko đã giải quyết được vấn đề. Thanks anyway :) –

2

Hãy thử điều này

public getView(int position, View convertView, ViewGroup parent){ 
    View view = convertView; 
    if (view == null) { 
     view = inflater.inflate(R.layout.my_item, null); 
    } 

    final MyItem item = list.get(position); 
    // This stores a reference to the actual item in the view 
    view.setTag(item); 

    final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox); 

    //set listener 
    cb.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      // This gets the correct item to work with. 
      final MyItem clickedItem = (MyItem) view.getTag(); 
      if(cb.isChecked()) 
       clickedItem.chosen = true; 
      else 
       clickedItem.chosen = false; 
     } 
    }); 


    cb.setChecked(item.chosen); 
    return view; 
} 
+0

+1 giải pháp tuyệt vời và đơn giản – Simmant

+0

Tại sao không clickItem.chosen = cb.isChecked()? – cyroxis

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