ZOFTINO.COM android and web dev tutorials

Android RecyclerView RadioGroup Example

In your app, if you need to build a screen where list of items will be shown to users with each item containing multiple options and users will be allowed to select only one option from any one item, then you can use RecyclerView with RadioGroup to implement the screen.

In this post, I’ll show how to use RecyclerView with RadioGroup using an example screen which shows list of packages which each package having multiple options and user is allowed to select only one option from any of the packages.

You can read our other radio button posts such as radio button custom styles and recycler view with radio button example.

Android RecyclerView RadioGroup Example Output

Below screenshot shows our example screen with list of items and each item having multiple options.

android recyclerview radiogroup single selection example

Android RecyclerView RadioGroup Example Code

To show how to use RecyclerView with RadioGroup, we’ll use package selection screen of a television provider application. The screen will display list of packages and prices for each package and allow user to select only one option. Following sections explain layout xml file and java classes of our example.

Item Layout for RecyclerView RadioGroup Example

For our example, item layout contains a text view for package name and a radio group. If you notice, RadioButtons haven’t been added to the RadioGroup in the item layout xml. That is because the number of price options for each package varies. In this example, RadioButtons will be added to RadioGroup programmatically depending on the number of price options for each package.

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/package_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <RadioGroup
        android:id="@+id/price_grp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="4dp"
        android:layout_marginStart="8dp"
        app:layout_constraintTop_toBottomOf="@+id/package_name"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
 

Activity Layout

Activity layout contains text view for screen title and recycler view.

 <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/package_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="Choose Package"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/package_lst"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/package_txt"/>
</android.support.constraint.ConstraintLayout>
 

RecyclerView Adapter for RecyclerView with RadioGroup

Below recyclerview adapter populates data such as package name and price list in RecyclerView using item layout. For each package from the given list of packages, it creates item for recycler view containing package name populated in text view and price options provided as RadioButtons in RadioGroup.

RadioGroup.OnCheckedChangeListener is added to each RadioGroup to capture user selection.

Since only one price or radio button from any one of the packages is allowed to be selected, we need to place logic to clear previous selection. The logic first saves last clicked RadioGroup and then compares it with current radiogroup, if last radiogroup object is not current radiogroup and it has one checked radio button, then it’ll clears the selection of last selected radio button.

 package com.example.srinu.stylesthemes;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

public class PackageRecyclerViewAdapter extends
        RecyclerView.Adapter<PackageRecyclerViewAdapter.ViewHolder> {

    private List<PackageModel> packageList;
    private Context context;

    private RadioGroup lastCheckedRadioGroup = null;

    public PackageRecyclerViewAdapter(List<PackageModel> packageListIn
            , Context ctx) {
        packageList = packageListIn;
        context = ctx;
    }

    @Override
    public PackageRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                                    int viewType) {

        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.package_item, parent, false);

        PackageRecyclerViewAdapter.ViewHolder viewHolder =
                new PackageRecyclerViewAdapter.ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(PackageRecyclerViewAdapter.ViewHolder holder,
                                 int position) {
        PackageModel packageModel = packageList.get(position);
        holder.packageName.setText(packageModel.getPackageName());

        int id = (position+1)*100;
        for(String price : packageModel.getPriceList()){
            RadioButton rb = new RadioButton(PackageRecyclerViewAdapter.this.context);
            rb.setId(id++);
            rb.setText(price);

            holder.priceGroup.addView(rb);
        }
    }

    @Override
    public int getItemCount() {
        return packageList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        public TextView packageName;
        public RadioGroup priceGroup;

        public ViewHolder(View view) {
            super(view);
            packageName = (TextView) view.findViewById(R.id.package_name);
            priceGroup = (RadioGroup) view.findViewById(R.id.price_grp);

            priceGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup radioGroup, int i) {
                    //since only one package is allowed to be selected
                    //this logic clears previous selection
                    //it checks state of last radiogroup and
                    // clears it if it meets conditions
                    if (lastCheckedRadioGroup != null
                            && lastCheckedRadioGroup.getCheckedRadioButtonId()
                                             != radioGroup.getCheckedRadioButtonId()
                            && lastCheckedRadioGroup.getCheckedRadioButtonId() != -1) {
                        lastCheckedRadioGroup.clearCheck();

                        Toast.makeText(PackageRecyclerViewAdapter.this.context,
                                "Radio button clicked " + radioGroup.getCheckedRadioButtonId(),
                                Toast.LENGTH_SHORT).show();

                    }
                    lastCheckedRadioGroup = radioGroup;

                }
            });
        }
    }
}
 

Activity

 package com.example.srinu.stylesthemes;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

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


public class PackagesActivity extends AppCompatActivity {
    private RecyclerView packageRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_package);

        packageRecyclerView = (RecyclerView) findViewById(R.id.package_lst);

        LinearLayoutManager recyclerLayoutManager = new LinearLayoutManager(this);
        packageRecyclerView.setLayoutManager(recyclerLayoutManager);

        DividerItemDecoration dividerItemDecoration =
                new DividerItemDecoration(packageRecyclerView.getContext(),
                recyclerLayoutManager.getOrientation());
        packageRecyclerView.addItemDecoration(dividerItemDecoration);

        PackageRecyclerViewAdapter recyclerViewAdapter = new
                PackageRecyclerViewAdapter(getPackages(),this);
        packageRecyclerView.setAdapter(recyclerViewAdapter);
    }

    private List<PackageModel> getPackages(){
        List<PackageModel> modelList = new ArrayList<PackageModel>();

        List<String> priceList = new ArrayList<String>();
        priceList.add("$33 Monthly");
        priceList.add("$155 Half Yearly");
        priceList.add("$277 Yearly");
        modelList.add(new PackageModel("All English TV Channels", priceList));

        priceList = new ArrayList<String>();
        priceList.add("$45 Monthly");
        priceList.add("$225 Half Yearly");
        priceList.add("$410 Yearly");
        modelList.add(new PackageModel("HD Movie TV Channels", priceList));

        priceList = new ArrayList<String>();
        priceList.add("$50 Monthly");
        priceList.add("$288 Half Yearly");
        priceList.add("$545 Yearly");
        modelList.add(new PackageModel("All Sports Channels", priceList));

        priceList = new ArrayList<String>();
        priceList.add("$25 Monthly");
        priceList.add("$115 Half Yearly");
        priceList.add("$200 Yearly");
        modelList.add(new PackageModel("All News Channels", priceList));

        priceList = new ArrayList<String>();
        priceList.add("$65 Monthly");
        priceList.add("$690 Yearly");
        modelList.add(new PackageModel("Regional TV Channels", priceList));

        return modelList;
    }

}
 

Style

 <resources>
    <style name="MyAppTheme" parent="Theme.AppCompat">
        <item name="android:colorPrimary">#ec407a</item>
        <item name="android:colorPrimaryDark">#ad1457</item>
        <item name="android:windowBackground">@color/colorWindowBg</item>
        <item name="android:textColorPrimary">#7c4dff</item>
        <item name="colorAccent">#e91e63</item>
    </style>
</resources>