带单选button模式下的RadioButton的Android ListView和一个自定义的行布局

我有一个ListView ,这是在singleChoice模式 。 我所要做的就是向旁边显示一个RadioButton,当点击突出显示它被选中时,以及当点击一个不同的RadioButton时,一个回到未选中状态,新的状态被选中。 为什么这么难? 这不应该是这么复杂。 我已经花了几天的时间寻找一个适当的答案,我什么都没有find,所以我希望以清晰,简洁的方式问。

我的布局视图(R.layout.view_orders)的布局:

<?xml version="1.0" encoding="utf-8"?> <ListView android:choiceMode="singleChoice" android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@drawable/list_divider" android:dividerHeight="1px" android:focusable="false" android:focusableInTouchMode="false" android:cacheColorHint="#00000000"> </ListView> 

我的自定义行(R.layout.orders_row)

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:app="http://schemas.android.com/apk/res/com.xxx.xxxxxx" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="6dip"> <com.xxx.xxxxxx.VerticalLabelView app:text="SHORT" app:textColor="#666" app:textSize="14sp" android:id="@+id/state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" /> <TextView android:id="@+id/quantity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/state" android:layout_centerVertical="true" android:gravity="center" android:textSize="40sp" android:layout_margin="2dip" android:minWidth="30dip" android:textColor="#555" /> <RelativeLayout android:layout_toRightOf="@id/quantity" android:layout_centerVertical="true" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/instrument" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="20sp" android:textColor="#333" android:layout_marginLeft="2dip" android:layout_marginRight="2dip" /> <TextView android:id="@+id/deets" android:layout_below="@id/instrument" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="16sp" android:textColor="#888" android:layout_marginLeft="2dip" android:layout_marginRight="2dip" /> </RelativeLayout> <RadioButton android:id="@+id/selector" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" /> </RelativeLayout> 

我的onCreate()方法:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_orders); client = new Client(handler); ola = new OrdersAdapter(this, R.layout.orders_row, Orders); setListAdapter(ola); final RelativeLayout loading = (RelativeLayout) findViewById(R.id.loading); panel = (PositionsPanel) findViewById(R.id.panel); Utility.showProgressBar(loading); client.Connect("orders"); } 

现在一切工作如预期,你点击一个单选button,通过它的标签,我可以适当地从列表中select该项目,并操纵它如何我想要的。 但是,当第一个单选button被点击,最后一个将被选中。 再次点击相同的单选button,现在也被选中。 再次单击它,没有任何反应,最后一个和第一个都被选中。 现在我点击列表中的任何一个,就像预期的那样被选中。 单击所选单选button中的任何一个,什么都不发生,单选button保持选中状态。

我已经尝试在onCreate()中使用以下内容:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_orders); client = new Client(handler); ola = new OrdersAdapter(this, android.R.layout.simple_list_item_single_choice, Orders); setListAdapter(ola); final RelativeLayout loading = (RelativeLayout) findViewById(R.id.loading); panel = (PositionsPanel) findViewById(R.id.panel); Utility.showProgressBar(loading); client.Connect("orders"); } 

而且根本不显示单选button。 真棒

现在可能(读:很有可能),我只是密集的,不能解决这个问题,但我看到这个问题很多,没有真正的答案。 很多其他教程的参考或Commonsware人的书。 然而,现在的评论已经老了,他的存储库已经发生了很大的变化,这些都不再是正确的答案。

那么,有没有人有任何想法如何获得预期的function呢? 或者失败了,只是把我沿GMail应用程序的源代码。 🙂

Solutions Collecting From Web of "带单选button模式下的RadioButton的Android ListView和一个自定义的行布局"

请记住,在ListView行项目是RECYCLED。 这很可能解释了为什么一行中的行为正在影响另一行。 在马克的书中挖掘,你会发现这个报道。

如果您使用带有列表的适配器,则可以使用适配器上的getView()在创build/回收时为每行添加一个点击处理程序,并确保在创build和回收行项目时正确pipe理状态。

我的方法是将状态存储在我自己的数据结构中,然后在用户滚动ListView时使用getView()在UI中对其进行镜像。 可能有更好的解决scheme,但是这对我有用。

我testing了一个更简单的解决scheme:

在你的xml文件的RadioButton中添加这一行:

 <RadioButton ... android:onClick="onClickRadioButton" ... /> 

然后在使用ListView的活动类中,添加以下内容:

  private RadioButton listRadioButton = null; int listIndex = -1; public void onClickRadioButton(View v) { View vMain = ((View) v.getParent()); // getParent() must be added 'n' times, // where 'n' is the number of RadioButtons' nested parents // in your case is one. // uncheck previous checked button. if (listRadioButton != null) listRadioButton.setChecked(false); // assign to the variable the new one listRadioButton = (RadioButton) v; // find if the new one is checked or not, and set "listIndex" if (listRadioButton.isChecked) { listIndex = ((ViewGroup) vMain.getParent()).indexOfChild(vMain); } else { listRadioButton = null; listIndex = -1 } } 

有了这个简单的代码,只有一个RadioButton被选中。 如果您触摸已经被选中的那个,那么它将返回到未选中的模式。

“listIndex”正在跟踪选中的项目,如果没有则为-1。

如果你想保持一个被选中,那么onClickRadioButton中的代码应该是:

  public void onClickRadioButton(View v) { View vMain = ((View) v.getParent()); int newIntex = ((ViewGroup) vMain.getParent()).indexOfChild(vMain); if (listIndex == newIndex) return; if (listRadioButton != null) { listRadioButton.setChecked(false); } listRadioButton = (RadioButton) v; listIndex = newIndex; } 

我叫Gourab Singha。 我解决了这个问题。 我已经写了这个代码来解决它。 我希望这可以帮助大家。 谢谢。 我需要3个小时。

 public void add_option_to_list(View v){ LinearLayout ll = (LinearLayout)v.getParent(); LinearLayout ll_helper = null; LinearLayout ll2 = (LinearLayout)ll.getParent(); LinearLayout ll3 = (LinearLayout)ll2.getParent(); ListView ll4 = (ListView)ll3.getParent(); //RadioButton rb1= (RadioButton)ll.getChildAt(1); Toast.makeText(getApplicationContext(), ", "+ll4.getChildCount(), Toast.LENGTH_LONG).show(); //ll.findViewById(R.id.radio_option_button) for(int k=0;k<ll4.getChildCount();k++){ ll3 = (LinearLayout)ll4.getChildAt(k); ll2 = (LinearLayout)ll3.getChildAt(0); ll_helper = (LinearLayout)ll2.getChildAt(0); RadioButton rb1 = (RadioButton)ll_helper.getChildAt(1); if(rb1.isChecked()) rb1.setChecked(false); } RadioButton rb1 = (RadioButton)ll.getChildAt(1); rb1.setChecked(true); //Toast.makeText(getApplicationContext(), ""+((TextView)ll.getChildAt(4)).getText().toString(), Toast.LENGTH_LONG).show(); } 

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="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Category Name" android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone" /> <RadioButton android:id="@+id/radio_option_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="add_option_to_list" android:text="" /> <TextView android:id="@+id/option_name" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_marginLeft="3dp" android:layout_weight="5.35" android:text="Category Name" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/option_price" android:layout_width="76dp" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:gravity="right" android:text="$0.00" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/option_unit_price" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:gravity="right" android:text="$0.00" android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone" /> </LinearLayout> </LinearLayout> </LinearLayout> 

我刚刚有类似的问题。 这似乎与意见回收有关。 但是我到处都加了Log,注意到回收处理很好。 问题是RadioButtons处理。 我正在使用:

 if(answer == DBAdapter.YES){ rbYes.setChecked(true); rbNo.setChecked(false); } else if(answer == DBAdapter.NO){ rbYes.setChecked(false); rbNo.setChecked(true); } else{ rbYes.setChecked(false); rbNo.setChecked(false); } 

而正确的做法是:

 if(answer == DBAdapter.YES){ rbYes.setChecked(true); } else if(answer == DBAdapter.NO){ rbNo.setChecked(true); } else{ RadioGroup rg = (RadioGroup)(holder.answerView); rg.clearCheck(); } 

你可以做得更简单,按照这个。 在MarshMallow中试过了

1)有一个CheckedTextView

 <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:padding="10dp" android:textAppearance="?android:attr/textAppearanceMedium"> 

  • ListChoiceIndicatorSingle将显示RadioButton

  • ListChoiceIndicatorMultiple将显示CheckBox

不要忘记在你的ListView放置choiceMode:Single

在适配器内部

  viewHolder.radioBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.e("called", "called"); if(position != mSelectedPosition && mSelectedRB != null){ mSelectedRB.setChecked(false); } mSelectedPosition = position; mSelectedRB = (RadioButton)v; } }); viewHolder.radioBtn.setText(mList[position]); if(mSelectedPosition != position){ viewHolder.radioBtn.setChecked(false); }else{ viewHolder.radioBtn.setChecked(true); if(mSelectedRB != null && viewHolder.radioBtn != mSelectedRB){ mSelectedRB = viewHolder.radioBtn; } } 

添加样式到单选button

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/tick" android:state_checked="true"/> <item android:drawable="@drawable/untick" android:state_checked="false"/> </selector> 

并在xml中使用单选button样式

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <RadioButton android:id="@+id/radioBtn" android:layout_width="match_parent" android:layout_height="50dp" android:button="@null" android:checked="true" android:drawablePadding="30dp" android:drawableRight="@drawable/checkmark" android:text="first" /> </RelativeLayout> 

在你的适配器上:

 public void setChecked(View v, int position) { ViewGroup parent = ((ViewGroup) v.getParent()); // linear layout for (int x = 0; x < parent.getChildCount() ; x++) { View cv = parent.getChildAt(x); ((RadioButton)cv.findViewById(R.id.checkbox)).setChecked(false); // your checkbox/radiobtt id } RadioButton radio = (RadioButton)v.findViewById(R.id.checkbox); radio.setChecked(true); } 

在你的活动/片段上:

  listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ((ModelNameAdapter)adapter).setChecked(view, position); } });