res/drawable/
目录中,XML 文件包含一个
元素(用作根节点)和一系列子
节点(每个节点定义一个帧)。 <!--android:oneshot="true"表示是否循环播放,true表示只播放一次。-->
<!--android:duration="200"表示这张图片动画播放的时长,单位ms。-->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">
<item android:drawable="@drawable/lockscreen_01" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_02" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_03" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_04" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_05" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_06" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_07" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_08" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_09" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_10" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_11" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_12" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_13" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_14" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_15" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_16" android:duration="200"/>
<item android:drawable="@drawable/lockscreen_17" android:duration="200"/>
</animation-list>
ImageView
中。特别要 注意 的是:AnimationDrawable
的start()
方法不能在Activity的onCreate()
方法中调用,因为AnimationDrawable
有可能在加载的时候还没有完全加载到Window上,所以最好的使用时机是onWindowFocusChanged()
方法中。 daiv.setBackgroundResource(R.drawable.drawable_animation);
animationDrawable = (AnimationDrawable) daiv.getBackground();
animationDrawable.start();
public void animationDrawable() {
//创建一个AnimationDrawable
AnimationDrawable animationDrawable1 = new AnimationDrawable();
//准备好资源图片
int[] ids = {R.drawable.lockscreen_01, R.drawable.lockscreen_02, R.drawable.lockscreen_03, R.drawable.lockscreen_04, R.drawable.lockscreen_05};
//通过for循环添加每一帧动画
for (int i = 0; i < ids.length; i++) {
Drawable frame = getResources().getDrawable(ids[i]);
//设定时长
animationDrawable1.addFrame(frame, 200);
}
animationDrawable1.setOneShot(false);
//将动画设置到背景上
daiv.setBackground(animationDrawable1);
//开启帧动画
animationDrawable1.start();
}
public class Frame extends android.support.v7.widget.AppCompatImageView {
private AnimationDrawable anim;
public Frame(Context context) {
super(context);
}
public Frame(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Frame(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setAnim(AnimationDrawable anim) {
this.anim = anim;
}
public void setLocation(int top, int left) {
this.setFrame(left, top, left + 200, top + 200);
}
@Override
protected void onDraw(Canvas canvas) {
try {
Field mCurFrame = AnimationDrawable.class.getDeclaredField("mCurFrame");
mCurFrame.setAccessible(true);
int frameInt = mCurFrame.getInt(anim);
if (frameInt == anim.getNumberOfFrames() - 1) {
setVisibility(INVISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
}
super.onDraw(canvas);
}
}
FrameLayout frameLayout = new FrameLayout(this);
setContentView(frameLayout);
final Frame frame = new Frame(this);
frame.setBackgroundResource(R.drawable.drawable_animation);//animation-list
frame.setVisibility(View.INVISIBLE);
final AnimationDrawable anim = (AnimationDrawable) frame.getBackground();
frame.setAnim(anim);
frameLayout.addView(frame);
frameLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//设置按下才产生动画效果
if (event.getAction() == MotionEvent.ACTION_DOWN) {
anim.stop();
float x = event.getX();
float y = event.getY();
frame.setLocation((int) y - 40, (int) x - 20);
frame.setVisibility(View.VISIBLE);
anim.start();
}
return false;
}
});
AnimatedVectorDrawable
类(以及用于实现向后兼容的 AnimatedVectorDrawableCompat
),您可以为矢量图添加动画效果,例如旋转或更改路径数据以将其变为其他图片。不过在学习AnimatedVectorDrawable
之前,我们有必要从VectorDrawable
(矢量图)开始,因为熟悉了矢量图,才可以添加动画。VectorDrawable
是一种矢量图形,在 XML 文件中定义为一组点、线条和曲线及其相关颜色信息。使用矢量图的主要优势在于图片可缩放。您可以在不降低显示质量的情况下缩放图片,也就是说,可以针对不同的屏幕密度调整同一文件的大小,而不会降低图片质量。这不仅能缩减 APK 文件大小,还能减少开发者维护工作。您还可以对动画使用矢量图片,具体方法是针对各种显示屏分辨率使用多个 XML 文件,而不是多张图片。<vector android:height="24dp" android:tint="#FF0006"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M 0,0 L50,100 L100,0Z"/>
vector>
看到这个是不是直接很懵逼, android:viewportHeight
定义矢量图视图的高度,视图就是矢量图path路径数据所绘制的虚拟画布。android:viewportWidth
定义矢量图视图的宽度。画布宽高均为24,意味着绘制了一个24*24的画布,path路径必须在这个画布大小里去绘制,超出画布就不显示了。android:fillColor
定义填充路径的颜色,如果没有定义则不填充路径。最难理解的就是android:pathData
,它的值是一系列字母和数字,为了告诉解析器如何绘制的,这些字母代表一些指令,具体如下:
每一个指令都有大小写,大写表示绝对定位,小写表示相对定位(相对定位参考点是上一次坐标)。 由于绘制路径的复杂性,因此强烈建议您使用 SVG 编辑器来创建复杂的图形。
android:pathData="M 0,0 L50,100 L100,0Z"
表示坐标(0,0)lineto(50,100)lineto(100,0)关闭,绘制出来是一个等腰三角形。
<vector>
<!--<group>用来把多个<path>组合在一起,进行相同的处理。-->
<group>
<path>
<path>
</group>
</vector>
——关于VectorDrawable的介绍就到这里!
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportHeight="100"
android:viewportWidth="100">
<group
android:name="group">
<path android:name="tangle"
android:strokeColor="@color/colorAccent"
android:strokeWidth="2"
android:pathData="M 0,0 L50,100 L100,0Z"/>
group>
vector>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vector_drawable">
<target
android:animation="@anim/anim_vector"
android:name="tangle"/>
<target
android:animation="@anim/anim_group"
android:name="group"/>
animated-vector>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="5000"
android:propertyName="scaleX"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:valueFrom="1"
android:valueTo="0.5"
android:valueType="floatType" />
set>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="2000"
android:propertyName="pathData"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:valueFrom="M 0,0 L50,100 L100,0Z"
android:valueTo="M 0,100 L50,0 L100,100Z"
android:valueType="pathType" />
set>
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
AnimatedVectorDrawable animatedVectorDrawable = (AnimatedVectorDrawable) vectoriv.getDrawable();
animatedVectorDrawable.start();
}
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="100"
android:viewportHeight="100">
<group android:name="group">
<path
android:name="tangle"
android:strokeWidth="2"
android:pathData="M 0,0 L50,100 L100,0Z"
android:strokeColor="@color/colorAccent" />
group>
vector>
aapt:attr>
<target android:name="tangle">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="2000"
android:propertyName="pathData"