2011-08-15 33 views
7

我正在製作我的第一個Android應用程序,但我遇到了一個問題,在Google上我無法找到答案。Android如何知道選中了哪個複選框

我想要一個帶有複選框的項目列表。我希望項目本身和複選框都可以點擊。

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

不要擔心所選變量。我寫了這個簡單的代碼。它實際上對應於數據庫中的值。點擊一個項目工作得很好。然而,當我點擊複選框會發生什麼情況是這樣的:

  • 在我點擊出現的選擇(這是Android的UI工作)
  • 在內部被選中的複選框是最後一個上的複選框屏幕無論是哪一個,也就是說,如果我的屏幕顯示了8個項目,並且我點擊了其中一個項目(哪個項目無關緊要),那麼這個支票就出現在正確的複選框中,但是在內部,第8個項目是被檢查的項目。

我希望你能給我提供任何幫助。提前致謝。

回答

6

實際上,支持chosen的實施是關鍵。 Android使用列表視圖做了一些優化,使您可以重用列表項視圖以避免過多的對象創建和垃圾收集(這通常會導致滾動)。因此,您必須確保每當相關時,您都確切知道您正在使用哪個列表項。

假設您有100個列表項目。您的屏幕可能無法顯示全部。您一次只能顯示十個項目。因此,創建了10個視圖(真正的視圖層次結構)來顯示這些可見項目。當您向下滾動到接下來的10個項目時,而不是創建10個新視圖(總共20個),該列表可能只會再創建一個(以涵蓋一個項目的一半顯示在頂部和一個半部的情況在屏幕底部顯示總共11個可見的項目),剩下的項目重用之前創建的視圖。

所以代表第一屏的概念表可能是這樣的:

 
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 

而對於向下滾動十個項目之後,它可能看起來有點像這樣(可能不完全,但是這可以讓你的想法):

 
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 

那麼你可以從這個收集是一個給定的視圖可以代表不同的項目,如你周圍滾動。這意味着您的事件處理程序必須在查找與其相關的項目時更具動態性。

所有這些都是爲了給你一些背景知識,以便你可以改變你如何實現你的方法getView。以下是您的實際問題:變量item位於您的Adapter的範圍內。不幸的是,我猜你的代碼,你沒有在這裏發佈,你已經用chosen取代使用item。每當創建一個項目視圖時,您就設置item。這意味着在創建前8個視圖後,item將設置爲列表中的第8個項目。每當你點擊一個複選框時,你正在使用item這是第8個項目,而不是與你點擊的列表項目視圖對應的項目。

下面是getView,我會推薦結構:

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

請注意,我已經戒掉了類級別item變量。

+0

它的工作就像一個魅力除了一個細節。 setTag/getTag必須完成而不是視圖,而是複選框。謝謝,非常感謝:D –

+1

已更新,以解決您指出的錯誤,以防萬一其他人發生此代碼。 – kabuko

0

您應該在您的MyItem對象中保存isChecked值,並在您的適配器的getView方法中將顯式設置選中複選框。使用onCheckedChangedListener。

+0

我這樣做。我使用的是OnClickListener,因爲我嘗試使用OnCheckedChangeListener,但它不起作用,所以我嘗試了onClick。結果是一樣的。我的問題是不保存更改(它將更改保存到列表中的第8項)。我的問題是,它說我點擊第8次,當我實際上點擊第1或什麼。 –

0

如果我按照你的解釋,它聽起來像你有一個列表,列表中的每一行都有一個複選框和一個TextView。在我的應用程序中,我有類似的東西,而不是試圖使複選框和TextView都可點擊,並對我使用ListView的onItemclick作出反應。當您捕獲用戶按下列表中的項目時,則可以在代碼中選中或取消選中複選框。它給人以直觀的印象,即用戶能夠檢查盒子,但卻非常容易實現。

+0

我不太明白你的答案,但@kabuko的人解決了這個問題。無論如何感謝:) –

2

試試這個

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偉大和簡單的解決方案 – Simmant

+0

爲什麼不clickedItem.chosen = cb.isChecked()? – cyroxis

相關問題