web-dev-qa-db-fra.com

Comment regrouper une grille de boutons radio 3x3?

Comme le titre le décrit, j'essaie de regrouper une grille de boutons radio 3x3 dans un seul groupe de radio. Dans une question précédente, j'avais appris que pour que les boutons radio correspondent à un seul groupe, ils devaient être les enfants immédiats du groupe radio auquel ils correspondraient. J'ai appris cela à la dure lorsque j'ai tenté d'encapsuler toute une structure de tableau (avec les boutons radio dans les rangées du tableau) dans un groupe de radio. 

En courant dans ce mur, j'ai essayé ce qui suit:

<TableLayout Android:id="@+id/table_radButtons" 
        Android:layout_width="wrap_content" 
        Android:layout_height="wrap_content"
        Android:layout_below="@+id/title_radGroup_buffer">

        <TableRow>
            <RadioGroup Android:layout_width="fill_parent" 
                Android:layout_height="wrap_content" 
                Android:orientation="horizontal"
                Android:id="@+id/radGroup1">  

                <RadioButton Android:id="@+id/rad1" 
                    Android:text="Button1" 
                    Android:layout_width="105px" 
                    Android:layout_height="wrap_content" 
                    Android:textSize="13px"></RadioButton>
                <RadioButton Android:id="@+id/rad2" 
                    Android:text="Button2" 
                    Android:layout_width="105px" 
                    Android:textSize="13px" 
                    Android:layout_height="wrap_content"></RadioButton>
                <RadioButton Android:id="@+id/rad3" 
                    Android:text="Button3" 
                    Android:layout_width="105px" 
                    Android:textSize="13px" 
                    Android:layout_height="wrap_content"></RadioButton>
            </RadioGroup>
        </TableRow>
        <TableRow>
            <RadioGroup Android:layout_width="fill_parent" 
                Android:layout_height="wrap_content" 
                Android:orientation="horizontal"
                Android:id="@+id/radGroup1">
                  <!-- snippet -->
        </TableRow>
        <!-- snippet --->
</TableLayout>

Évidemment, je n'ai pas appris la première fois parce que je me suis encore heurté à un mur. J'espérais que les boutons radio des différentes lignes de la table remarqueraient qu'ils faisaient partie du même groupe radio (attribuent le même identifiant à chaque groupe), mais cela ne fonctionnait pas.

Est-il possible de regrouper tous ces boutons dans un seul groupe de radio tout en maintenant ma structure 3x3 (3 rangées, 3 boutons radio dans chaque rangée)?

32
Fizz

En réalité, ce n'est pas si difficile si vous sous-classe TableLayout comme dans cet exemple

/**
 * 
 */
package com.codtech.Android.view;

import Android.content.Context;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.RadioButton;
import Android.widget.TableLayout;
import Android.widget.TableRow;

/**
 * @author diego
 *
 */
public class ToggleButtonGroupTableLayout extends TableLayout  implements OnClickListener {

    private static final String TAG = "ToggleButtonGroupTableLayout";
    private RadioButton activeRadioButton;

    /** 
     * @param context
     */
    public ToggleButtonGroupTableLayout(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    /**
     * @param context
     * @param attrs
     */
    public ToggleButtonGroupTableLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onClick(View v) {
        final RadioButton rb = (RadioButton) v;
        if ( activeRadioButton != null ) {
            activeRadioButton.setChecked(false);
        }
        rb.setChecked(true);
        activeRadioButton = rb;
    }

    /* (non-Javadoc)
     * @see Android.widget.TableLayout#addView(Android.view.View, int, Android.view.ViewGroup.LayoutParams)
     */
    @Override
    public void addView(View child, int index,
            Android.view.ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        setChildrenOnClickListener((TableRow)child);
    }


    /* (non-Javadoc)
     * @see Android.widget.TableLayout#addView(Android.view.View, Android.view.ViewGroup.LayoutParams)
     */
    @Override
    public void addView(View child, Android.view.ViewGroup.LayoutParams params) {
        super.addView(child, params);
        setChildrenOnClickListener((TableRow)child);
    }


    private void setChildrenOnClickListener(TableRow tr) {
        final int c = tr.getChildCount();
        for (int i=0; i < c; i++) {
            final View v = tr.getChildAt(i);
            if ( v instanceof RadioButton ) {
                v.setOnClickListener(this);
            }
        }
    }

    public int getCheckedRadioButtonId() {
        if ( activeRadioButton != null ) {
            return activeRadioButton.getId();
        }

        return -1;
    }
}

et créez une mise en page comme celle-ci (bien sûr, vous devez la nettoyer, mais vous avez eu l'idée)

<?xml version="1.0" encoding="utf-8"?>
<com.codtech.Android.view.ToggleButtonGroupTableLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="wrap_content" Android:layout_height="wrap_content"
    Android:id="@+id/radGroup1">
    <TableRow>
            <RadioButton Android:id="@+id/rad1" Android:text="Button1"
                Android:layout_width="105px" Android:layout_height="wrap_content"
                Android:textSize="13px" />
            <RadioButton Android:id="@+id/rad2" Android:text="Button2"
                Android:layout_width="105px" Android:textSize="13px"
                Android:layout_height="wrap_content" />
            <RadioButton Android:id="@+id/rad3" Android:text="Button3"
                Android:layout_width="105px" Android:textSize="13px"
                Android:layout_height="wrap_content" />
    </TableRow>
    <TableRow>
            <RadioButton Android:id="@+id/rad1" Android:text="Button1"
                Android:layout_width="105px" Android:layout_height="wrap_content"
                Android:textSize="13px" />
            <RadioButton Android:id="@+id/rad2" Android:text="Button2"
                Android:layout_width="105px" Android:textSize="13px"
                Android:layout_height="wrap_content" />
            <RadioButton Android:id="@+id/rad3" Android:text="Button3"
                Android:layout_width="105px" Android:textSize="13px"
                Android:layout_height="wrap_content" />
    </TableRow>
    <TableRow>
            <RadioButton Android:id="@+id/rad1" Android:text="Button1"
                Android:layout_width="105px" Android:layout_height="wrap_content"
                Android:textSize="13px" />
            <RadioButton Android:id="@+id/rad2" Android:text="Button2"
                Android:layout_width="105px" Android:textSize="13px"
                Android:layout_height="wrap_content" />
            <RadioButton Android:id="@+id/rad3" Android:text="Button3"
                Android:layout_width="105px" Android:textSize="13px"
                Android:layout_height="wrap_content" />
    </TableRow>
</com.codtech.Android.view.ToggleButtonGroupTableLayout>
63

Après ci-dessus https://stackoverflow.com/a/2383978/5567009 answer J'ai eu une autre solution pour cette question, j'ai ajouté d'autres fonctionnalités telles que, pour enregistrer l'état du groupe et également pour effacer la fonctionnalité de vérification comme dans un groupe de radio.

import Android.content.Context;
import Android.os.Parcel;
import Android.os.Parcelable;
import Android.support.annotation.IdRes;
import Android.util.AttributeSet;
import Android.view.View;
import Android.widget.RadioButton;
import Android.widget.TableLayout;
import Android.widget.TableRow;

public class RadioGridGroup extends TableLayout implements View.OnClickListener {

    private static final String TAG = "ToggleButtonGroupTableLayout";
    private int checkedButtonID = -1;

    /**
     * @param context
     */
    public RadioGridGroup(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    /**
     * @param context
     * @param attrs
     */
    public RadioGridGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onClick(View v) {
        if (v instanceof RadioButton) {
            int id = v.getId();
            check(id);
        }
    }

    private void setCheckedStateForView(int viewId, boolean checked) {
        View checkedView = findViewById(viewId);
        if (checkedView != null && checkedView instanceof RadioButton) {
            ((RadioButton) checkedView).setChecked(checked);
        }
    }

    /* (non-Javadoc)
     * @see Android.widget.TableLayout#addView(Android.view.View, int, Android.view.ViewGroup.LayoutParams)
     */
    @Override
    public void addView(View child, int index,
                        Android.view.ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        setChildrenOnClickListener((TableRow) child);
    }


    /* (non-Javadoc)
     * @see Android.widget.TableLayout#addView(Android.view.View, Android.view.ViewGroup.LayoutParams)
     */
    @Override
    public void addView(View child, Android.view.ViewGroup.LayoutParams params) {
        super.addView(child, params);
        setChildrenOnClickListener((TableRow) child);
    }


    private void setChildrenOnClickListener(TableRow tr) {
        final int c = tr.getChildCount();
        for (int i = 0; i < c; i++) {
            final View v = tr.getChildAt(i);
            if (v instanceof RadioButton) {
                v.setOnClickListener(this);
            }
        }
    }


    /**
     * @return the checked button Id
     */
    public int getCheckedRadioButtonId() {
        return checkedButtonID;
    }


    /**
     * Check the id
     *
     * @param id
     */
    public void check(@IdRes int id) {
        // don't even bother
        if (id != -1 && (id == checkedButtonID)) {
            return;
        }
        if (checkedButtonID != -1) {
            setCheckedStateForView(checkedButtonID, false);
        }
        if (id != -1) {
            setCheckedStateForView(id, true);
        }
        setCheckedId(id);
    }

    /**
     * set the checked button Id
     *
     * @param id
     */
    private void setCheckedId(int id) {
        this.checkedButtonID = id;
    }

    public void clearCheck() {
        check(-1);
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof SavedState)) {
            super.onRestoreInstanceState(state);
            return;
        }

        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());

        this.checkedButtonID = ss.buttonId;
        setCheckedStateForView(checkedButtonID, true);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState savedState = new SavedState(superState);
        savedState.buttonId = checkedButtonID;
        return savedState;
    }

    static class SavedState extends BaseSavedState {
        int buttonId;

        /**
         * Constructor used when reading from a parcel. Reads the state of the superclass.
         *
         * @param source
         */
        public SavedState(Parcel source) {
            super(source);
            buttonId = source.readInt();
        }

        /**
         * Constructor called by derived classes when creating their SavedState objects
         *
         * @param superState The state of the superclass of this view
         */
        public SavedState(Parcelable superState) {
            super(superState);
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(buttonId);
        }

        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }

                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
    }
}

et utilise ceci en XML comme suit

<com.test.customviews.RadioGridGroup xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content">

    <TableRow Android:layout_marginTop="@dimen/preview_five">

        <RadioButton
            Android:id="@+id/rad1"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button1" />

        <RadioButton
            Android:id="@+id/rad2"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button2" />
    </TableRow>

    <TableRow Android:layout_marginTop="@dimen/preview_five">

        <RadioButton
            Android:id="@+id/rad3"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button3" />

        <RadioButton
            Android:id="@+id/rad4"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button4" />
    </TableRow>

    <TableRow Android:layout_marginTop="@dimen/preview_five">

        <RadioButton
            Android:id="@+id/rad5"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button5" />

        <RadioButton
            Android:id="@+id/rad6"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button6" />
    </TableRow>

    <TableRow Android:layout_marginTop="@dimen/preview_five">

        <RadioButton
            Android:id="@+id/rad7"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button7" />

        <RadioButton
            Android:id="@+id/rad8"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="Button8" />
    </TableRow>
</com.test.customviews.RadioGridGroup>

Pour toute autre amélioration, veuillez commenter.

7
Nigam Patro

Votre seule option est de récupérer le code source à RadioGroup et d'essayer de répliquer ses fonctionnalités dans un TableLayout ou quelque chose du genre. Sinon, il est impossible de créer une grille 3x3 de RadioButtons. Heureusement, la classe RadioButton ne connaît pas RadioGroup - toute la logique d’exclusion mutuelle est dans RadioGroup. Par conséquent, il devrait être possible de créer un RadioGrid ou quelque chose comme ça ... mais cela va demander beaucoup de travail.

3
CommonsWare

RadioGroup s'étend de la manière suivante.

Java.lang.Object
 ↳  Android.view.View
   ↳    Android.view.ViewGroup
       ↳    Android.widget.LinearLayout
           ↳    Android.widget.RadioGroup

Si vous devez organiser le bouton radio dans une disposition de grille, vous devrez peut-être créer votre propre code personnalisé qui s'étend de GridLayout.

2
Rupin

Pour ma part, j'irais pour RadioGroups imbriqués. Le groupe radio de base aura une orientation verticale et ses enfants seront trois groupes de radio avec une orientation horizontale.

<RadioGroup
    Android:orientation="vertical">
    <RadioGroup
        Android:id="@+id/rg_1"
        Android:orientation="horizontal">
        <RadioButton />
        <RadioButton />
        <RadioButton />
    </RadioGroup>
    <RadioGroup
        Android:id="@id/rg_2"
        Android:orientation="horizontal">
        <RadioButton />
        <RadioButton />
        <RadioButton />
    </RadioGroup>
    <RadioGroup
        Android:id="@+id/rg_3"
        Android:orientation="horizontal">
        <RadioButton />
        <RadioButton />
        <RadioButton />
    </RadioGroup>
</RadioGroup>

Chacun des groupes radio Chield aura un identifiant qui sera appelé par un objet RadioGroup dans la méthode de validation Java. Comme ça:

RadioGroup rg_1 = (RadioGroup) findViewById(R.id.rg_1);
RadioGroup rg_2 = (RadioGroup) findViewById(R.id.rg_2);
RadioGroup rg_3 = (RadioGroup) findViewById(R.id.rg_3);

Maintenant, en utilisant simplement clearCheck() à l'intérieur du boîtier du commutateur, vous pourrez effacer la vérification des deux autres RadioGroup. Comme ça:

case R.id.radioButton_1:
            if (checked) {
                rg_2.clearCheck();
                rg_3.clearCheck();
            }
            break;
0
DCx86

Pourquoi ne pas utiliser simplement neuf RadioGroupes, ou trois RadioGroupes horizontaux, chacun doté de trois boutons. Chaque groupe de radio peut ensuite être aligné avec un gridView, ou relativeLayout, etc.

Au lieu d'utiliser le standard OnCheckedChangeListener de RadioButton, utilisez celui (du même nom) appartenant au CompoundButton.

Ensuite, chaque fois que vous appuyez sur un bouton RadioButton, vous pouvez utiliser les groupes de radio pour désélectionner les boutons radio. Puis sélectionnez par programme le bouton radio sur lequel vous avez cliqué. 

C'est une solution horrible, mais elle fonctionne comme on l'espère.

Vous trouverez ci-dessous un exemple de code que j'avais l'habitude de faire avec une disposition de boutons 2x2.

  public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        updateList(Hurricane.ELEVATION_ALL);

        watermarkAdapter = new WatermarkAdapter(getActivity(), R.layout.watermark_item, 
                           relatedHurricanes);

        setListAdapter(watermarkAdapter);

        this.getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        this.getView().setBackgroundResource(R.drawable.splash_screen1);


        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);


        View v = this.getView();
        filterGroup1 = (RadioGroup)v.findViewById(R.id.filter_rg1);
        filterGroup2 = (RadioGroup)v.findViewById(R.id.filter_rg2);
        filterGroup3 = (RadioGroup)v.findViewById(R.id.filter_rg3);
        filterGroup4 = (RadioGroup)v.findViewById(R.id.filter_rg4);


        rb1 = (RadioButton) v.findViewById(R.id.first_radio_button);//All
        rb2 = (RadioButton) v.findViewById(R.id.second_radio_button);//0-6
        rb4 = (RadioButton) v.findViewById(R.id.third_radio_button);//6-12
        rb3 = (RadioButton) v.findViewById(R.id.fourth_radio_button);//>=5

        rb1.setOnCheckedChangeListener(this);
        rb2.setOnCheckedChangeListener(this);
        rb3.setOnCheckedChangeListener(this);
        rb4.setOnCheckedChangeListener(this);


    }






 @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

        filterGroup1.clearCheck();
        filterGroup2.clearCheck();
        filterGroup3.clearCheck();
        filterGroup4.clearCheck();


        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this.getActivity());

       int cid = buttonView.getId();

       Editor editor     = prefs.edit();
       int elevation = Hurricane.ELEVATION_ALL;
        //All
       if(rb1.getId() == cid){
          elevation = Hurricane.ELEVATION_ALL;
       }  
       //0-6
       else if(rb2.getId() == cid){
           elevation = Hurricane.ELEVATION_6to12;
       }
       //6-12
       else if(rb3.getId() == cid){       
           elevation = Hurricane.ELEVATION_0to6;
       }
       //>=12
       else if(rb4.getId() == cid){
           elevation = Hurricane.ELEVATION_GT12;
       }

       update(StormFragment.NORMAL, elevation);

    }
0
Andrew S