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

2voto

BLuFeNiX Points 357

Il y a déjà 20 réponses, mais oserais-je dire que je pense avoir la meilleure.

Cela utilise la liaison des données de vue, donc la première chose que vous voudrez faire est d'ajouter ceci dans le module build.gradle de votre module.

android {
    dataBinding {
        enabled = true
    }
}

Ensuite, vous pouvez créer une disposition avec la hiérarchie de vues souhaitée, par exemple:

fancy_radio_button.xml

Cela peut avoir l'apparence que vous souhaitez, assurez-vous simplement de définir android:clickable="false" sur le RadioButton, et d'utiliser les variables de liaison de données lorsque cela est nécessaire.

Cette disposition est gérée par cette classe:

FancyRadioGroup.java

package com.example.app;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RadioGroup;

import com.example.app.FancyRadioButtonBinding;

import java.util.ArrayList;

public class FancyRadioGroup extends RadioGroup implements View.OnClickListener {

    private final ArrayList radioButtons = new ArrayList<>();
    private OnSelectionChangedListener selectionChangedListener;

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

    public FancyRadioGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setOnSelectionChangedListener(OnSelectionChangedListener selectionChangedListener) {
        this.selectionChangedListener = selectionChangedListener;
    }

    public int addOption(String title, String description) {
        // inflate view and get binding
        FancyRadioButtonBinding buttonBinding = FancyRadioButtonBinding.inflate(LayoutInflater.from(getContext()), this, true);
        // set title and description
        buttonBinding.setTitle(title);
        buttonBinding.setDescription(description);
        // give the button an id (just use the index)
        buttonBinding.setButtonId(radioButtons.size());
        // set the root view's tag to the binding, so we can get the binding from the view
        View root = buttonBinding.getRoot();
        root.setTag(buttonBinding);
        // set click listener on the whole view, so we can click anywhere
        root.setOnClickListener(this);
        radioButtons.add(buttonBinding);
        // return button id to caller, so they know what was clicked
        return buttonBinding.getButtonId();
    }

    @Override
    public void onClick(View v) {
        for (FancyRadioButtonBinding binding : radioButtons) {
                binding.setChecked(v.getTag() == binding);
        }
        if (selectionChangedListener != null) {
            selectionChangedListener.onSelectionChanged(getSelected());
        }
    }

    public int getSelected() {
        for (FancyRadioButtonBinding binding : radioButtons) {
            if (binding.getChecked()) {
                return binding.getButtonId();
            }
        }
        return -1;
    }

    public interface OnSelectionChangedListener {
        void onSelectionChanged(int buttonId);
    }

}

Pour utiliser, ajoutez simplement le FancyRadioGroup à votre vue:

activity_foo.xml

Ensuite, ajoutez vos options:

FooActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    FancyRadioGroup radioGroup = findViewById(R.id.radio_group);
    radioGroup.addOption("The First One", "This option is recommended for users who like the number one.");
    radioGroup.addOption("The Second One", "For advanced users. Larger than one.");
    radioGroup.setOnSelectionChangedListener(this::doSomething);
}

private void doSomething(int id) {
    Toast.makeText(this, "selected: "+id, Toast.LENGTH_SHORT).show();
}

1voto

Luksprog Points 52767

Il n'y a rien qui vous empêche de mettre en œuvre cette structure de mise en page (RadioGroup est en fait une sous-classe de LinearLayout), mais vous ne devriez pas. Tout d'abord, vous créez une structure profonde de 4 niveaux (en utilisant une autre structure de mise en page vous pourriez optimiser cela) et deuxièmement, si vos RadioButtons ne sont pas des enfants directs d'un RadioGroup, le seul élément sélectionné dans le groupe ne fonctionnera pas. Cela signifie que si vous sélectionnez un Radiobutton dans cette disposition, puis en sélectionnez un autre RadioButton, vous vous retrouverez avec deux RadioButtons sélectionnés au lieu du dernier sélectionné.

Si vous expliquez ce que vous voulez faire dans cette mise en page, je pourrais peut-être vous recommander une alternative.

1voto

Nick Points 39

Mon avis sur la question basé sur @infografnet et @lostdev (merci également à @Neromancer pour la suggestion du bouton composé!)

public class AdvRadioGroup {
    public interface OnButtonCheckedListener {
        void onButtonChecked(CompoundButton button);
    }

    private final List buttons;
    private final View.OnClickListener onClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setChecked((CompoundButton) v);
        }
    };

    private OnButtonCheckedListener listener;
    private CompoundButton lastChecked;

    public AdvRadioGroup(View view) {
        buttons = new ArrayList<>();
        parseView(view);
    }

    private void parseView(final View view) {
        if(view instanceof CompoundButton) {
            buttons.add((CompoundButton) view);
            view.setOnClickListener(onClick);
        } else if(view instanceof ViewGroup) {
            final ViewGroup group = (ViewGroup) view;
            for (int i = 0; i < group.getChildCount();i++) {
                parseView(group.getChildAt(i));
            }
        }
    }

    public List getButtons() { return buttons; }

    public CompoundButton getLastChecked() { return lastChecked; }

    public void setChecked(int index) { setChecked(buttons.get(index)); }

    public void setChecked(CompoundButton button) {
        if(button == lastChecked) return;

        for (CompoundButton btn : buttons) {
            btn.setChecked(false);
        }

        button.setChecked(true);

        lastChecked = button;

        if(listener != null) {
            listener.onButtonChecked(button);
        }
    }

    public void setOnButtonCheckedListener(OnButtonCheckedListener listener) { this.listener = listener; }
}

Utilisation (avec écouteur inclus):

AdvRadioGroup group = new AdvRadioGroup(findViewById(R.id.YOUR_VIEW));
group.setOnButtonCheckedListener(new AdvRadioGroup.OnButtonCheckedListener() {
    @Override
    public void onButtonChecked(CompoundButton button) {
        // faire des trucs amusants ici!
    }
});

En prime : Vous pouvez obtenir le dernier bouton vérifié, la liste de tous les boutons et vous pouvez vérifier n'importe quel bouton par index avec cela!

1voto

Achraf Amil Points 321

Comme indiqué dans les réponses, la solution est une simple astuce personnalisée. Voici ma version minimaliste en Kotlin.

import android.widget.RadioButton

class SimpleRadioGroup(private val radioButtons: List) {

    init {
        radioButtons.forEach {
            it.setOnClickListener { clickedButton ->
                radioButtons.forEach { it.isChecked = false }
                (clickedButton as RadioButton).isChecked = true
            }
        }
    }

    val checkedButton: RadioButton?
        get() = radioButtons.firstOrNull { it.isChecked }
}

ensuite, il vous suffit de faire quelque chose comme ça dans le onCreate de votre activité ou dans le onViewCreated du fragment :

SimpleRadioGroup(listOf(radio_button_1, radio_button_2, radio_button_3))

1voto

med.Hamdan Points 196
    int currentCheckedRadioButton = 0;
    int[] mesBoutonsRadio= new int[6];
    mesBoutonsRadio[0] = R.id.premier;
    mesBoutonsRadio[1] = R.id.deuxieme;
    //..
    for (int idBoutonRadio : mesBoutonsRadio) {
        findViewById(idBoutonRadio).setOnClickListener(
                    new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (currentCheckedRadioButton != 0)
                    ((RadioButton) findViewById(currentCheckedRadioButton)).setChecked(false);
                currentCheckedRadioButton = v.getId();

            }
        });
    }

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