103 votes

Comment regrouper les boutons radio de différents LinearLayouts?

Je me demandais s'il est possible de regrouper chaque RadioButton individuel dans un unique RadioGroup en conservant la même structure. Ma structure ressemble à ceci :

  • LinearLayout_principal
    • LinearLayout_1
      • RadioButton1
    • LinearLayout_2
      • RadioButton2
    • LinearLayout_3
      • RadioButton3

Comme vous pouvez le constater, chaque RadioButton est actuellement un enfant d'un LinearLayout différent. J'ai essayé d'utiliser la structure ci-dessous, mais cela ne fonctionne pas :

  • RadioGroup
    • LinearLayout_principal
      • LinearLayout_1
        • RadioButton1
      • LinearLayout_2
        • RadioButton2
      • LinearLayout_3
        • RadioButton3

57voto

Scott Biggs Points 958

Il semble que les bonnes personnes chez Google/Android supposent que lorsque vous utilisez des RadioButtons, vous n'avez pas besoin de la flexibilité offerte par tous les autres aspects du système Android UI/layout. Pour le dire simplement : ils ne veulent pas que vous imbriquiez des mises en page et des boutons radio. Soupir.

Donc, il faut contourner le problème. Cela signifie que vous devez implémenter les boutons radio vous-même.

Ce n'est vraiment pas si difficile. Dans votre onCreate(), définissez vos RadioButtons avec leur propre onClick() afin que lorsqu'ils sont activés, ils se setChecked(true) et fassent l'inverse pour les autres boutons. Par exemple:

class FooActivity {

    RadioButton m_one, m_two, m_three;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        m_one = (RadioButton) findViewById(R.id.first_radio_button);
        m_two = (RadioButton) findViewById(R.id.second_radio_button);
        m_three = (RadioButton) findViewById(R.id.third_radio_button);

        m_one.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(true);
                m_two.setChecked(false);
                m_three.setChecked(false);
            }
        });

        m_two.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(false);
                m_two.setChecked(true);
                m_three.setChecked(false);
            }
        });

        m_three.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(false);
                m_two.setChecked(false);
                m_three.setChecked(true);
            }
        });

        ...     
    } // onCreate() 

}

Ouais, je sais - complètement old-school. Mais ça marche. Bonne chance!

29voto

lostdev Points 74

Utilisez cette classe que j'ai créée. Elle trouvera tous les enfants vérifiables dans votre hiérarchie.

import java.util.ArrayList;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class MyRadioGroup extends LinearLayout {

private ArrayList mCheckables = new ArrayList();

public MyRadioGroup(Context context) {
    super(context);
}

public MyRadioGroup(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public MyRadioGroup(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public void addView(View child, int index,
        android.view.ViewGroup.LayoutParams params) {
    super.addView(child, index, params);
    parseChild(child);
}

public void parseChild(final View child)
{
    if(child instanceof Checkable)
    {
        mCheckables.add(child);
        child.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                for(int i = 0; i < mCheckables.size();i++)
                {
                    Checkable view = (Checkable) mCheckables.get(i);
                    if(view == v)
                    {
                        ((Checkable)view).setChecked(true);
                    }
                    else
                    {
                        ((Checkable)view).setChecked(false);
                    }
                }
            }
        });
    }
    else if(child instanceof ViewGroup)
    {
        parseChildren((ViewGroup)child);
    }
}

public void parseChildren(final ViewGroup child)
{
    for (int i = 0; i < child.getChildCount();i++)
    {
        parseChild(child.getChildAt(i));
    }
}
}

17voto

infografnet Points 385

Eh bien, j'ai écrit cette classe simple.

Utilisez-la simplement comme ceci :

// ajoutez ici autant d'identifiants de ressources RadioButton que vous le souhaitez
GRadioGroup gr = new GRadioGroup(this, 
    R.id.radioButton1, R.id.radioButton2, R.id.radioButton3);

ou

GRadioGroup gr = new GRadioGroup(rb1, rb2, rb3);
// où RadioButton rb1 = (RadioButton) findViewById(R.id.radioButton1);
// etc.

Vous pouvez l'appeler dans onCreate() de l'activité par exemple. Peu importe quel RadioButton vous cliquez, les autres deviendront désélectionnés. De plus, peu importe si certains RadioButtons sont à l'intérieur de certains RadioGroup, ou non.

Voici la classe :

package pl.infografnet.GClasses;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewParent;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class GRadioGroup {

    List radios = new ArrayList();

    /**
     * Constructeur, qui vous permet de passer un certain nombre d'instances RadioButton,
     * créant un groupe.
     * 
     * @param radios
     *            Un RadioButton ou plus.
     */
    public GRadioGroup(RadioButton... radios) {
        super();

        for (RadioButton rb : radios) {
            this.radios.add(rb);
            rb.setOnClickListener(onClick);
        }
    }

    /**
     * Constructeur, qui vous permet de passer un certain nombre de RadioButtons 
     * représentés par des identifiants de ressources, créant un groupe.
     * 
     * @param activity
     *            Vue actuelle (ou activité) à laquelle appartiennent ces RadioButtons.
     * @param radiosIDs
     *            Un RadioButton ou plus.
     */
    public GRadioGroup(View activity, int... radiosIDs) {
        super();

        for (int radioButtonID : radiosIDs) {
            RadioButton rb = (RadioButton)activity.findViewById(radioButtonID);
            if (rb != null) {
                this.radios.add(rb);
                rb.setOnClickListener(onClick);
            }
        }
    }

    /**
     * Cela se produit à chaque fois qu'un RadioButton est cliqué, 
     * et désélectionne tous les autres du groupe.
     */
    OnClickListener onClick = new OnClickListener() {

        @Override
        public void onClick(View v) {

            // désélectionnons tous les radios du groupe
            for (RadioButton rb : radios) {

                ViewParent p = rb.getParent();
                if (p.getClass().equals(RadioGroup.class)) {
                    // si le RadioButton appartient à un RadioGroup, 
                    // alors désélectionner tous les radios qui y sont
                    RadioGroup rg = (RadioGroup) p;
                    rg.clearCheck();
                } else {
                    // si le RadioButton N'APPARTIENT PAS à un RadioGroup, 
                    // il suffit de le désélectionner
                    rb.setChecked(false);
                }
            }

            // maintenant sélectionnons le RadioButton actuellement cliqué
            if (v.getClass().equals(RadioButton.class)) {
                RadioButton rb = (RadioButton) v;
                rb.setChecked(true);
            }

        }
    };

}

10voto

Pankaj Points 5055

Cette solution n'a pas été postée donc postez :

Étape 0 : Créez un CompoundButton previousCheckedCompoundButton; en tant que variable globale.

Étape 1 : Créez OnCheckedChangedListener pour les boutons radio

CompoundButton.OnCheckedChangeListener onRadioButtonCheckedListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (!isChecked) return;
            if (previousCheckedCompoundButton != null) {
                previousCheckedCompoundButton.setChecked(false);
            } 
            previousCheckedCompoundButton = buttonView;
        }
    };

Étape 3 : ajoutez un auditeur à tous les boutons radio :

radioButton1.setOnCheckedChangeListener(onRadioButtonCheckedListener);
radioButton2.setOnCheckedChangeListener(onRadioButtonCheckedListener);
radioButton3.setOnCheckedChangeListener(onRadioButtonCheckedListener);
radioButton4.setOnCheckedChangeListener(onRadioButtonCheckedListener);

C'est tout !! vous avez terminé.

8voto

viz Points 667

Soupir.. Vraiment regrettable que Android manque d'une fonctionnalité aussi basique.

Adapté de la réponse de @ScottBiggs, voici peut-être la manière la plus courte de le faire avec Kotlin:

var currentSelected = bouton1
listOf(
    bouton1, bouton2, bouton3, ...
).forEach {
    it.setOnClickListener { _ ->
        currentSelected.isChecked = false
        currentSelected = it
        currentSelected.isChecked = true
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X