web-dev-qa-db-ja.com

Android単一選択モードのラジオボタンとカスタム行レイアウトのリストビュー

ListViewがあり、これはsingleChoiceモードです。私が望むのは、RadioButtonを横に表示することです。クリックすると強調表示され、別のボタンをクリックすると非選択に戻り、新しいボタンが選択されます。なぜこんなに難しいのですか?これはそれほど複雑ではありません。 [〜#〜] days [〜#〜]これに適切な答えを探しましたが、何も見つかりませんでしたので、明確かつ簡潔な方法で願っています。

リストビューの私のレイアウト(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");
}

基になるすべてのものが期待どおりに動作するようになったので、ラジオボタンをクリックし、そのタグを使用してリストからそのアイテムを適切に選択し、必要に応じて操作できます。ただし、最初のラジオボタンをクリックすると、最後のラジオボタンが選択されます。同じラジオボタンをもう一度クリックすると、そのボタンも選択されます。もう一度クリックしても何も起こりません。最後と最初の両方が選択されます。リスト上の他のいずれかをクリックすると、期待どおりに選択されます。選択したラジオボタンのいずれかをクリックしても何も起こりません。ラジオボタンは選択されたままです。

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

ラジオボタンはまったく表示されません。 [〜#〜] awesome [〜#〜]

今、多分(読んで:ほとんどの場合)、私はちょうど密で、これを理解することはできませんが、私はこの質問が本当の答えなしでたくさん尋ねられるのを見ました。他のチュートリアルやCommonswareの男の本への多くの参照。ただし、コメントは現在古く、彼のリポジトリは大きく変更されているため、それらはもはや正解ではありません。

だから、誰もこれから期待される機能を引き出す方法を知っていますか?または、失敗した場合は、GMailアプリのソースコードを渡してください。 :)

26
zkwentz

ListViewの行項目はリサイクルされていることに注意してください。これは、ある行のアクションが別の行に影響を与える理由を説明する可能性があります。マークの本を掘り下げてみてください。

リストでアダプターを使用している場合は、アダプターでgetView()を使用して、作成/リサイクルされる各行にクリックハンドラーを追加し、行項目が作成およびリサイクルされるときに状態が正しく管理されていることを確認できます。

私のアプローチは、独自のデータ構造に状態を保存し、ユーザーがListViewを上下にスクロールするときにgetView()を使用してUIにそれをミラーリングすることです。より良い解決策があるかもしれませんが、それは私のために動作します。

8
Ollie C

シンプルなソリューション:

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

この単純なコードでは、1つのRadioButtonのみがチェックされます。既にチェックされているものをタッチすると、チェックされていないモードに戻ります。

「listIndex」はチェックされた項目を追跡し、ない場合は-1です。

常に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; 
    }
7
AlexKots

私の名前は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>
3
Gourab Singha

同様の問題が発生しました。リサイクルの見方に関係しているように見えました。しかし、私はどこにでも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();
}                
2
Yar

これをはるかに簡単に達成できます。マシュマロで試した

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">
  • ListChoiceIndicatorSingleRadioButtonを表示します。

  • ListChoiceIndicatorMultipleCheckBoxを表示します

choiceMode:SingleListViewにあります。

1
Raja Jawahar

アダプター内部

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

ラジオボタンにスタイルを追加します

<?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ではラジオボタンスタイルを使用します

<?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>
0
sharath yadhav