使用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>
问题原因与修复步骤
核心问题
animated-selector无法直接为外部静态Drawable加动画:当前写法是引用外部独立的Vector Drawable,过渡动画无法穿透到外部资源的内部元素进行操作。- 错误嵌套
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
相关产品推荐
相关产品推荐

