如何在Xamarin.Android中通过ObjectAnimator代码实现基于PathData的动画?
在Xamarin.Android中用ObjectAnimator结合PathData实现动画
我来帮你搞定Xamarin.Android里用ObjectAnimator结合PathData做动画的事儿,之前你用XML实现的逻辑,转成代码其实只需这几步:
1. 准备VectorDrawable资源
首先确保你的VectorDrawable(比如Resources/drawable/ic_animated_vector.xml)里包含需要动画的Path元素,给它设置android:name方便后续获取:
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> <path android:name="animatedPath" android:pathData="M -7,-7 l 14,0 c 0,0 0,0 0,0 l 0,14 c 0,0 0,0 0,0 l -14,0 c 0,0 0,0 0,0 l 0,-14 c 0,0 0,0 0,0 Z" android:fillColor="#FF0000"/> </vector>
2. 创建自定义PathData属性
Android的Path类没有直接的setPathData方法,我们得自定义一个Property来处理PathData字符串到Path对象的转换:
using Android.Animation; using Android.Graphics; public class PathDataProperty : Property<Path, string> { private static PathDataProperty _instance; private PathDataProperty() : base(typeof(string), "pathData") { } // 单例模式避免重复创建 public static PathDataProperty Instance => _instance ??= new PathDataProperty(); public override string Get(Path objectValue) { // 动画中不需要获取当前PathData,返回null即可 return null; } public override void Set(Path objectValue, string value) { if (string.IsNullOrEmpty(value)) return; objectValue.Reset(); // 将PathData字符串解析为Path并填充 PathParser.CreatePathFromPathData(value).FillPath(objectValue); } }
3. 编写动画核心代码
在Activity/Fragment中,获取控件、VectorDrawable和目标Path,然后创建并启动ObjectAnimator:
using AndroidX.AppCompat.Widget; using AndroidX.Graphics.Drawables; using Android.Animation; // 获取显示动画的ImageView var imageView = FindViewById<AppCompatImageView>(Resource.Id.animatedImageView); // 创建兼容低版本的VectorDrawable实例 var vectorDrawable = VectorDrawableCompat.Create(Resources, Resource.Drawable.ic_animated_vector, null); imageView.SetImageDrawable(vectorDrawable); // 获取VectorDrawable中需要动画的Path var targetPath = vectorDrawable.GetPathByName("animatedPath"); if (targetPath == null) return; // 定义动画的起始和目标PathData(你提供的两段路径) var initialPathData = "M -7,-7 l 14,0 c 0,0 0,0 0,0 l 0,14 c 0,0 0,0 0,0 l -14,0 c 0,0 0,0 0,0 l 0,-14 c 0,0 0,0 0,0 Z"; var targetPathData = "M 7,-9 c 0,0 -14,0 -14,0 c -1.1044921875,0 -2,0.8955078125 -2,2 c 0,0 0,14 0,14 c 0,1.1044921875 0.8955078125,2 2,2 c 0,0 14,0 14,0 c 1.1044921875,0 2,-0.8955078125 2,-2 c 0,0 0,-14 0,-14 c 0,-1.1044921875 -0.8955078125,-2 -2,-2 Z"; // 创建ObjectAnimator,指定目标对象、自定义属性、插值器和路径值 var pathAnimator = ObjectAnimator.OfObject( targetPath, PathDataProperty.Instance, new PathEvaluator(), // 实现路径间的平滑过渡插值 initialPathData, targetPathData ); // 设置动画时长,和你XML里的166ms一致 pathAnimator.Duration = 166; // 添加更新监听,动画每一帧都刷新控件,否则看不到变化 pathAnimator.AddUpdateListener(new AnimatorUpdateListener(anim => { vectorDrawable.InvalidateSelf(); imageView.Invalidate(); })); // 启动动画 pathAnimator.Start();
辅助类:AnimatorUpdateListener
因为Xamarin需要实现Java接口,我们做个简单的包装类:
public class AnimatorUpdateListener : Java.Lang.Object, IAnimatorUpdateListener { private readonly Action<Animator> _onUpdate; public AnimatorUpdateListener(Action<Animator> onUpdate) { _onUpdate = onUpdate; } public void OnAnimationUpdate(ValueAnimator animation) { _onUpdate?.Invoke(animation); } }
关键注意事项
- 依赖AndroidX:
PathParser和VectorDrawableCompat需要AndroidX库支持,确保你的项目已经引用了Xamarin.AndroidX相关包。 - 路径插值:必须用
PathEvaluator处理路径过渡,不然动画会很生硬。 - 强制刷新:动画更新时一定要调用
InvalidateSelf()和Invalidate()触发视图重绘,否则动画不会显示。
内容的提问来源于stack exchange,提问作者yoganathan k
相关产品推荐
相关产品推荐

