Icono del sitio Develou

RadioButton En Android: Controles De Entrada

Un RadioButton es uno control de selección que proporciona la interfaz de Android para permitir a los usuarios seleccionar una opción de un conjunto.

Son ideales para elegir uno de varios elementos con exclusión mutua, es decir, la selección de un radio button obliga a descartar la de otro, permitiendo solo a un ítem estar activo.

Si sigues leyendo podrás aprender a:

Descargar Proyecto En Android Studio

El siguiente video muestra una app que recopila todos los temas que aprenderás en este tutorial:

Si quieres desbloquear el enlace para descargar este proyecto en Android Studio, entonces sigue estas instrucciones:

[sociallocker id=»7121″][/sociallocker]

Crear Proyecto En Android Studio

1. Antes de comenzar, abre Android Studio y crea un nuevo proyecto desde File > New > New Project…

Usa los siguientes de configuración:

2. Selecciona API 11: Android 3.0(Honeycomb) como plataforma mínima de ejecución y presiona Next.

3. Cuando te pregunten si deseas añadir una actividad al proyecto, selecciona la plantilla Empty Activity.

4. Te pedirán una configuración básica de la actividad. Para que vayamos a la par usa lo siguientes nombres:

Usar RadioButton En Android

Como venía diciendo los radio buttons son excelentes para proporcionar exclusión mutua entre las opciones de un conjunto. Por lo que a diferencia del checkbox, este elemento no cambia de estado al presionarse de nuevo.

Este botón es representado por la clase java RadioButton al momento de crear un layout.

Su usó es ideal cuando deseas que el usuario vea todas las opciones del conjunto. De lo contrario usa un Spinner para este cometido.

La exclusión la logras con el componente RadioGroup, el cual agrupa los radio buttons para permitir la selección de uno solamente.

Ejemplo:

Crear un panel de opciones para el sexo en la sección de registro

Solución:

1. Abre actividad_principal.xml y añade una etiqueta nodo <RadioGroup>, extendida con los valores match_parent.

Un dato importante. RadioGroup extiende de LinearLayout, por lo que es posible usar el atributo android:orientation para la alineación de los radio buttons. En este caso usaremos la constante horizontal.

<?xml version="1.0" encoding="utf-8"?>
<RadioGroup
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/opciones_sexo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal">

</RadioGroup>

2. Añade dos hijos <RadioGroup>. Uno con la opción «Masculino» y otro con «Femenino».

Usa el atributo android:checked para determinar el estado de cada radio button.

<?xml version="1.0" encoding="utf-8"?>
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/opciones_sexo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal">

    <RadioButton
        android:id="@+id/radio_masculino"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="16dp"
        android:checked="true"
        android:text="Masculino" />

    <RadioButton
        android:id="@+id/radio_femenino"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="false"
        android:text="Femenino" />
</RadioGroup>

Radio Button En Material Design

En la documentación oficial del Material Design especifican que un Radio Button puede atravesar por 5 estados al igual que los otros controles de selección.

Ten en cuenta que el color que usa el radio button al estar activo se deriva del atributo android:colorAccent que se declara en el tema principal de la app.

Obtener Valor De RadioButton

La obtención del estado de un radio button se realiza con el método isChecked() de la superclase CompoundButton. El retorno es booleano, donde true representa el estado «On» y false el estado «Off».

RadioButton radioButton = (RadioButton) findViewById(R.id.radio_ejemplo);
boolean estado = radioButton.isCheked();

Ejemplo:

Proveer las opciones «Depósito directo» y «Paypal» para el tipo de retiro del afiliado. Disparar un Toast de alerta si la ubicación del usuario no permite un depósito directo al presionar el botón de guardar.

Solución:

1. Crea un layout cuyo nodo principal sea un RelativeLayout. Debido a que vas a simular la sección de un formulario usa una etiqueta (TextView) para la sección con el texto «Opciones de pago».

Por debajo ubica un RadioGroup con dos RadioButton para las opciones que se hablaban en la descripción del problema.

Al final adiciona un botón debajo de estas opciones con la acción «GUARDAR».

actividad_principal.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"
    android:padding="@dimen/activity_horizontal_margin">

    <TextView
        android:id="@+id/etiqueta_opciones_pago"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:text="Opciones de pago:"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <RadioGroup
        android:id="@+id/opciones_pago"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/etiqueta_opciones_pago"
        android:layout_marginBottom="@dimen/activity_vertical_margin">

        <RadioButton
            android:id="@+id/radio_deposito"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="16dp"
            android:checked="true"
            android:text="Depósito directo" />

        <RadioButton
            android:id="@+id/radio_paypal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="false"
            android:text="Paypal" />
    </RadioGroup>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/opciones_pago"
        android:layout_centerHorizontal="true"
        android:text="Guardar" />


</RelativeLayout>

2. Para procesar los eventos de click en el botón usa el atributo onClick en la etiqueta <Button>. Asigna la firma «comprobarModoPago» de la siguiente forma:

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/opciones_pago"
    android:layout_centerHorizontal="true"
    android:onClick="comprobarModoPago"
    android:text="Guardar" />

Y ahora crea el cuerpo en ActividadPrincipal:

public void comprobarModoPago(View v){
    // Acciones
}

3. Lo siguiente es comprobar el estado de la opción para el depósito.

Esto requiere comprobar el valor de radio_deposito con el método isCheck() al interior de comprobarModoPago().

Si está presionado, entonces imprime el mensaje «Comprobar ubicación del usuario».

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.RadioButton;
import android.widget.Toast;

public class ActividadPrincipal extends AppCompatActivity {

    private RadioButton radioDeposito;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        radioDeposito = (RadioButton) findViewById(R.id.radio_deposito);


    }

    public void comprobarModoPago(View v){
        if (radioDeposito.isChecked()){
            final String text = "Comprobar ubicación del usuario";
            Toast.makeText(this, text, Toast.LENGTH_LONG).show();
        }
    }
}

Cómo resultado tendrías:

Obtener estado desde el RadioGroup — Desde el grupo puedes obtener el identificador del RadioButton que tiene el estado On en tiempo de ejecución a través del método getCheckedRadioButtonId().

Para el ejemplo anterior puedes obtener primero el RadioGroup. Luego en el if de comprobarModoPago() usa el método del que te hablo para compararlo con R.id.radio_deposito.

public class ActividadPrincipal extends AppCompatActivity {

    private RadioGroup grupo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        grupo = (RadioGroup) findViewById(R.id.opciones_pago);

    }

    public void comprobarModoPago(View view) {
        if (grupo.getCheckedRadioButtonId() == R.id.radio_deposito) {
            final String text = "Comprobar ubicación del usuario";
            Toast.makeText(this, text, Toast.LENGTH_LONG).show();
        }
    }
}

Cambiar Estado

El estado de la clase RadioButton se hereda de CompoundButton con el atributo booleano mChecked, el cual en notación XML se define con android:checked.

Es intuitivo que el estado On se le atribuye al valor true y Off a false (por defecto).

<RadioButton
    android:id="@+id/radioButton"
    android:checked="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Opción A" />

Si quieres cambiar el estado dinámicamente, entonces usa el método setChecked() con un parámetro booleano.

Ejemplo:

Marcar el radio button con índice 2 de un grupo de 5 opciones

Solución

1. Modifica el layout de la actividad principal con un nodo LinearLayout. Su primer hijo será un TextView con el texto informativo «¿Cuántos días a la semana haces ejercicio?».

La posibilidad de responder al usuario se otorgará con un RadioGroup de 5 opciones:

Con la anterior concepción tendrás la siguiente definición 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"
    android:padding="@dimen/activity_vertical_margin">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:text="¿Cuántos días a la semana haces ejercicio?"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <RadioGroup
        android:id="@+id/grupo_dias"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

        <RadioButton
            android:id="@+id/opcion_todos"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Todos" />

        <RadioButton
            android:id="@+id/opcion_cinco"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cinco" />

        <RadioButton
            android:id="@+id/opcion_tres"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tres" />

        <RadioButton
            android:id="@+id/opcion_uno"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Uno" />

        <RadioButton
            android:id="@+id/opcion_ninguno"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Ninguno" />
    </RadioGroup>


</LinearLayout>

2. Lo siguiente es obtener el radio button cuyo orden de aparición es 2 (índice basado en 0). Esto puedes hacerlo con getChildAt() desde el contenedor.

Al obtener la instancia del view, usa el método setChecked() con el valor de true para marcarlo.

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class ActividadPrincipal extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        RadioGroup contenedor = (RadioGroup) findViewById(R.id.grupo_dias);
        RadioButton opcionI2 = (RadioButton) contenedor.getChildAt(2);
        opcionI2.setChecked(true);

    }

}

3. Ejecuta y verás la opción Tres marcada.

Seleccionar RadioButton desde RadioGroup — El ejemplo anterior puede ser modificado para marcar el radiobutton desde el grupo.

Para ello usa el método check() pasando como parámetro el identificador entero creado en los recursos de android.

Modificación…

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.actividad_principal);

    RadioGroup contenedor = (RadioGroup) findViewById(R.id.grupo_dias);
    RadioButton opcionI2 = (RadioButton) contenedor.getChildAt(2);
    contenedor.check(opcionI2.getId());

}

Recuerda que el método getId() de la clase View permite saber el identificador asignado.

Añadir RadioButton En Android Studio

En esta sección te mostraré como ubicar los elementos RadioGroup y RadioButton en el panel de diseño de Android Studio.

Construirás un pequeño grupo de opciones para determinar el estado marital del usuario en una selección única, cuyas opciones son:

Veamos:

1. Abre tu archivo actividad_principal.xml y cambia todo el contenido por un LinearLayout como padre.

<?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"
    android:padding="@dimen/activity_horizontal_margin">


</LinearLayout>

2. Cambia de la pestaña Text a Design. Cuando aparezca el lienzo, dirígete a la ventana Palette y arrastra un elemento Plain TextView de la sección Widgets.

Pon en su propiedad text el mensaje «Estado marital:» y cambia su identificador por texto_estado_marital.

3. Ubícate en la sección Containers de la paleta y arrastra por debajo del texto un elemento RadioGroup

Si das doble click sobre el RadioGroup en el lienzo se abrirá un diálogo emergente para determinar el id del elemento y su orientación. En el primero caso el valor será opciones_estado_marital y en el otro será vertical.

4. El siguiente paso es añadir los 4 RadioButtons para representar las opciones del estado marital.

Ve a la sección Widgets de la paleta y arrastra 4 elementos RadioButton hacia el RadioGroup en el lienzo. Si no logras insertar con precisión el radio, entonces mejor añádelos desde la ventana Component Tree.

Cambia sus ids rápidamente al dar doble click en el lienzo al formato opcion_<valor>.

Cambia la propiedad text de todos los radios con las opciones que ya habíamos mencionado:

5. Por último determina que el estado Soltero será la opción por defecto al iniciar la app.

Esto puedes hacerlo marcando la propiedad checked de opcion_soltero.

Otra alternativa para determinar el radio button marcado por defecto es a través de la propiedad checkedButton del componente RadioGroup. Solo especifica el identificador de la opción.

6. Si todo te salió bien, tendrás un código para actividad_principal.xml como el siguiente:

<?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"
    android:padding="@dimen/activity_horizontal_margin">

    <TextView
        android:id="@+id/texto_estado_marital"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:text="Estado marital:"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <RadioGroup
        android:id="@+id/opciones_estado_marital"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checkedButton="@+id/opcion_soltero"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/opcion_soltero"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Soltero" />

        <RadioButton
            android:id="@+id/opcion_casado"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Casado" />

        <RadioButton
            android:id="@+id/opcion_divorciado"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Divorciado" />

        <RadioButton
            android:id="@+id/opcion_viudo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Viudo" />
    </RadioGroup>

</LinearLayout>

Manejo De Eventos

Al igual que todos los views, procesa los eventos de click de un RadioButton con View.OnClickListener.

Como viste en la sección de botones, puedes asignar con setOnClickListener() una escucha anónima.

O crear un método con la estructura del controlador onClick() en la actividad contenedora y luego asignarlo al atributo android:onClick de cada Radio Button.

Ejemplo

Mostrar los campos Razón social, Representante y Número de empleados si se selecciona Cliente corporativo. De lo contrario, mostrar los campos para nombre completo y profesión para la opción Particular.

Solución:

1. Modifica el archivo actividad_principal.xml con un LinearLayout como nodo principal.

El diseño es muy parecido a los anteriores. Tendrás:

El RadioButton marcado por defecto será «Particular» por lo que tendremos los campos de texto asociados visibles al inicio. Sin embargo al seleccionar «Corporativo» debes intercambiar la visibilidad de estos elementos con los asociados a este tipo de cliente.

El siguiente diagrama resume la estructura del layout:

La definición en código será:

<?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"
    android:padding="@dimen/activity_horizontal_margin">

    <TextView
        android:id="@+id/tv_estado_marital"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:text="Tipo de cliente:"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <RadioGroup
        android:id="@+id/rg_tipo_cliente"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:checkedButton="@+id/rb_particular"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rb_corporativo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Corporativo" />

        <RadioButton
            android:id="@+id/rb_particular"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Particular" />
    </RadioGroup>

    <LinearLayout
        android:id="@+id/ll_contenedor_particular"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <EditText
            android:id="@+id/et_nombre"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/activity_vertical_margin"
            android:hint="Nombre completo"
            android:inputType="textPersonName" />

        <EditText
            android:id="@+id/et_profesion"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Profesión" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_contenedor_corporativo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:visibility="gone">

        <EditText
            android:id="@+id/et_razon_social"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/activity_vertical_margin"
            android:hint="Razón social"
            android:inputType="textPersonName" />

        <EditText
            android:id="@+id/et_representante"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/activity_vertical_margin"
            android:hint="Representante"
            android:inputType="textPersonName" />

        <EditText
            android:id="@+id/et_no_empleados"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Número de empleados"
            android:inputType="number" />
    </LinearLayout>

</LinearLayout>

El atributo android:visibility de ll_contenedor_corporativo será gone para evitar su aparición en el layout, ya que el cliente particular es la selección por defecto.

2. Añade a los dos RadioButtons en onClick la firma «onRadioButtonClicked» (o como le quieras llamar al controlador).

Android Studio te permitirá crear el método automáticamente si presionas sobre el texto ALT + ENTER.

El resultado será:

public void onRadioButtonClicked(View view) {
    // Acciones
}

3. Procesa la acción para cada RadioButton según el identificador obtenido desde el parámetro view. Ten en cuenta que:

Sumando estas características tu código será similar a este:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.RadioButton;

public class ActividadPrincipal extends AppCompatActivity {

    private View contenedorParticular;
    private View contenedorCorporativo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        contenedorParticular = findViewById(R.id.ll_contenedor_particular);
        contenedorCorporativo = findViewById(R.id.ll_contenedor_corporativo);
    }

    public void onRadioButtonClicked(View view) {
        boolean marcado = ((RadioButton) view).isChecked();

        switch (view.getId()) {
            case R.id.rb_corporativo:
                if (marcado) {
                    mostrarParticular(false);
                }
                break;

            case R.id.rb_particular:
                if (marcado) {
                    mostrarParticular(true);
                }
                break;
        }
    }

    private void mostrarParticular(boolean b) {
        contenedorParticular.setVisibility(b ? View.VISIBLE : View.GONE);
        contenedorCorporativo.setVisibility(b ? View.GONE : View.VISIBLE);
    }
}

4. Ejecuta y cambia entre opciones para ver la aparición de cada contenedor:

Como ves, mostrarParticular() hace visible el formulario del cliente particular si el parámetro b es true, de lo contrario en su lugar aparecerá el contenedor del corporativo.

Usar OnCheckedChangeListener en el RadioGroup — Otra opción para configurar una escucha de eventos es a través de la interfaz RadioGroup.OnCheckedChangeListener.

Esta reacciona ante el cambio de estados de los hijos del contenedor. Simplemente usa el método setOnCheckedChangeListener() con una nueva instancia anónima en el grupo.

Si implementaras el ejemplo anterior con este nuevo enfoque tendrías la siguiente modificación:

public class ActividadPrincipal extends AppCompatActivity {


    private View contenedorParticular;
    private View contenedorCorporativo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        contenedorParticular = findViewById(R.id.ll_contenedor_particular);
        contenedorCorporativo = findViewById(R.id.ll_contenedor_corporativo);

        RadioGroup opcionesCliente = (RadioGroup)findViewById(R.id.rg_tipo_cliente);
        opcionesCliente.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.rb_particular:
                        mostrarParticular(true);
                        break;
                    case R.id.rb_corporativo:
                        mostrarParticular(false);
                        break;
                }
            }
        });
    }

    private void mostrarParticular(boolean b) {
        contenedorParticular.setVisibility(b ? View.VISIBLE : View.GONE);
        contenedorCorporativo.setVisibility(b ? View.GONE : View.VISIBLE);
    }

}

Crear RadioButtons Programáticamente

Usa uno de los constructores de la clase RadioButton para crear una nueva instancia cuyo contexto sea la actividad.

RadioButton opcion = new RadioButton(this);

Adicionalmente emplea los siguientes métodos para configurar las propiedades de los radios:

Método Descripción
setLayoutParams() Asigna los atributos relacionados al layout, como por ejemplo su ancho y altura
setId() Asigna un identificador descrito en los recursos. Puedes tenerlos en un archivo ids.xml y referirte a ellos como R.id.<nombre> en el parámetro de setId().
setText() Modifica el texto del radio button
View.generateViewId() Genera un identificador que no colisione con los que ya han sido generados. Aplica para versiones del SDK mayores o igual a 17.
setOrientation() Método de RadioGroup para cambiar la orientación de los radio buttons. Puedes usar la constante View.HORIZONTAL y View.VERTICAL
setTag() Asigna una etiqueta única para un radio buttton. Este método me parece útil cuando se requiere acceder en el futuro a un radio creado dinámicamente.
addView() Añade la nueva instancia del RadioButton al RadioGroup

Ejemplo

Crear dinámicamente un conjunto de RadioButtons desde un array de strings cuyo contenido son marcas de autos.

Solución:

1. Cambia el contenido de actividad_principal.xml con un nodo LinearLayout.  Declara como primer hijo un TextView con el texto de presentación y por debajo pon un RadioGroup vacío.

<?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"
    android:padding="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_marca_auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:text="¿Qué marca de auto prefieres?"
        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

    <RadioGroup
        android:id="@+id/rg_opciones_marca"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

2. Dentro de ActividadPrincipal crea un método llamado crearRadioButton() para producir radio buttons, donde la marca de auto sea el parámetro de entrada.

private RadioButton crearRadioButton(String marca) {
    RadioButton nuevoRadio = new RadioButton(this);
    LinearLayout.LayoutParams params = new RadioGroup.LayoutParams(
            RadioGroup.LayoutParams.WRAP_CONTENT,
            RadioGroup.LayoutParams.WRAP_CONTENT);
    nuevoRadio.setLayoutParams(params);
    nuevoRadio.setText(marca);
    nuevoRadio.setTag(marca);
    return nuevoRadio;
}

Como ves, se crea una nueva instancia de RadioGroup.LayoutParams para ajustar al contenido del radio con la constante WRAP_CONTENT. Si deseas expandir la dimensión en todo el padre, usa MATCH_PARENT.

3. Ahora declara un arreglo de strings con las marcas: «Mazda», «Mercedes Benz», «Audi», «Chevrolet»

La idea es recorrer su contenido con un ciclo for donde se creará un radio button con crearRadioButton() y luego se asignará al grupo con addView().

Por último cambia el estado del primer radio button a On con el método setCheked().

ActividadPrincipal.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class ActividadPrincipal extends AppCompatActivity {

    private static String[] MARCAS = {
            "Mazda", "Mercedes Benz", "Audi", "Chevrolet"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        RadioGroup opcionesMarca = (RadioGroup)findViewById(R.id.rg_opciones_marca);

        for(String marca : MARCAS) {
            RadioButton nuevoRadio = crearRadioButton(marca);
            opcionesMarca.addView(nuevoRadio);
        }

        RadioButton primerRadio = (RadioButton) opcionesMarca.getChildAt(0);
        primerRadio.setChecked(true);
    }

    private RadioButton crearRadioButton(String marca) {
        RadioButton nuevoRadio = new RadioButton(this);
        LinearLayout.LayoutParams params = new RadioGroup.LayoutParams(
                RadioGroup.LayoutParams.WRAP_CONTENT,
                RadioGroup.LayoutParams.WRAP_CONTENT);
        nuevoRadio.setLayoutParams(params);
        nuevoRadio.setText(marca);
        nuevoRadio.setTag(marca);
        return nuevoRadio;
    }

}

4. La ejecución mostrará el resultado final:

Crear RadioButtons Desde SQLite

Existen casos donde tendrás una serie de datos en una base de datos SQLite que representan cada una de las opciones que irán en un RadioGroup.

En ese caso debes consultar los datos de la tabla específica y luego recorrer el cursor resultante para obtener el texto del RadioButton.

Ejemplo

Obtener las opciones de respuesta para la pregunta «¿A qué animal nunca dejan de crecerle los dientes?» desde la base de datos

Solución

1. Lo primero es definir el layout del requerimiento.

Al igual que los casos anteriores, tendremos un TextView para informar al usuario de la selección que se encuentra por debajo en un RadioGroup.

actividad_principal.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"
    android:padding="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_pregunta"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:text="¿A qué animal nunca dejan de crecerle los dientes?"
        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

    <RadioGroup
        android:id="@+id/rg_respuestas"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

2. La creación de la base de datos local arranca con una clase de contrato que disponga de todos los nombres y cualidades que tendrán las tablas.

Ve al menú de herramientas y presiona File > New > Java Class y crea una clase con el nombre Contrato.

Debido a que tenemos solo una tabla llamada respuesta cuyos campos son el identificador y el texto de la respuesta, el contenido del contrato se resume a:

/**
 * Convenciones de nombrado en la base de datos SQLite local
 */
public class Contrato {

    interface ColumnasRespuesta {
        String RESPUESTA = "respuesta";
    }


    private Contrato() {
    }

}

Básicamente el modelo se podría ilustrar así:

Aunque es un ejemplo básico, te será de ayuda para experimentar la dinámica.

Si quieres aprender diseños de bases de datos, entonces descarga mi ebook con una serie de pasos para facilitarte esta tarea.

3. Ahora crea el controlador de la base de datos para describir como se creará la estructura inicial.

Recuerda que solo debes crear una nueva clase java que extienda de SQLiteOpenHelper y luego sobrescribir los controladores onCreate() y onUpgrade().

En la creación usa el comando CREATE TABLE para crear la tabla respuesta y añade 4 registros con los siguientes strings.

En la actualización elimina la tabla respuesta y vuelve a crearla.

También es necesario crear un método get para conseguir todos los registros de las respuestas. Llámalo getRespuestas() y realiza el query necesario.

Al final tu controlador tendría un código similar al siguiente:

ControladorSQLite.java

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;

/**
 * Controlador de operaciones de la base de datos
 */
public class ControladorSQLite extends SQLiteOpenHelper {

    private static final String NOMBRE_BASE_DATOS = "preguntas.db";

    private static final int VERSION_ACTUAL = 1;

    private final Context contexto;

    interface Tablas {
        String RESPUESTA = "respuesta";
    }


    public ControladorSQLite(Context contexto) {
        super(contexto, NOMBRE_BASE_DATOS, null, VERSION_ACTUAL);
        this.contexto = contexto;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String respuesta = Contrato.ColumnasRespuesta.RESPUESTA;

        String scriptCreate = "CREATE TABLE " + Tablas.RESPUESTA + "(" +
                BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                respuesta + " TEXT UNIQUE NOT NULL)";
        db.execSQL(scriptCreate);

        ContentValues cv = new ContentValues();
        cv.put(respuesta, "A. Castor");
        db.insert(Tablas.RESPUESTA, BaseColumns._ID, cv);
        cv.put(respuesta, "B. Jaguar");
        db.insert(Tablas.RESPUESTA, BaseColumns._ID, cv);
        cv.put(respuesta, "C. Elefante");
        db.insert(Tablas.RESPUESTA, BaseColumns._ID, cv);
        cv.put(respuesta, "D. Rinoceronte");
        db.insert(Tablas.RESPUESTA, BaseColumns._ID, cv);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + Tablas.RESPUESTA);
        onCreate(db);
    }

    public Cursor getRespuestas() {
        SQLiteDatabase db = getReadableDatabase();
        return db.query(Tablas.RESPUESTA, null, null, null, null, null, null);
    }
}

4. Finalmente ve a la actividad principal y crea una instancia en del controlador sqlite en onCreate().

La idea es crear los radios programáticamente como viste en la sección anterior.

Usa un ciclo while para recorrer el cursor que retorna el método getRespuestas(). En cada iteración obtén la columna "respuesta" con el método getString() y usa su contenido para crear el RadioButton.

import android.database.Cursor;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class ActividadPrincipal extends AppCompatActivity {

    private ControladorSQLite sqLiteOpenHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.actividad_principal);

        RadioGroup opcionesMarca = (RadioGroup) findViewById(R.id.rg_respuestas);

        sqLiteOpenHelper = new ControladorSQLite(this);

        Cursor c = sqLiteOpenHelper.getRespuestas();

        while (c.moveToNext()) {
            String respuesta = c.getString(c.getColumnIndex(Contrato.ColumnasRespuesta.RESPUESTA));
            opcionesMarca.addView(crearRadioButton(respuesta));
        }

    }

    private RadioButton crearRadioButton(String respuesta) {
        RadioButton nuevoRadio = new RadioButton(this);
        LinearLayout.LayoutParams params = new RadioGroup.LayoutParams(
                RadioGroup.LayoutParams.WRAP_CONTENT,
                RadioGroup.LayoutParams.WRAP_CONTENT);
        nuevoRadio.setLayoutParams(params);
        nuevoRadio.setText(respuesta);
        nuevoRadio.setTag(respuesta);
        return nuevoRadio;
    }

}

Importante que uses servicios o tareas asíncronas para consultar la base de datos y no atrofiar el hilo principal de la app.

5. Ejecuta el proyecto y tendrás los radio buttons en su lugar:

Cambiar Color Del Botón

Una de las formas de personalizar un RadioButton es cambiar el color de su botón.

Esta sección te mostrará dos formas para hacerlo:

1. Usar el atributo app:buttonTint sobre el RadioButton. Sin embargo, debido a que cambia el drawable completo, verás que el estado Off también cambia su tinte.

<RadioButton
    android:id="@+id/radioButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="3 o más"
    app:buttonTint="@color/colorPrimary" />

2. La otra alternativa es aprovechar el atributo android:colorAccent. Recuerda que por defecto este será el color del estado activo del RadioButton, así que puedes usar el atributo android:theme para sobrescribir dicho elemento y personalizar únicamente el view.

styles.xml

<style name="RadioButtonLima">
    <item name="colorAccent">#D4E157</item>
</style>

layout

<RadioButton
    android:id="@+id/radioButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Entre 10 y 15"
    android:theme="@style/RadioButtonLima" />

Cambiar Imagen Del Background

Si necesitas cambiar el background completo del RadioButton, necesitas crear un drawable con una lista de estados (<selector>).

Para hacerlo debes crear como mínimo dos backgrounds. Uno para el estado On y otro para Off. Podrías también implementar el estado deshabilitado y enfocado si llegas a requerirlos en la vida de tu UI.

La idea es que uses los atributos android:background y android:button para cambiar el background completo del componente o solo el del botón.

Ejemplo

Crear un background personalizado para un conjunto de 4 RadioButtons que representan una selección del clima.

Solución:

1. Como ves en la ilustración anterior, este conjunto de radio buttons tiene un estilo parecido al componente Button Group del framework Bootstrap.

Te voy a mostrar cómo hacer el primer botón de lluvia para que te guíes. Los demás siguen el mismo patrón.

Lo primero es producir el drawable que represente la imagen del botón, en este caso son iconos relacionados al clima. Algunos métodos para hacerlo son:

En mi caso usaré vectores.

Para ello ve a Material Design Icons y busca el icono que satisfaga tu necesidad. En mi caso fué weather-rainy de Austin Andrews. Luego selecciona View Vector Drawable.

Esto arrojará el código XML para el nuevo drawable que crearemos en Android Studio.

Presiona Download .xml para descargar el archivo o copia el código directamente.

Esto debe producirte un archivo dentro de res/drawable al que llamarás ic_clima_lluvia.xml con el siguiente contenido.

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="24"
    android:viewportWidth="24">
    <path
        android:fillColor="#fff"
        android:pathData="M6,14A1,1 0 0,1 7,15A1,1 0 0,1 6,16A5,5 0 0,1 1,11A5,5 0 0,1 6,6C7,3.65 9.3,2 12,2C15.43,2 18.24,4.66 18.5,8.03L19,8A4,4 0 0,1 23,12A4,4 0 0,1 19,16H18A1,1 0 0,1 17,15A1,1 0 0,1 18,14H19A2,2 0 0,0 21,12A2,2 0 0,0 19,10H17V9A5,5 0 0,0 12,4C9.5,4 7.45,5.82 7.06,8.19C6.73,8.07 6.37,8 6,8A3,3 0 0,0 3,11A3,3 0 0,0 6,14M14.83,15.67C16.39,17.23 16.39,19.5 14.83,21.08C14.05,21.86 13,22 12,22C11,22 9.95,21.86 9.17,21.08C7.61,19.5 7.61,17.23 9.17,15.67L12,11L14.83,15.67M13.41,16.69L12,14.25L10.59,16.69C9.8,17.5 9.8,18.7 10.59,19.5C11,19.93 11.5,20 12,20C12.5,20 13,19.93 13.41,19.5C14.2,18.7 14.2,17.5 13.41,16.69Z" />
</vector>

2. Necesitas que este elemento tenga por debajo un background sólido con un color que dependa del estado.

Así que define los colores On y Off en colors.xml de la siguiente forma:

<color name="colorRadioButtonOn">#2980b9</color>
<color name="colorRadioButtonOff">#3498db</color>

Ambos tonos son la variación de un azul tipo Flat Design.

3. Crea un drawable por capas (<layer-list>) para el estado On donde se ponga por debajo un rectángulo con fondo colorRadioButtonOn y añade arco a sus bordes izquierdo.

Por encima irá el icono con 10dp de padding en toda dirección:

rb_background_lluvia_on.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <corners
                android:bottomLeftRadius="10dp"
                android:topLeftRadius="10dp" />
            <solid android:color="@color/colorRadioButtonOn" />
        </shape>
    </item>
    <item
        android:bottom="10dp"
        android:drawable="@drawable/ic_clima_lluvia"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp" />
</layer-list>

El estado Off es idéntico, solo que usas a colorRadioButtonOff en el rectángulo.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <corners
                android:bottomLeftRadius="10dp"
                android:topLeftRadius="10dp" />
            <solid android:color="@color/colorRadioButtonOff" />
        </shape>
    </item>
    <item
        android:bottom="10dp"
        android:drawable="@drawable/ic_clima_lluvia"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp" />
</layer-list>

4. Crea el drawable que representará el background final del RadioButton. Solo debes añadir un selector con dos ítems.

El primero representará el estado marcado (state_checked = "true") y el segundo el estado Off (state_checked="false").

rb_background_lluvia.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/rb_background_lluvia_on" android:state_checked="true" />

    <item android:drawable="@drawable/rb_background_lluvia_off" android:state_checked="false" />
</selector>

5. Modifica el layout de la actividad principal y añade un RadioGroup con 4 opciones.

Cada uno de ellos no debe tener texto y su atributo android:background debe tener asignado @null.

Solo usarás android:button al cuál asignarás el background que acabas de construir.

actividad_principal.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:gravity="center"
    android:orientation="vertical">

    <RadioGroup
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checkedButton="@+id/rb_lluvia"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rb_lluvia"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:button="@drawable/rb_background_lluvia" />

        <RadioButton
            android:id="@+id/rb_nublado"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:button="@drawable/rb_background_nublado" />

        <RadioButton
            android:id="@+id/rb_soleado"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:button="@drawable/rb_background_soleado" />

        <RadioButton
            android:id="@+id/rb_torrencial"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@null"
            android:button="@drawable/rb_background_torrencial" />
    </RadioGroup>
</LinearLayout>

Conclusión

¿Cómo te fue con el control RadioButton?

De seguro encontraste varias características que te ayudaran en la UI de tu app.

Recuerda que este widget es ideal cuando es necesario la selección de una sola opción entre un conjunto.

Te será de gran ayuda en formularios al combinarlo con checkboxes, campos de texto, raised buttons, etc.

Incluso reflejar datos de sqlite, determinar acciones en diálogos o crear preferencias para el usuario.

Salir de la versión móvil