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

Android中点击Button如何切换绑定的Drawable图标?

Android Button点击切换图标与文本的实现方案

问题描述

在CardLayout中有一个「save」按钮,用户点击后将内容保存至另一个Fragment,同时需要切换按钮的「heart」Drawable图标和文本。目前已实现文本切换,但不清楚如何切换图标。

现有代码

Kotlin点击事件代码

binding.saves.setOnClickListener {
    val exist = dbHandler.getTask(task.id)
    if(exist) {
        Toast.makeText(itemView.context, "Activity removed", Toast.LENGTH_SHORT)
            .show()
        binding.saves.text ="Save"
        dbHandler.deleteFavorite(task);
    }else{
        Toast.makeText(itemView.context, "Activity added", Toast.LENGTH_SHORT)
            .show()
        dbHandler.addFavorite(task);
        binding.saves.text ="Saved"
    }
}

XML布局代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="0dp"
    app:cardBackgroundColor="@color/white"
    app:cardCornerRadius="0dp"
    app:cardElevation="0dp"
    app:cardMaxElevation="3dp"
    app:cardPreventCornerOverlap="true"
    app:cardUseCompatPadding="true"
    tools:context="ui.CardLayout">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/idActivityName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="14dp"
            android:layout_marginRight="10dp"
            android:text="@string/placeholdertasktitle"
            android:textColor="@color/black"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/idActivityDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/idActivityName"
            android:layout_marginStart="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginBottom="30dp"
            android:drawablePadding="2dp"
            android:text="@string/activitydescription"
            android:textColor="@color/black"
            android:textSize="15sp"
            tools:ignore="UnknownId" />

        <View
            android:id="@+id/divider"
            android:layout_width="380dp"
            android:layout_height="2dp"
            android:layout_below="@id/idActivityDescription"
            android:layout_alignStart="@id/idActivityName"
            android:background="#EDEDED" />

        <LinearLayout
            android:id="@+id/linLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/divider"
            android:layout_alignStart="@+id/divider"
            android:layout_alignEnd="@+id/divider"
            android:gravity="center"
            android:orientation="horizontal">

            <Button
                android:id="@+id/saves"
                style="@style/cardbutton"
                android:layout_width="110dp"
                android:layout_height="wrap_content"
                android:background="@drawable/cardbutton"
                android:contentDescription="@string/saves"
                android:stateListAnimator="@null"
                android:text="@string/save"
                android:textAlignment="center"
                android:textColor="#595959"
                android:textSize="12sp"
                app:icon="@drawable/ic_saves_blank"
                app:iconGravity="start"
                app:iconTint="#595959" />

            <Button
                android:id="@+id/calendar"
                style="@style/cardbutton"
                android:layout_width="110dp"
                android:layout_height="wrap_content"
                android:background="@drawable/cardbutton"
                android:contentDescription="@string/saves"
                android:stateListAnimator="@null"
                android:text="@string/calendar"
                android:textAlignment="center"
                android:textColor="#595959"
                android:textSize="12sp"
                app:icon="@drawable/ic_calendar"
                app:iconTint="#595959"
                app:iconGravity="start"/>

            <Button
                android:id="@+id/copyactivity"
                style="@style/cardbutton"
                android:layout_width="110dp"
                android:layout_height="wrap_content"
                android:background="@drawable/cardbutton"
                android:contentDescription="@string/saves"
                android:stateListAnimator="@null"
                android:text="@string/copy"
                android:textAlignment="center"
                android:textColor="#595959"
                android:textSize="12sp"
                app:icon="@drawable/ic_copytext"
                app:iconGravity="start"
                app:iconTint="#595959" />
        </LinearLayout>

    </RelativeLayout>
</androidx.cardview.widget.CardView>

已尝试方法

  • 尝试用binding.saves.image ="drawable1"这类方式,但不清楚正确的切换方法
  • 考虑将Button改为ImageButton并使用selected状态属性

需求疑问

是否需要将Button替换为ImageButton?能否通过Binding直接切换图标同时保留文本?


解决方案

不需要替换为ImageButton,你当前使用的是Material Button(从app:icon属性可判断),它本身支持图标与文本共存,直接通过Binding即可切换图标,有两种实现方式:

方式1:直接在代码中切换图标资源

在切换文本的同时,调用setIconResource()方法切换图标:

binding.saves.setOnClickListener {
    val exist = dbHandler.getTask(task.id)
    if(exist) {
        Toast.makeText(itemView.context, "Activity removed", Toast.LENGTH_SHORT).show()
        binding.saves.text = "Save"
        // 切换为空白心形图标
        binding.saves.setIconResource(R.drawable.ic_saves_blank)
        dbHandler.deleteFavorite(task)
    }else{
        Toast.makeText(itemView.context, "Activity added", Toast.LENGTH_SHORT).show()
        binding.saves.text = "Saved"
        // 切换为填充心形图标
        binding.saves.setIconResource(R.drawable.ic_saves_filled)
        dbHandler.addFavorite(task)
    }
}

如果需要同时切换图标颜色,可搭配iconTint:

// 示例:切换为红色填充图标
binding.saves.iconTint = ContextCompat.getColorStateList(itemView.context, R.color.red)

方式2:使用StateListDrawable自动切换(更简洁)

通过定义状态选择器Drawable,让系统根据按钮的selected状态自动切换图标,无需手动调用图标切换方法:

  1. 创建drawable/ic_saves_selector.xml状态选择器:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 选中状态显示填充心形 -->
    <item android:drawable="@drawable/ic_saves_filled" android:state_selected="true"/>
    <!-- 默认状态显示空白心形 -->
    <item android:drawable="@drawable/ic_saves_blank"/>
</selector>
  1. 修改XML中按钮的app:icon属性:
<Button
    android:id="@+id/saves"
    ...
    app:icon="@drawable/ic_saves_selector"
    ... />
  1. 在代码中切换按钮的selected状态即可联动图标与文本:
binding.saves.setOnClickListener {
    val exist = dbHandler.getTask(task.id)
    val isSelected = !exist
    binding.saves.isSelected = isSelected
    
    if(exist) {
        Toast.makeText(itemView.context, "Activity removed", Toast.LENGTH_SHORT).show()
        binding.saves.text = "Save"
        dbHandler.deleteFavorite(task)
    }else{
        Toast.makeText(itemView.context, "Activity added", Toast.LENGTH_SHORT).show()
        binding.saves.text = "Saved"
        dbHandler.addFavorite(task)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 08:09:18