在SingleChoice模式下使用RadioButton的Android ListView和自定义行布局

zkw*_*ntz 26 android listview listviewitem radio-button

我有一个ListView,它处于singleChoice模式.我想要的只是在侧面显示一个RadioButton,当点击高亮显示它被选中时,当点击另一个时,一个返回到未选择状态,新的一个被选中.为什么这么难?这不应该是这么复杂.我已经花了DAYS寻找合适的答案而且我什么也没找到,所以我希望以清晰简洁的方式提出要求.

我对listview的布局(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>
Run Code Online (Sandbox Code Playgroud)

我的自定义行(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>
Run Code Online (Sandbox Code Playgroud)

我的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");
}
Run Code Online (Sandbox Code Playgroud)

现在所有基础工作都按预期工作,你点击一个单选按钮,通过它的标签,我可以从列表中适当地选择该项目,并按照我想要的方式操作它.但是,单击第一个单选按钮时,将选择最后一个单选按钮.再次单击相同的单选按钮,现在也可以选中它.再次单击它,没有任何反应,选择最后一个和第一个.现在我点击列表中的任何其他一个,它会像预期的那样被选中.单击所选单选按钮中的任何一个,没有任何反应,单选按​​钮保持选中状态.

我尝试在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");
}
Run Code Online (Sandbox Code Playgroud)

并且根本没有显示任何单选按钮.真棒.

现在也许(阅读:最有可能),我只是密集而无法解决这个问题,但我已经看到这个问题问了很多而没有真正的答案.很多参考其他教程或Commonsware的书.但是,这些评论现在已经过时了,而且他的存储库已经发生了很大变化,这些评论不再是正确答案.

那么,有没有人知道如何从中获得预期的功能?或者失败了,请告诉我GMail应用程序的源代码.:)

Oll*_*e C 8

请记住,ListView行项目是RECYCLED.这很可能解释为什么一行上的行为会影响另一行.在马克的书中挖掘,你会发现它的覆盖范围.

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

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


小智 7

简单方案:

在xml文件的RadioButton布局中添加以下行:

<RadioButton 
   ...
   android:onClick="onClickRadioButton"
   ...
/>
Run Code Online (Sandbox Code Playgroud)

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

   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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

使用这个简单的代码,只检查一个RadioButton.如果触摸已经选中的那个,则返回未选中模式.

"listIndex"跟踪已检查的项目,如果没有,则为-1.

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

   public void onClickRadioButton(View v) {
        View vMain = ((View) v.getParent());
        int newIndex = ((ViewGroup) vMain.getParent()).indexOfChild(vMain);
        if (listIndex == newIndex) return;

        if (listRadioButton != null) {
                listRadioButton.setChecked(false);
        }
        listRadioButton = (RadioButton) v;
        listIndex = newIndex; 
    }
Run Code Online (Sandbox Code Playgroud)

  • 嗨,这在列表适合 1 页时有效,但是当列表比一页长时,listIndex 会混乱,因为它从第一个可见列表项而不是从列表的实际开始开始计数。这怎么解决? (2认同)