• Home

  • Custom Ecommerce
  • Application Development
  • Database Consulting
  • Cloud Hosting
  • Systems Integration
  • Legacy Business Systems
  • Security & Compliance
  • GIS

  • Expertise

  • About Us
  • Our Team
  • Clients
  • Blog
  • Careers

  • VisionPort

  • Contact
  • Our Blog

    Ongoing observations by End Point Dev people

    Dynamically adding custom radio buttons in Android

    Zed Jensen

    By Zed Jensen
    May 9, 2013

    I’ve been writing a timesheet tracking app for End Point. In working on various features of this app, I’ve had more than a few problems to work through, since this project is one of my first on Android and I’ve never used many of the Android features that I’m now using. One particularly fun bit was setting up a scrollable list of radio buttons with numbers from 0 – 23 (no, we don’t often have people working 23 hours on a project in a day, but just in case!) when the user is creating an entry, as a prettier and more backward-compatible alternative to using a number picker to indicate how many hours were spent on this particular job.

    In Android, view layouts are usually defined in XML like this:

    layout/activity_hour_picker.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" >
      <Button android:id="@+id/button"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:onClick="doStuff"
        android:text="Hello World!" />
    </RelativeLayout>
    

    Simple. But, as you can imagine, not so fun when you’re adding a list of 24 buttons—​so, I decided to add them dynamically in the code. First, though, a ScrollView and RadioGroup (ScrollView only allows one child) need to be defined in the XML, no point in doing that programmatically. Let’s add those:

    layout/activity_hour_picker.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" >
       <HorizontalScrollView
            android:id="@+id/hour_scroll_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fillViewport="true"
            android:scrollbars="none" >
            <RadioGroup
                android:id="@+id/hour_radio_group"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="horizontal">
                // This is where our buttons will be
            </RadioGroup>
        </HorizontalScrollView>
    </RelativeLayout>
    

    Okay. So, now, in our Activity, we need to override onCreate if we haven’t already and add the following code:

    src/com/example/HourPickerActivity.java

    @Override
    public void onCreate(Bundle icicle) {
      super.onCreate(icicle);
      setContentView(R.layout.activity_hour_picker);  // This adds the views from the XML we wrote earlier
      ViewGroup hourButtonLayout = (ViewGroup) findViewById(R.id.hour_radio_group);  // This is the id of the RadioGroup we defined
      for (int i = 0; i < RANGE_HOURS; i++) {
        RadioButton button = new RadioButton(this);
        button.setId(i);
        button.setText(Integer.toString(i));
        button.setChecked(i == currentHours); // Only select button with same index as currently selected number of hours
        button.setBackgroundResource(R.drawable.item_selector); // This is a custom button drawable, defined in XML
        hourButtonLayout.addView(button);
      }
    }
    

    And this is what we get:

    It scrolls horizontally like we want, but there’s a problem—​we don’t want the default radio button selector showing up, since we’ve already got custom button graphics showing. And we can’t forget that we’re still missing the code to make everything within the RadioGroup work properly—​In other words, the buttons won’t do anything when a user clicks them. So, let’s add a listener to each button as it’s created:

    src/com/example/HourPickerActivity.java

    <font color="#969696">button.setId(i);</font>
    button.setBackgroundResource(R.drawable.item_selector); // This is a custom button drawable, defined in XML
    button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                ((RadioGroup) view.getParent()).check(view.getId());
                currentHours = view.getId();
            }
        });
    <font color="#969696">button.setText(Integer.toString(i));</font>
    

    So now the currently selected value is ready in our static variable currentHours for whenever the user is finished. Now we need to get rid of the standard radio button graphics. The solution I found is to use selector XML, with just one item that points to a transparent drawable:

    drawable/null_selector.xml

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

    Set each button to use it (and to center the text) like this (R.drawable.null_selector is our selector XML):

    src/com/example/HourPickerActivity.java

    <font color="#969696">button.setText(Integer.toString(i));</font>
    button.setGravity(Gravity.CENTER);
    button.setButtonDrawable(R.drawable.null_selector);
    <font color="#969696">button.setChecked(i == currentHours); // Only select button with same index as currently selected number of hours  </font>
    

    Now, let’s see how this all has pulled together.

    There—​that looks much better! And it works great.

    android mobile


    Comments