☰
cw-omnibus 实战:Android RadioButton 与 RadioGroup 单选组件从布局到状态监听的完整实现
2026/10/15 8:28:47 网站建设 项目流程
  • 示例工程
  • 教程

【免费下载链接】cw-omnibus

Source code to omnibus edition of _The Busy Coder's Guide to Android Development_

项目地址:https://gitcode.com/gh_mirrors/cw/cw-omnibus
点击查看免费下载

导读

RadioButton(单选按钮)与RadioGroup(单选组)是 Android 中最常用的"多选一"交互组件组合:RadioGroup负责承载一组RadioButton并自动保证"同一时刻只有一个被选中",非常适合性别选择、答题选项、设置项二选一或三选一这类场景。本文以 cw-omnibus 仓库中的 Basic/RadioButton 示例为骨架,逐步拆解其布局文件、字符串资源、Activity 入口与工程配置,并对比 BasicMaterial/RadioButton 的 Material 主题版本,帮助读者掌握从零搭建单选界面的完整链路,同时理解选中状态监听、程序化控制等进阶用法。


一、示例定位:一份"最小可运行"的单选组件演示

在 cw-omnibus(《The Busy Coder's Guide to Android Development》全量示例源码合集)中,Basic/RadioButton/README.markdown 用一句话概括了本示例的核心目标:

This sample Android app demonstrates usingRadioButtonwidgets in aRadioGroup.

即:演示如何在RadioGroup容器中使用RadioButton控件。与之配套的兄弟示例 Basic/CheckBox 则演示多选CheckBox的用法,二者同属于"常用控件与容器"主题章节,可以对照学习。

该示例的工程结构非常精简,仅包含一个app模块(见 settings.gradle 中的include ':app'),核心代码文件只有三个:

文件职责
app/src/main/res/layout/main.xml界面布局:一个纵向RadioGroup内嵌三个RadioButton
app/src/main/res/values/strings.xml字符串资源:应用名与三个选项文案
app/src/main/java/com/commonsware/android/basic/RadioButtonDemo.javaActivity 入口:加载布局并展示界面

这种"布局 + 资源 + 一个 Activity"的最小组合,正是 Android 入门阶段学习单选控件的理想范本。


二、布局核心:用 RadioGroup 保证单选互斥

示例的界面完全由 XML 布局声明,未写任何 Java 逻辑。完整布局如下(app/src/main/res/layout/main.xml):

<?xml version="1.0" encoding="utf-8"?> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/rock" /> <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/scissors" /> <RadioButton android:id="@+id/radio3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/paper" /> </RadioGroup>

2.1 RadioGroup:单选互斥的容器

RadioGroup是LinearLayout的子类,具备线性容器的全部特性,同时额外承担单选互斥管理职责:

  • android:orientation:决定选项排列方向。示例取vertical(垂直排列),改为horizontal即可让三个选项横向排布在一行内。
  • android:layout_width/height:示例均为match_parent,让整个单选组铺满屏幕。
  • 互斥规则:在同一个RadioGroup内,任意时刻最多只有一个RadioButton处于选中(checked)状态。当用户点击一个新的选项时,RadioGroup会自动取消其余选项的选中态,开发者无需手工遍历清除。这正是"组"存在的意义——脱离RadioGroup的RadioButton彼此独立、可同时选中,不构成单选语义。

2.2 RadioButton:单个选项

每个RadioButton继承自CompoundButton,是一个"圆形按钮 + 文本标签"的复合控件,常用属性:

属性示例取值作用
android:id@+id/radio1等为每个选项定义唯一标识,供 Java 代码findViewById查找
android:layout_width/heightwrap_content让按钮按自身内容自适应大小
android:text@string/rock引用字符串资源作为选项文案,而非硬编码

示例为三个选项分别声明了radio1、radio2、radio3三个 id,对应"石头(Rock)— 剪刀(Scissors)— 布(Paper)"这一经典的猜拳三选一场景,语义直观、便于演示单选行为。

2.3 默认选中项

示例布局中三个RadioButton均未声明android:checked属性,因此初始状态三者都处于未选中状态。在实际项目中,如果要求"默认必须选中某一项",只需在目标RadioButton上添加android:checked="true"即可;而RadioGroup也支持在 Java 侧通过check(int id)或clearCheck()方法程序化控制选中项。更进阶的默认值设定(如根据持久化数据恢复选中项)会在第四节展开说明。


三、字符串资源:文案与布局解耦

选项文案没有直接写死在布局里,而是抽取到 app/src/main/res/values/strings.xml:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">RadioButtonDemo</string> <string name="rock">Rock</string> <string name="scissors">Scissors</string> <string name="paper">Paper</string> </resources>

其中rock、scissors、paper分别对应三个单选选项的文本,app_name则作为应用与 Activity 的显示名称。这样做的好处是:

  • 多语言支持:新增values-zh/strings.xml、values-ja/strings.xml等目录即可完成本地化,无需改动布局;
  • 便于维护:文案集中管理,修改措辞不会触及代码与布局;
  • 符合 Android 最佳实践:所有面向用户的文本都应放入资源而非硬编码字符串。

四、Java 入口:一个纯粹加载布局的 Activity

Java 侧的实现极其简洁(RadioButtonDemo.java):

package com.commonsware.android.basic; import android.app.Activity; import android.os.Bundle; public class RadioButtonDemo extends Activity { @Override public void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.main); } }

要点如下:

  • RadioButtonDemo继承原生Activity(android.app.Activity),而非 AppCompat 系列;
  • onCreate(Bundle state)中通过setContentView(R.layout.main)将第二节的布局树挂载为界面内容;
  • 由于本示例只演示静态展示,没有编写任何事件监听代码——单选互斥行为完全由RadioGroup内部机制保证。

4.1 如何监听"用户选了哪一项"

虽然示例未实现监听,但"获取选中结果"是单选组件的核心诉求。RadioButton继承自CompoundButton,因此可通过setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener)监听选中状态变化。同仓库的 Basic/CheckBox/app/src/main/java/com/commonsware/android/checkbox/CheckBoxDemo.java 展示了这一监听模式的完整写法(CheckBox与RadioButton同为CompoundButton子类,监听 API 完全一致):

public class CheckBoxDemo extends Activity implements CompoundButton.OnCheckedChangeListener { CheckBox cb; @Override public void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.main); cb = (CheckBox) findViewById(R.id.check); cb.setOnCheckedChangeListener(this); } public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { cb.setText(R.string.checked); } else { cb.setText(R.string.unchecked); } } }

将其套用到本示例,即可得到实用的单选反馈逻辑:

RadioGroup group = (RadioGroup) findViewById(R.id.group); group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // checkedId 为当前选中项的 id(如 R.id.radio1) if (checkedId == R.id.radio1) { // 用户选择了 Rock } } });

两点关键区别需要注意:

  1. RadioGroup提供的OnCheckedChangeListener回调签名是onCheckedChanged(RadioGroup group, int checkedId),直接给出被选中项的 id,无需遍历;
  2. CompoundButton级别的监听签名是onCheckedChanged(CompoundButton buttonView, boolean isChecked),粒度到单个按钮。

此外,通过radio.isChecked()可查询某个按钮的选中态,通过radio.setChecked(true)或group.check(R.id.radioX)可程序化设置选中项——这些 API 组合足以覆盖"读取当前选择"和"恢复默认选择"两类常见需求。


五、工程与构建配置:让示例跑起来

要让这份示例编译运行,还需要了解它的工程配置。该示例使用 Gradle 构建(Android Studio 时代的标准工程布局),相关配置如下:

5.1 模块声明与 SDK 定位

settings.gradle 声明了唯一模块:app。同时项目还保留了 project.properties(早期 Ant/Eclipse 工程的残留配置),其中target=android-19表明项目定位在 API 19(Android 4.4)级别编译。

5.2 应用清单

app/src/main/AndroidManifest.xml 的关键声明:

<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14"/> ... <application android:icon="@drawable/ic_launcher"> <activity android:name=".RadioButtonDemo" android:label="RadioButtonDemo"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application>
  • minSdkVersion="4"使示例可运行在 Android 1.6 及以上的几乎所有设备上,兼容范围极广;
  • RadioButtonDemo被声明为带MAIN/LAUNCHER过滤器的启动 Activity,即应用安装后的默认入口;
  • 同时声明了supports-screens(兼容各尺寸屏幕)与应用图标@drawable/ic_launcher(drawable-ldpi 至 drawable-xhdpi 共四档密度图标)。

5.3 构建方式

由于工程采用 Gradle 构建(gradle/wrapper/gradle-wrapper.properties 已提供 Wrapper 配置),在 Android Studio 中直接打开该目录即可同步并运行;命令行下也可使用 Gradle Wrapper 执行构建任务(如assembleDebug)。构建时还会套用 proguard.cfg 中的混淆规则(该配置面向android.app.Activity等四大组件及Parcelable实现类做 keep 保护),因此即使启用混淆也不会误伤 Activity 与布局回调。


六、进阶对比:Material 主题下的单选组件

在 Android 5.0(API 21)引入 Material Design 之后,单选组件的视觉风格有了显著升级。cw-omnibus 为此提供了配套示例 BasicMaterial/RadioButton,其布局文件与 Basic 版完全一致(同样是纵向RadioGroup+ 三个RadioButton,见 其 main.xml),差异集中在主题与清单配置上:

6.1 主题替换

styles.xml 以android:Theme.Material为父主题,并注入三色方案:

<resources> <style name="AppTheme" parent="android:Theme.Material"> <item name="android:colorPrimary">@color/primary</item> <item name="android:colorPrimaryDark">@color/primary_dark</item> <item name="android:colorAccent">@color/accent</item> </style> </resources>

对应的 colors.xml 定义了配色(主色#3f51b5、深主色#1a237e、强调色#ffee58)。在 Material 主题下,RadioButton会自动采用符合 Material 规范的选择动画与强调色渲染,圆点选中时呈现colorAccent着色效果。

6.2 清单差异

BasicMaterial 版 Manifest 将minSdkVersion/targetSdkVersion提升到21,并在<application>上声明android:theme="@style/AppTheme"。两版对比可归纳为:

维度Basic/RadioButtonBasicMaterial/RadioButton
主题系统默认(Holoe 前身风格)Theme.Material
minSdk421(Material 主题的最低要求)
布局同一份RadioGroup+ 三个RadioButton完全相同
视觉旧式圆点Material 动画与强调色

由此可见:单选组件的交互逻辑与布局结构不随主题变化,主题只改变其外观渲染;需要 Material 风格时,只需按上述方式换主题并提升 minSdk 即可。


七、总结与延伸

通过 Basic/RadioButton 这一示例,可以完整掌握 Android 单选组件的核心用法:

  1. 布局:RadioGroup(纵向/横向排列)内嵌多个RadioButton,容器自动维护单选互斥;
  2. 资源:文案抽离到strings.xml,便于本地化与维护;
  3. 入口:Activity 仅需setContentView(R.layout.main)即可渲染;
  4. 监听:借助RadioGroup.OnCheckedChangeListener获取选中项 id,或复用CompoundButton.OnCheckedChangeListener监听单按钮状态;
  5. 主题升级:切换到Theme.Material(minSdk 21)即可获得现代化视觉,布局代码无需改动。

若需继续深入,可在仓库中对照 Basic/CheckBox(多选场景)、BasicMaterial/RadioButton(Material 风格)以及 Selection 目录下的选择类控件示例,形成对"选择控件族"的系统认知。

  • 示例工程
  • 教程

【免费下载链接】cw-omnibus

Source code to omnibus edition of _The Busy Coder's Guide to Android Development_

项目地址:https://gitcode.com/gh_mirrors/cw/cw-omnibus
点击查看免费下载
上一篇:ThinkJS 3.x 生态组件全景解析:think-awesome 中间件、适配器与扩展实战指南
下一篇:破解三元比特流:Ternary-Bonsai-2-27B-mlx-2bit的PTQ1_0/PQ2_0到MLX 2-bit无损转码算法详解

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询