You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Studio中实现单选按钮切换CardView UI及展开收起动画?

Android Studio实现两个UI交互需求的详细方案

嘿,这两个需求在Android日常开发里真的挺常用的,尤其是第二个类似Google Keep的提醒切换交互,我来给你一步步拆解实现方法,保证你能快速上手:


一、点击按钮修改CardView/Dialog的UI

1. 先搞定布局基础

先在XML里定义好CardView和触发按钮,如果是Dialog的话,还要准备自定义Dialog的布局:

<!-- activity_main.xml -->
<LinearLayout
    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"
    android:orientation="vertical"
    android:padding="16dp">

    <Button
        android:id="@+id/modifyCardBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改CardView样式"/>

    <androidx.cardview.widget.CardView
        android:id="@+id/myCard"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_marginTop="16dp"
        app:cardCornerRadius="8dp"
        app:cardElevation="4dp">

        <TextView
            android:id="@+id/cardText"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="初始状态的CardView"/>
    </androidx.cardview.widget.CardView>
</LinearLayout>

<!-- dialog_custom.xml(自定义Dialog布局) -->
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/dialogCard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="12dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">

        <TextView
            android:id="@+id/dialogText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="初始Dialog内容"/>
        <Button
            android:id="@+id/modifyDialogBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="修改Dialog样式"
            android:layout_marginTop="16dp"/>
    </LinearLayout>
</androidx.cardview.widget.CardView>

2. 编写点击修改逻辑

在Activity/Fragment里给按钮设置点击监听,直接修改UI属性就行,Dialog的话要先获取它的布局控件:

// MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 处理CardView的修改逻辑
        val modifyCardBtn = findViewById<Button>(R.id.modifyCardBtn)
        val myCard = findViewById<CardView>(R.id.myCard)
        val cardText = findViewById<TextView>(R.id.cardText)

        modifyCardBtn.setOnClickListener {
            // 修改CardView的圆角、阴影和背景色
            myCard.radius = 16f
            myCard.cardElevation = 8f
            myCard.setCardBackgroundColor(Color.parseColor("#E8F5E9"))
            // 修改文本内容
            cardText.text = "点击按钮后修改的CardView"
        }

        // 处理Dialog的修改逻辑
        val dialog = AlertDialog.Builder(this)
            .setView(R.layout.dialog_custom)
            .create()
        dialog.show()

        val dialogCard = dialog.findViewById<CardView>(R.id.dialogCard)
        val modifyDialogBtn = dialog.findViewById<Button>(R.id.modifyDialogBtn)
        val dialogText = dialog.findViewById<TextView>(R.id.dialogText)

        modifyDialogBtn?.setOnClickListener {
            dialogCard?.setCardBackgroundColor(Color.parseColor("#FFF3E0"))
            dialogText?.text = "修改后的Dialog内容"
        }
    }
}

二、单选按钮切换CardView内容+展开收起动画

这个需求和Google Keep的提醒功能逻辑完全一致,核心是监听单选按钮选中状态+用过渡动画实现平滑切换。

1. 布局设计:单选组+多内容CardView

把RadioGroup放在CardView上方,CardView内部嵌套多个不同的内容布局,初始只显示默认选项的内容:

<!-- activity_main.xml -->
<RadioGroup
    android:id="@+id/reminderOptionGroup"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_marginTop="16dp">

    <RadioButton
        android:id="@+id/dateOption"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="日期提醒"
        android:checked="true"/>

    <RadioButton
        android:id="@+id/timeOption"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="时间提醒"/>

    <RadioButton
        android:id="@+id/locationOption"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="位置提醒"/>
</RadioGroup>

<androidx.cardview.widget.CardView
    android:id="@+id/reminderCard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    app:cardCornerRadius="8dp">

    <!-- 日期提醒内容 -->
    <LinearLayout
        android:id="@+id/dateLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择提醒日期"/>
        <DatePicker
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <!-- 时间提醒内容 -->
    <LinearLayout
        android:id="@+id/timeLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:visibility="gone">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择提醒时间"/>
        <TimePicker
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <!-- 位置提醒内容 -->
    <LinearLayout
        android:id="@+id/locationLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp"
        android:visibility="gone">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择提醒位置"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="输入位置信息"/>
    </LinearLayout>
</androidx.cardview.widget.CardView>

2. 实现单选切换+平滑动画

用TransitionManager.beginDelayedTransition()来触发内容切换的动画,同时处理不同布局的显示隐藏:

// MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val optionGroup = findViewById<RadioGroup>(R.id.reminderOptionGroup)
        val dateLayout = findViewById<LinearLayout>(R.id.dateLayout)
        val timeLayout = findViewById<LinearLayout>(R.id.timeLayout)
        val locationLayout = findViewById<LinearLayout>(R.id.locationLayout)
        val reminderCard = findViewById<CardView>(R.id.reminderCard)

        // 单选按钮切换逻辑+动画
        optionGroup.setOnCheckedChangeListener { _, checkedId ->
            // 开启过渡动画,让内容切换更平滑
            TransitionManager.beginDelayedTransition(reminderCard)
            
            // 先隐藏所有布局
            dateLayout.visibility = View.GONE
            timeLayout.visibility = View.GONE
            locationLayout.visibility = View.GONE

            // 根据选中项显示对应布局
            when(checkedId) {
                R.id.dateOption -> dateLayout.visibility = View.VISIBLE
                R.id.timeOption -> timeLayout.visibility = View.VISIBLE
                R.id.locationOption -> locationLayout.visibility = View.VISIBLE
            }
        }

        // 额外实现CardView的展开/收起动画(点击CardView触发)
        var isExpanded = true
        reminderCard.setOnClickListener {
            TransitionManager.beginDelayedTransition(reminderCard)
            isExpanded = !isExpanded
            reminderCard.layoutParams.height = if (isExpanded) {
                ViewGroup.LayoutParams.WRAP_CONTENT
            } else {
                // 收起到固定高度
                100
            }
            reminderCard.requestLayout()
        }
    }
}

3. 进阶优化小技巧

  • 如果内容布局比较复杂,建议用ViewStub延迟加载,提升页面启动性能;
  • 可以自定义动画,比如用ObjectAnimator组合高度变化、透明度变化的动画效果;
  • 记得在onSaveInstanceState里保存当前选中的单选按钮ID,避免旋转屏幕后状态丢失。

内容的提问来源于stack exchange,提问作者Gaurav Ghongde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:26:05