webentwicklung-frage-antwort-db.com.de

Android ListView mit Optionsfeld im Single Choice-Modus und benutzerdefiniertes Zeilenlayout

Ich habe eine ListView , die sich im singleChoice-Modus befindet. Alles, was ich möchte, ist, ein RadioButton neben der Seite anzuzeigen. Wenn Sie darauf klicken, dass ein hervorgehobenes Symbol markiert ist, wird ein RadioButton angezeigt. Wenn ein anderer Button angeklickt wird, wird er wieder deaktiviert und der neue wird ausgewählt. Warum ist das so schwer? Dies sollte nicht so kompliziert sein. Ich habeTAGEdamit verbracht, nach einer passenden Antwort darauf zu suchen, und ich habe nichts gefunden, daher frage ich hoffentlich klar und prägnant.

Mein Layout für die Listenansicht (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>

Meine benutzerdefinierte Zeile (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>

Meine onCreate () Methode:

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

Jetzt funktioniert alles wie erwartet, Sie klicken auf einen Radiobutton und durch das Tag kann ich das Element passend aus der Liste auswählen und wie gewünscht bearbeiten. Wenn Sie jedoch auf das erste Optionsfeld klicken, wird das letzte ausgewählt. Klicken Sie erneut auf dasselbe Optionsfeld, und es ist jetzt ebenfalls ausgewählt. Klicken Sie noch einmal darauf und es passiert nichts, sowohl der Letzte als auch der Erste werden ausgewählt. Jetzt klicke ich auf einen anderen in der Liste, er wird wie erwartet ausgewählt. Klicken Sie auf eine der ausgewählten Optionsschaltflächen, und es passiert nichts. Die Optionsschaltfläche bleibt ausgewählt.

Ich habe versucht, Folgendes in onCreate () zu verwenden:

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

und das zeigt nur keine Optionsfelder. GENIAL

Nun, vielleicht (gelesen: höchstwahrscheinlich), bin ich einfach dicht und kann das nicht verstehen, aber ich habe gesehen, dass diese Frage oft ohne wirkliche Antwort gestellt wurde. Viele Verweise auf andere Tutorials oder auf das Commonsware-Buch. Die Kommentare sind jedoch alt und sein Repository hat sich so sehr verändert, dass diese nicht mehr die richtigen Antworten sind.

Hat jemand eine Idee, wie er die erwartete Funktionalität daraus abruft? Andernfalls übergeben Sie mir einfach den Quellcode der GMail-App. :)

26
zkwentz

Denken Sie daran, dass in der ListView-Zeile Elemente RECYCLED sind. Dies erklärt wahrscheinlich, warum sich Aktionen in einer Reihe auf eine andere auswirken. Grabe dich in Marks Buch um und du findest Bericht darüber. 

Wenn Sie einen Adapter mit der Liste verwenden, können Sie getView () für einen Adapter verwenden, um jeder Zeile bei ihrer Erstellung/Wiederverwendung einen Klick-Handler hinzuzufügen und sicherzustellen, dass der Status korrekt verwaltet wird, während die Zeilenelemente erstellt und erneut verwendet werden .

Mein Ansatz ist, den Zustand in meiner eigenen Datenstruktur zu speichern und dann mit getView () den in der Benutzeroberfläche zu spiegeln, wenn der Benutzer in der ListView nach oben oder unten blättert. Es gibt vielleicht eine bessere Lösung, aber das funktioniert für mich.

8
Ollie C

Einfache Lösung:

Fügen Sie diese Zeile im RadioButton-Layout Ihrer XML-Datei hinzu:

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

Fügen Sie dann in der Aktivitätsklasse, die die ListView verwendet, Folgendes hinzu:

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

Mit diesem einfachen Code wird nur ein RadioButton geprüft .. Wenn Sie den bereits markierten berühren, kehrt er in den ungeprüften Modus zurück.

"listIndex" verfolgt das geprüfte Element, -1 falls nicht.

Wenn Sie immer einen Haken behalten möchten, sollte der Code in onClickRadioButton folgendermaßen lauten:

   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

Mein Name ist Gourab Singha. Ich habe dieses Problem gelöst. Ich habe diesen Code geschrieben, um ihn zu lösen. Ich hoffe das hilft dir allen. Vielen Dank. Ich brauche dafür 3 Stunden.

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();


    }

Die 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

Ich hatte gerade ein ähnliches Problem. Es schien, dass es mit dem Recycling von Ansichten zu tun hatte. Aber ich habe überall Logs hinzugefügt und festgestellt, dass die Recycling-Verarbeitung in Ordnung war .Das Problem war die Handhabung von RadioButtons. Ich habe verwendet:

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

und der richtige Weg ist,

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

Sie können viel einfacher erreichen, folgen Sie diesem. Es wurde in Marshmallow versucht

1) habe eine 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 zeigt RadioButton an.

  • ListChoiceIndicatorMultiple zeigt CheckBox an.

Vergessen Sie nicht, choiceMode:Single in Ihre ListView einzufügen.

1
Raja Jawahar

Im Adapter

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

fügen Sie dem Optionsfeld Stil hinzu 

<?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>

und in der XML-Datei verwenden Sie das Optionsfeld 

<?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