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

使用AnimatedSelector实现Drawable状态切换动画失败求助

AnimatedSelector过渡动画未触发的问题排查与修复

我尝试使用animated-selector,通过修改path data在静态Drawable资源间切换,并添加弹跳动画实现按压状态变化效果,但过渡动画完全没有触发。


相关代码

布局组件代码

<androidx.appcompat.widget.AppCompatImageButton
    android:id="@+id/camera_capture_button"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:background="@drawable/ic_shutter"
    android:clickable="true"
    android:contentDescription="@string/camera__btn_capture"
    android:onClick="@{() -> viewModel.onCaptureClick()}"
    android:scaleType="fitCenter"
    app:layout_constraintTop_toTopOf="@id/bg_camera"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent" />

ic_shutter (animated-selector资源)

<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/state_pressed"
        android:drawable="@drawable/ic_shutter_pressed"
        android:state_pressed="true" />
    <item
        android:id="@+id/state_normal"
        android:drawable="@drawable/ic_shutter_normal"
        android:state_pressed="false" />

<transition
    android:fromId="@id/state_normal"
    android:toId="@id/state_pressed">
    <animation-list>
        <set>
            <item>
                <objectAnimator
                    android:duration="300"
                    android:interpolator="@android:interpolator/accelerate_decelerate"
                    android:propertyName="pathData"
                    android:valueFrom="M44,44.913m-34.089,0a34.089,34.089 0,1 1,68.177 0a34.089,34.089 0,1 1,-68.177 0"
                    android:valueTo="M44,44.913m-26.5,0a26.5,26.5 0,1 1,53 0a26.5,26.5 0,1 1,-53 0"
                    android:valueType="pathType" />
            </item>
        </set>
    </animation-list>
</transition>
</animated-selector>

对应的Vector Drawable资源

ic_shutter_pressed

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="88dp"
    android:height="89dp"
    android:viewportWidth="88"
    android:viewportHeight="89">

<path
      android:name="centerCircle"
      android:pathData="M44,44.913m-26.5,0a26.5,26.5 0,1 1,53 0a26.5,26.5 0,1 1,-53 0"
      android:strokeWidth="2"
      android:strokeColor="#ffffff">
    <aapt:attr name="android:fillColor">
      <gradient
          android:startX="26.54"
          android:startY="24.459"
          android:endX="61.46"
          android:endY="65.491"
          android:type="linear">
        <item android:offset="0" android:color="#FFD9DADB"/>
        <item android:offset="1" android:color="#FFFFFFFF"/>
      </gradient>
    </aapt:attr>
  </path>
</vector>

ic_shutter_normal

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="88dp"
    android:height="89dp"
    android:viewportWidth="88"
    android:viewportHeight="89">
  <path
      android:name="centerCircle"
      android:pathData="M44,44.913m-34.089,0a34.089,34.089 0,1 1,68.177 0a34.089,34.089 0,1 1,-68.177 0"
      android:strokeWidth="2"
      android:strokeColor="#ffffff">
    <aapt:attr name="android:fillColor">
      <gradient
          android:startX="21.721"
          android:startY="18.815"
          android:endX="66.278"
          android:endY="71.169"
          android:type="linear">
        <item android:offset="0" android:color="#FFD9DADB"/>
        <item android:offset="1" android:color="#FFFFFFFF"/>
      </gradient>
    </aapt:attr>
  </path>
</vector>

问题原因与修复步骤

核心问题

  1. animated-selector无法直接为外部静态Drawable加动画:当前写法是引用外部独立的Vector Drawable,过渡动画无法穿透到外部资源的内部元素进行操作。
  2. 错误嵌套animation-list容器:animation-list是逐帧动画的专用容器,和属性动画不兼容,过渡动画应直接使用objectAnimator或set标签。

修复方案

修改ic_shutter.xml,将Vector内容内嵌到animated-selector中,调整动画结构:

<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">

    <!-- 正常状态 -->
    <item android:id="@+id/state_normal" android:state_pressed="false">
        <vector android:width="88dp"
            android:height="89dp"
            android:viewportWidth="88"
            android:viewportHeight="89">
            <path
                android:name="centerCircle"
                android:pathData="M44,44.913m-34.089,0a34.089,34.089 0,1 1,68.177 0a34.089,34.089 0,1 1,-68.177 0"
                android:strokeWidth="2"
                android:strokeColor="#ffffff">
                <aapt:attr name="android:fillColor">
                    <gradient
                        android:startX="21.721"
                        android:startY="18.815"
                        android:endX="66.278"
                        android:endY="71.169"
                        android:type="linear">
                        <item android:offset="0" android:color="#FFD9DADB"/>
                        <item android:offset="1" android:color="#FFFFFFFF"/>
                    </gradient>
                </aapt:attr>
            </path>
        </vector>
    </item>

    <!-- 按压状态 -->
    <item android:id="@+id/state_pressed" android:state_pressed="true">
        <vector android:width="88dp"
            android:height="89dp"
            android:viewportWidth="88"
            android:viewportHeight="89">
            <path
                android:name="centerCircle"
                android:pathData="M44,44.913m-26.5,0a26.5,26.5 0,1 1,53 0a26.5,26.5 0,1 1,-53 0"
                android:strokeWidth="2"
                android:strokeColor="#ffffff">
                <aapt:attr name="android:fillColor">
                    <gradient
                        android:startX="26.54"
                        android:startY="24.459"
                        android:endX="61.46"
                        android:endY="65.491"
                        android:type="linear">
                        <item android:offset="0" android:color="#FFD9DADB"/>
                        <item android:offset="1" android:color="#FFFFFFFF"/>
                    </gradient>
                </aapt:attr>
            </path>
        </vector>
    </item>

    <!-- 正常 -> 按压过渡动画 -->
    <transition android:fromId="@id/state_normal" android:toId="@id/state_pressed">
        <set>
            <objectAnimator
                android:duration="300"
                android:interpolator="@android:interpolator/accelerate_decelerate"
                android:propertyName="pathData"
                android:valueFrom="M44,44.913m-34.089,0a34.089,34.089 0,1 1,68.177 0a34.089,34.089 0,1 1,-68.177 0"
                android:valueTo="M44,44.913m-26.5,0a26.5,26.5 0,1 1,53 0a26.5,26.5 0,1 1,-53 0"
                android:valueType="pathType"
                android:targetName="centerCircle"/>
        </set>
    </transition>

    <!-- 按压 -> 正常过渡动画 -->
    <transition android:fromId="@id/state_pressed" android:toId="@id/state_normal">
        <set>
            <objectAnimator
                android:duration="300"
                android:interpolator="@android:interpolator/accelerate_decelerate"
                android:propertyName="pathData"
                android:valueFrom="M44,44.913m-26.5,0a26.5,26.5 0,1 1,53 0a26.5,26.5 0,1 1,-53 0"
                android:valueTo="M44,44.913m-34.089,0a34.089,34.089 0,1 1,68.177 0a34.089,34.089 0,1 1,-68.177 0"
                android:valueType="pathType"
                android:targetName="centerCircle"/>
        </set>
    </transition>
</animated-selector>

关键修改点

  • 将Vector Drawable内容直接内嵌到animated-selector的<item>中,让动画能直接操作内部path元素。
  • 移除过渡动画中的animation-list容器,直接用<set>包裹objectAnimator。
  • 添加android:targetName="centerCircle",明确指定动画作用的path元素名称,确保动画能找到目标属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:59:55