2015-02-05 40 views
0

我是一個新的android學習者。我正在處理一個項目,該項目需要具有50個或更多行的自定義列表視圖。每一行都包含一個表示行號的文本視圖和一個有四個單選按鈕的無線電組。問題是當我檢查任何單選按鈕然後向下滾動時,我看到許多單選按鈕被自動檢查。當向上滾動時,我看到一些隨機單選按鈕被檢查!大型自定義listview與廣播組

我猜測它的發生是因爲getView()方法的回收問題here。坦率地說,作爲一個新手,我無法理解整個講座。

我也看過this的線程。這與我的問題類似,但無法清楚地理解並解決我的問題。

那麼我該如何解決這個問題,並從無線電組中獲取數據。由於我是一名新學員,請您輕鬆解釋。

謝謝!

[image]Here is my list view with a radio button checked of 1st row.

[image]When I scroll down I see 15th row is auto checked!

[image]When scroll up again I see radio group of the 1st row is in initial state again!

這裏是我的代碼:

MainActivity:

public class MainActivity extends Activity { 

    /* ListView */ 
    ListView lv; 

    /* Data source for numbering */ 
    String[] numbering = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50"}; 

    /* Custom adapter */ 
    CustomListAdapter adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     /* initialization */ 
     adapter = new CustomListAdapter(this, R.layout.list_row_item, numbering); 
     lv = (ListView) findViewById(R.id.lvQuestion); 

     /* show list view */ 
     lv.setAdapter(adapter); 
    } 
} 

list_row_item.xml:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal" > 

    <TextView 
     android:id="@+id/tvNumbering" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_weight="4" 
     android:textAppearance="?android:attr/textAppearanceMedium" /> 

    <RadioGroup 
     android:id="@+id/radioGroup" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_weight="1" 
     android:orientation="horizontal" > 

     <RadioButton 
      android:id="@+id/answer0" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:button="@drawable/radio_button" 
      android:checked="true" /> 

     <RadioButton 
      android:id="@+id/answer1" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:button="@drawable/radio_button" /> 

     <RadioButton 
      android:id="@+id/answer2" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:button="@drawable/radio_button" /> 

     <RadioButton 
      android:id="@+id/answer3" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:button="@drawable/radio_button" /> 
    </RadioGroup> 

</LinearLayout> 

自定義列表適配器:

public class CustomListAdapter extends ArrayAdapter<String> { 
    Context context; 
    int layoutResourceId; 
    String[] numbers; 

    public CustomListAdapter(Context context, int layoutResourceId, 
      String[] numbers) { 
     super(context, layoutResourceId, numbers); 
     this.context = context; 
     this.layoutResourceId = layoutResourceId; 
     this.numbers = numbers; 
    } 

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

     ViewHolder holder = null; 

     if (convertView == null) { 
      /* Add layout inflater */ 
      LayoutInflater infletar = ((Activity) context).getLayoutInflater(); 
      convertView = infletar.inflate(layoutResourceId, null); 

      /* initialization */ 
      holder = new ViewHolder(); 
      holder.tvNumbering = (TextView) convertView 
        .findViewById(R.id.tvNumbering); 
      holder.rg = (RadioGroup) convertView.findViewById(R.id.radioGroup); 

      /* set tag */ 
      convertView.setTag(holder); 

     } else { 
      holder = (ViewHolder) convertView.getTag(); 
     } 

     holder.tvNumbering.setText(numbers[position]); 

     return convertView; 
    } 

    static class ViewHolder { 
     TextView tvNumbering; 
     RadioGroup rg; 
    } 
} 

回答

2

getView是叫你需要使用的初始化所持的觀點在holder相關數據爲position

您目前正在爲該行TextView執行此操作。

holder.tvNumbering.setText(numbers[position]); 

您需要對RadioGroup進行相同的操作。

目前,您的CustomListAdapter被定義爲延伸ArrayAdapterStrings。因此,您過去到適配器的項目列表是一個字符串數組,適配器保存的每個項目的唯一信息是數字的值每個項目的字符串。

在你的情況,你真正想要的是每個項目有一個數字值和檢查單選按鈕值。

而不是提供一個字符串列表的適配器,你應該提供一個你自己的自定義類的封裝這些變量的列表。

public class MyItem { 
    public String number; 
    public int checkedRadioButtonId; 
} 

你需要讓你的適配器處理這個類。

public class CustomListAdapter extends ArrayAdapter<MyItem> { 
    Context context; 
    int layoutResourceId; 
    MyItem[] items; 

    public CustomListAdapter(Context context, int layoutResourceId, 
          MyItem[] items) { 
     super(context, layoutResourceId, items); 
     this.context = context; 
     this.layoutResourceId = layoutResourceId; 
     this.items = items; 
    } 

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

     View row = convertView; 
     ViewHolder holder = null; 

     if (row == null) { 
      LayoutInflater inflater = ((Activity) context).getLayoutInflater(); 
      row = inflater.inflate(layoutResourceId, null); 
      holder = new ViewHolder(row); 
      row.setTag(holder); 
      // Set a listener to update the data in your items list when the RadioGroup is clicked 
      holder.rowRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 
       public void onCheckedChanged(RadioGroup group, int checkedId) { 

        // **get which item this RadioGroup refers to** 
        Integer pos = (Integer) group.getTag(); 
        Log.d("onCheckedChanged", "pos = " + pos + ", checkedId = " + checkedId); 
        items[pos].checkedRadioButtonId = checkedId; 

       } 
      }); 
     } else { 
      holder = (ViewHolder) row.getTag(); 
     } 

     // **Tag each RadioGroup so we know what item it refers to** 
     holder.rowRadioGroup.setTag(position); 

     // setup both views from the values stored in your items list 
     holder.rowTextView.setText(items[position].number); 
     holder.rowRadioGroup.check(items[position].checkedRadioButtonId); 



     return row; 
    } 

    static class ViewHolder { 
     TextView rowTextView = null; 
     RadioGroup rowRadioGroup = null; 

     ViewHolder(View row) { 
      this.rowTextView = (TextView) row.findViewById(R.id.tvNumbering); 
      this.rowRadioGroup = (RadioGroup) row.findViewById(R.id.radioGroup); 
     } 
    } 
} 

你MainActivity將成爲像

public class MainActivity extends Activity { 

    /* ListView */ 
    ListView lv; 

    /* Data source for the ListView */ 
    MyItem[] myItems = new MyItems[50]; 

    /* Custom adapter */ 
    CustomListAdapter adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     // Create the data for the list 
     for (int i = 0; i < myItems.length; i++) { 
      final MyItem item = new MyItem(); 
      // your numbering goes from 1 to 50, but the array indexes go from 0 to 49 
      item.number = String.valueOf(i + 1); 
      // set all items to answer0 by default 
      item.checkedRadioButtonId = R.id.answer0 

      // put the new item in the array 
      myItems[i] = item; 
     } 

     /* initialization */ 
     adapter = new CustomListAdapter(this, R.layout.list_row_item, myItems); 
     lv = (ListView) findViewById(R.id.lvQuestion); 

     /* show list view */ 
     lv.setAdapter(adapter); 
    } 
} 
+0

謝謝!但是我怎麼能爲RadioGroup做到這一點?在TextView中,我傳遞了一個信息,但RadioGroup沒有這樣的事情! –

+0

當然有一個RadioGroup的信息!您可以獲取使用getCheckedRadioButtonId()檢查哪個按鈕的信息。 –

+0

大部分錯誤都消失了,除非現在如果我檢查一個單選按鈕並向下滾動(使單選按鈕離開屏幕),然後向上滾動,看到選中的單選按鈕已經進入其初始狀態!這是爲什麼發生? –