Android animation 动画背景图自动播放的实现
- 格式:docx
- 大小:16.73 KB
- 文档页数:3
Android实现可播放GIF动画的ImageViewAndroid的原⽣控件并不⽀持播放GIF格式的图⽚。
我们都知道,在Android中如果想要显⽰⼀张图⽚,可以借助ImageView来完成,但是如果将⼀张GIF图⽚设置到ImageView⾥,它只会显⽰这张图⽚的第⼀帧,不会产⽣任何的动画效果。
今天我们来编写⼀个⾃定义的增强型ImageView(继承ImageView),可以播放GIF格式的图⽚,暂且叫做GifImageView吧。
1.⾃定义属性<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="GifImageView"><attr name="auto_play" format="boolean"></attr></declare-styleable></resources>2.⾃定义View中获取属性值private Movie mMovie;//播放动画需要⽤到的,系统类private int mImageWidth;//动画的imageview的宽度private int mImageHeight;//动画imageview的⾼度private long mMovieStart = 0;// 播放开始private boolean isAutoPlay;//是否⾃动播放private Bitmap mStartPlay;//开始按钮private boolean isPlaying=false;//记录是否正在播放private float mScale;//图⽚的缩放⽐private int mMeasuredGifWidth;//缩放后图⽚宽private int mMeasuredGifHeight;//缩放后图⽚⾼...private void init(Context context, AttributeSet attrs) {TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.GifImageView);// 通过反射拿布局中src的资源id,所以gif⽂件需要放在布局的src中int resourceId = getResourceId(attributes, context, attrs);if (resourceId != 0) {// 说明是gif动画// 1.将resourcesId变成流// 2.⽤Move来decode解析流// 3.获得bitmap的长宽InputStream is = getResources().openRawResource(resourceId);mMovie = Movie.decodeStream(is);if (mMovie != null) {Bitmap bitmap = BitmapFactory.decodeStream(is);mImageWidth = bitmap.getWidth();mImageHeight = bitmap.getHeight();// ⽤完释放bitmap.recycle();// 获得是否允许⾃动播放,如果不允许⾃动播放,则初始化播放按钮isAutoPlay = attributes.getBoolean(R.styleable.GifImageView_auto_play, false);if (!isAutoPlay) {mStartPlay = BitmapFactory.decodeResource(getResources(),R.drawable.start_play);setOnClickListener(this);}}}//回收资源attributes.recycle();}/*** 通过反射拿布局中src的资源id** @param attrs* @param context* @param attributes*/private int getResourceId(TypedArray attributes, Context context, AttributeSet attrs) {try {Field filed = TypedArray.class.getDeclaredField("mValue");filed.setAccessible(true);TypedValue typeValue = (TypedValue) filed.get(attributes);return typeValue.resourceId;} catch (Exception e) {e.printStackTrace();return 0;}3.重写onMesure()@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (mMovie != null) {/** Calculate horizontal scaling*/float scaleW = 1f;int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);if (measureModeWidth != MeasureSpec.UNSPECIFIED) {int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);scaleW = (float) mImageWidth / (float) maximumWidth;}/** calculate vertical scaling*/float scaleH = 1f;int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec); if (measureModeHeight != MeasureSpec.UNSPECIFIED) {int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);scaleH = (float) mImageHeight / (float) maximumHeight;}/** calculate overall scale*/mScale = 1f / Math.max(scaleH, scaleW);mMeasuredGifWidth = (int) (mImageWidth * mScale);mMeasuredGifHeight = (int) (mImageHeight * mScale);setMeasuredDimension(mMeasuredGifWidth, mMeasuredGifHeight);}}4.重写onDraw()@Overrideprotected void onDraw(Canvas canvas) {if (mMovie == null) {// mMovie等于null,说明是张普通的图⽚,则直接调⽤⽗类的onDraw()⽅法 super.onDraw(canvas);} else {// mMovie不等于null,说明是张GIF图⽚if (isAutoPlay) {// 如果允许⾃动播放,就播放playMovie(canvas);invalidate();} else {// 不允许⾃动播放的话// 1.判断是否正在播放// 2.获得第⼀帧的图像// 3.然后添加播放按钮if (isPlaying) {// 如果正在播放就playmoive继续播放if (playMovie(canvas)) {isPlaying = false;}invalidate();} else {// 第⼀帧mMovie.setTime(0);canvas.save(Canvas.MATRIX_SAVE_FLAG);canvas.scale(mScale, mScale);mMovie.draw(canvas, 0, 0);// 画canvas.restore();// 绘制开始按钮int offsetW = (mMeasuredGifWidth - mStartPlay.getWidth()) / 2;int offsetH = (mMeasuredGifHeight - mStartPlay.getHeight()) / 2;canvas.drawBitmap(mStartPlay, offsetW, offsetH, null);}}/*** 播放gif动画** @param canvas*/private boolean playMovie(Canvas canvas) {// 1.获取播放的时间// 2.如果开始start=0,则认为是开始// 3.记录播放的时间// 4.设置进度// 5.画动画// 6.如果时间⼤于了播放的时间,则证明结束long now = SystemClock.uptimeMillis();if (mMovieStart == 0) {mMovieStart = now;}int duration = mMovie.duration();if (duration == 0) {duration = 1000;}//记录gif播放了多少时间int relTime = (int) ((now - mMovieStart) % duration);mMovie.setTime(relTime);// 设置时间canvas.save(Canvas.MATRIX_SAVE_FLAG);canvas.scale(mScale, mScale);mMovie.draw(canvas, 0, 0);// 画canvas.restore();if ((now - mMovieStart) >= duration) {// 结束mMovieStart = 0;return true;}return false;}5.添加点击事件@Overridepublic void onClick(View v) {if(v.getId()==getId()){isPlaying=true;invalidate();}}还有⼀点需要注意,有些4.0以上系统的⼿机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest.xml中去禁⽤硬件加速功能,可以通过指定android:hardwareAccelerated=false来完成。
Android自定义下拉刷新动画--仿百度外卖下拉刷新动画我们先来看看Android中的动画吧:Android中的动画分为三种:Tween动画,这一类的动画提供了旋转、平移、缩放等效果。
Alpha –淡入淡出Scale –缩放效果Roate –旋转效果Translate –平移效果Frame动画(帧动画),这一类动画可以创建一个Drawable序列,按照指定时间间歇一个一个显示出来。
Property动画(属性动画),Android3.0之后引入出来的属性动画,它更改的是对象的实际属性。
分析我们可以看到百度外卖的下拉刷新的头是一个骑车的快递员在路上疾行,分析一下我们得到下面的动画:背景图片的平移动画太阳的自旋转动画两个小轮子的自旋转动画这就很简单了,接下来我们去百度外面的图片资源文件里找到这几张图片:(下载百度外卖的apk直接解压即可)<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><ImageViewandroid:id="@+id/iv_back1"android:src="@drawable/pull_back"android:layout_width="match_parent"android:layout_height="100dp" /><ImageViewandroid:id="@+id/iv_back2"android:src="@drawable/pull_back"android:layout_width="match_parent"android:layout_height="100dp" /><RelativeLayoutandroid:id="@+id/main"android:layout_centerHorizontal="true"android:layout_width="wrap_content"android:layout_height="wrap_content"><ImageViewandroid:layout_marginTop="45dp"android:id="@+id/iv_rider"android:background="@drawable/pull_rider"android:layout_width="50dp"android:layout_height="50dp" /><ImageViewandroid:id="@+id/wheel1"android:layout_marginLeft="10dp"android:layout_marginTop="90dp"android:background="@drawable/pull_wheel"android:layout_width="15dp"android:layout_height="15dp" /><ImageViewandroid:id="@+id/wheel2"android:layout_marginLeft="40dp"android:layout_marginTop="90dp"android:background="@drawable/pull_wheel"android:layout_width="15dp"android:layout_height="15dp" /></RelativeLayout><ImageViewandroid:id="@+id/ivsun"android:layout_marginTop="20dp"android:layout_toRightOf="@+id/main"android:background="@drawable/pull_sun"android:layout_width="30dp"android:layout_height="30dp" /></RelativeLayout>接下来我们定义动画效果:背景图片的平移效果:实现两个animation xml文件,一个起始位置在100%,结束位置在0%,设置repeat属性为循环往复。
移动应用开发技术中常见的界面动画和效果实现方法移动应用的界面动画和效果对于提升用户体验以及吸引用户的注意力起着关键作用。
在这篇文章中,我们将探讨一些常见的移动应用开发技术中用于实现界面动画和效果的方法。
一、逐帧动画逐帧动画是指通过在一段时间内显示多个静态图片的方式来呈现连续变化的动画效果。
在移动应用开发中,可以使用逐帧动画来实现一些简单的动态效果,如循环播放的loading动画或者帧动画。
开发者可以通过使用帧动画资源文件或者代码来实现逐帧动画效果。
二、属性动画属性动画是Android平台中一种常用的动画实现方法。
属性动画可以对任意对象的属性进行动画效果的改变,并且提供了平滑的过渡效果。
开发者可以使用属性动画来实现一些复杂的交互动画,比如平移、旋转、缩放等。
通过在代码中定义动画的属性、开始值和结束值,以及动画的时长等参数,可以实现各种各样的动画效果。
三、过渡动画过渡动画是指在界面切换的过程中,通过添加一些过渡效果,让用户感受到页面之间的流畅性和连贯性。
在移动应用开发中,可以使用过渡动画来实现页面的切换效果,比如淡入淡出、滑动、翻页等效果。
Android平台提供了一些过渡动画的内置效果,同时也可以通过自定义动画来实现更加个性化的过渡效果。
四、补间动画补间动画是指通过对控件的属性进行渐变、位移、旋转、缩放等操作,从而实现动画效果的方法。
在移动应用开发中,可以使用补间动画来给控件添加一些简单的动画效果,比如渐变透明度、平移、旋转、缩放等。
开发者可以通过XML布局文件或者代码来定义补间动画,然后将其应用到对应的控件上。
五、物理引擎物理引擎是一种通过模拟物体在现实世界中受到的物理规律,从而实现真实、复杂动画效果的方法。
在移动应用开发中,可以使用物理引擎来实现一些真实、有趣的物理效果,比如重力、碰撞、摩擦等。
Android平台提供了一些物理引擎的库,比如Box2D,可以帮助开发者轻松地实现各种物理效果。
六、视差滚动视差滚动是一种通过改变页面中不同图层之间的滚动速度,从而营造出立体效果的方法。
Android动画机制与使⽤技巧动画效果⼀直是⼈机交互中⾮常重要的部分,与死板、突兀的显⽰效果不同,动画效果的加⼊,让交互变得更加友好,特别是在提⽰、引导类的场景中,合理地使⽤动画能让⽤户获得更加愉悦的使⽤体验⼀、Android View动画框架Animation框架定义了透明度、旋转、缩放、位移等⼏种常见的动画实现原理:每次绘制View时,ViewGroup中的drawChild函数获取该view的Animation的Transformation值,然后调⽤canvas.concat(transformToApply.getMatrix())通过矩阵运算完成帧动画,如果动画没有完成,就继续调⽤invalidate() 函数,启动下次绘制来驱动动画,从⽽完成整个动画的绘制。
⼆、帧动画帧动画就是⼀张张图⽚不同的切换,形成的动画效果。
⼀般⼿机的开机动画,应⽤的等待动画等都是帧动画,因为只需要⼏张图⽚轮播,极其节省资源,如果真的设计成动画,那么是很耗费资源的事。
在res⽬录下新建⼀个drawable⽂件夹并定义xml⽂件,⼦节点为 animation-list,在这⾥定义要显⽰的图⽚和每张图⽚的显⽰时长。
<animation-list xmlns:android="/apk/res/android"android:oneshot="false"><!-- false表⽰循环播放,true表⽰只播放⼀次 --><item android:drawable="@drawable/g1" android:duration="200" /><item android:drawable="@drawable/g2" android:duration="200" /><item android:drawable="@drawable/g3" android:duration="200" /><item android:drawable="@drawable/g4" android:duration="200" /><item android:drawable="@drawable/g5" android:duration="200" /><item android:drawable="@drawable/g6" android:duration="300" /><item android:drawable="@drawable/g7" android:duration="400" /><!-- 慢动作 --><item android:drawable="@drawable/g8" android:duration="500" /><item android:drawable="@drawable/g9" android:duration="200" /><item android:drawable="@drawable/g10" android:duration="200" /><item android:drawable="@drawable/g11" android:duration="200" /></animation-list>在屏幕上播放帧动画,需要布局⽂件有⼀个ImageView来显⽰动画图⽚public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);ImageView iv = (ImageView) findViewById(R.id.iv);//把动画⽂件设置为imageView的背景iv.setBackgroundResource(R.drawable.frameanimation);AnimationDrawable ad = (AnimationDrawable) iv.getBackground();//播放动画ad.start();}}三、补间动画(视图动画)组件由原始状态向终极状态转变时,为了让过渡更⾃然,⽽⾃动⽣成的动画叫做补间动画。
下面我们一起来看篇Android开发AnimationDrawable控制逐帧播放动画实现过程,希望文章对各位朋友带不一些帮助。
当我们点击按钮时,该图片会不停的旋转,当再次点击按钮时,会停止在当前的状态。
activity代码:代码如下package .chenzheng_java.animation;import android.app.Activity;import android.graphics.drawable.AnimationDrawable;import android.os.Bundle;import android.view.View;import android.widget.ImageView;/*** @description android中的逐帧动画.* 逐帧动画的原理很简单,跟电影的播放一样,一张张类似的图片不停的切换,当切换速度达到一定值时.* 我们的视觉就会出现残影,残影的出现保证了视觉上变化的连续性,这时候图片的切换看在我们眼中就跟真实的一样了。
* 想使用逐帧动画:* 第一步:需要在res/drawable文件夹下新建一个xml文件,该文件详细定义了动画播放时所用的图片、切换每张图片* 所用的时间、是否为连续播放等等。
(有些文章说,在res/anim文件夹下放置该文件,事实证明,会出错哦)* 第二步:在代码中,将该动画布局文件,赋值给特定的图片展示控件,如本例子中的ImageView。
* 第三步:通过imageView.getBackGround()获取相应的AnimationDrawable对象,然后通过该对象的方法进行控制动画* @author chenzheng_java*/public class Animation1Activity extends Activity {ImageView imageView ;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.animation1);imageView = (ImageView) findViewById(R.id.imageView_animation1); imageView.setBackgroundResource(R.drawable.animation1_drawable); }public void myClickHandler(View targetButton){// 获取AnimationDrawable对象AnimationDrawable animationDrawable = (AnimationDrawable)imageView.getBackground();// 动画是否正在运行if(animationDrawable.isRunning()){//停止动画播放animationDrawable.stop();}else{//开始或者继续动画播放animationDrawable.start();}}}animation1.xml文件:代码如下<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=""android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"><Button android:id="@+id/button_animation1" android:text="动画开始"android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="myClickHandler"></Button> <ImageView android:id="@+id/imageView_animation1"android:layout_width="fill_parent"android:layout_height="wrap_content" android:layout_weight="1"></ImageView></LinearLayout>存放动画文件的xml文件:代码如下<?xml version="1.0" encoding="utf-8"?><!--根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画根标签下,通过item标签对动画中的每一个图片进行声明android:duration 表示展示所用的该图片的时间长度--><animation-listxmlns:android="/apk/res/android"android:oneshot="false"><item android:drawable="@drawable/a1" android:duration="50"></item><item android:drawable="@drawable/a2" android:duration="50"></item><item android:drawable="@drawable/a3" android:duration="50"></item><item android:drawable="@drawable/a4" android:duration="50"></item><item android:drawable="@drawable/a5" android:duration="50"></item><item android:drawable="@drawable/a6" android:duration="50"></item></animation-list>除此之外:在AnimationDrawable中,我们还可以看到如下的几个重要方法:setOneShot(boolean flag) 和在配置文件中进行配置一样,可以设置动画是否播放一次,false为连续播放;addFrame (Drawable frame, int duration) 动态的添加一个图片进入该动画中.。
Android图片滚动,加入自动播放功能,使用自定义属性实现,霸气十足!大家好,记得上次我带着大家一起实现了一个类似与淘宝客户端中带有的图片滚动播放器的效果,但是在做完了之后,发现忘了加入图片自动播放的功能(或许是我有意忘记加的.....),结果图片只能通过手指滑动来播放。
于是今天我将再次带领大家,添加上之前遗漏的功能,让我们的图片播放器更加完善。
这次的程序开发将完全基于上一次的代码,如果有朋友还未看过上篇文章,请先阅读Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来。
既然是要加入自动播放的功能,那么就有一个非常重要的问题需要考虑。
如果当前已经滚动到了最后一张图片,应该怎么办?由于我们目前的实现方案是,所有的图片都按照布局文件里面定义的顺序横向排列,然后通过偏移第一个图片的leftMargin,来决定显示哪一张图片。
因此当图片滚动在最后一张时,我们可以让程序迅速地回滚到第一张图片,然后从头开始滚动。
这种效果和淘宝客户端是有一定差异的(淘宝并没有回滚机制,而是很自然地由最后一张图片滚动到第一张图片),我也研究过淘宝图片滚动器的实现方法,并不难实现。
但是由于我们是基于上次的代码进行开发的,方案上无法实现和淘宝客户端一样的效果,因此这里也就不追求和它完全一致了,各有风格也挺好的。
好了,现在开始实现功能,首先是打开SlidingSwitcherView,在里面加入一个新的AsyncTask,专门用于回滚到第一张图片:[java]view plaincopy1.class ScrollToFirstItemTask extends AsyncTask<Integer, Integer, Integer> {2.3.@Override4.protected Integer doInBackground(Integer... speed) {5.int leftMargin = firstItemParams.leftMargin;6.while (true) {7. leftMargin = leftMargin + speed[0];8.// 当leftMargin大于0时,说明已经滚动到了第一个元素,跳出循环9.if (leftMargin > 0) {10. leftMargin = 0;11.break;12. }13. publishProgress(leftMargin);14. sleep(20);15. }16.return leftMargin;17. }18.19.@Override20.protected void onProgressUpdate(Integer... leftMargin) {21. firstItemParams.leftMargin = leftMargin[0];22. firstItem.setLayoutParams(firstItemParams);23. }24.25.@Override26.protected void onPostExecute(Integer leftMargin) {27. firstItemParams.leftMargin = leftMargin;28. firstItem.setLayoutParams(firstItemParams);29. }30.31.}然后在SlidingSwitcherView里面加入一个新的方法:[java]view plaincopy1./**2. * 滚动到第一个元素。
Android Animation开机动画的优化使用bootanimation程序显示开机画面,如需修改开机画面,需要修改源码b)代码frameworks/base/cmds/bootanimation/*frameworks/base/core/res/assets/images/Android-logo*2)android 2.0及之后a)说明使用bootanimation程序显示开机画面,如需修改开机画面,不用修改代码,只需按格式要求做bootanimation.zip包,放在系统的 /system/media目录中,或/data/local目录中即可,两个目录下都存在时,优先使用/data/local下的b)代码frameworks/base/cmds/bootanimation/*frameworks/base/core/res/assets/images*/system/bin/bootanimation这个应该是启动第三屏动画控制的;做了几个步骤的实验:1. 正常重启,启动完成我的系统一般是110s左右;C8600就是慢啊;【这里我已经替换了典型的开机动画,/system/media下的zip文件我只放了2张图片进去】2.删除/system/media下的zip文件;重启;时间103s左右;【第二屏android文字过后,就是android字母依次亮的动画,一直到开机】3. 修改/init.rc文件,屏蔽下面这段代码;重启,时间95s;【没有感觉明显界面的变化,但是开机时间就是简短了】#service bootanim /system/bin/bootanimation# user graphics# group graphics# disabled# oneshot4. 删除/system/bin/bootanimation,重启,时间92s;【第二屏后就是黑屏;这个成绩不错,整整少了18s;保留这个配置】上面的这个执行,我看了看网上贴的boot部分的源码,是有根据的;源码大概逻辑是:1. 第二屏android文字后,将检查/system/media/下的zip,有就显示动画2. 没有的话,就显示android文字的动画;文字消耗资源少吧,所以这里有时间减少3. 把bootanimation文件删了后,没有服务去启动这个android文字动画了;速度又变快了;先爱折腾的人推荐这个方法;其实我的初衷是显示最早那种linux启动时显示文字输出的界面;结果把这个启动时间优化了;有兴趣的可以用附件的程序监控开机时间进行试验。
android animation用法
Android动画用法是指在Android平台上使用动画效果来提高应用程序的用户体验。
动画可以通过改变视图的属性值来实现,比如位置、大小、透明度、旋转角度等。
Android提供了几种不同类型的动画,包括Tween动画、帧动画、属性动画等。
Tween动画是基于补间动画的,可以通过指定起始和结束值来实现动画效果。
Tween动画有四种类型,分别是Alpha动画(改变视图的透明度)、Scale动画(改变视图的大小)、Translate动画(改变视图的位置)和Rotate动画(改变视图的旋转角度)。
帧动画是通过逐帧播放一组预定义的图像来实现动画效果的。
帧动画的每一帧都是一个静态的位图或Drawable对象,可以通过XML文件或Java代码来定义。
属性动画是一种可以改变视图任意属性值的动画,可以通过实现ValueAnimator类来自定义动画效果。
属性动画在API Level 11之后引入,可以使用ObjectAnimator和AnimatorSet来组合动画效果。
在Android开发中,动画可以应用于许多场景,比如用户交互、应用导航、数据加载等。
通过使用动画效果,可以增强应用程序的交互性和视觉吸引力,提高用户体验。
- 1 -。
android 动画的实现原理Android动画的实现原理是通过改变视图的属性值来创建视觉效果。
在Android中,动画可以通过三种方式实现:补间动画、帧动画和属性动画。
1. 补间动画:补间动画是指通过指定开始和结束状态,系统会自动完成状态之间的过渡动画。
常用的补间动画包括平移动画、缩放动画、旋转动画和淡入淡出动画。
补间动画是通过对目标视图的transform属性进行变换来实现的,通过对动画的属性值进行插值计算,系统会将中间状态渐变地应用到目标视图上,从而实现动画效果。
2. 帧动画:帧动画是指将连续的图片资源按照一定时间间隔依次播放,从而形成动画效果。
帧动画是通过逐帧显示不同的图片资源来实现的。
在Android中,帧动画可以通过逐个资源文件的方式创建,也可以通过在XML文件中定义动画资源实现。
3. 属性动画:属性动画是Android3.0引入的一种动画机制,相较于补间动画和帧动画,属性动画更加强大和灵活。
属性动画通过修改目标视图的属性值来实现动画效果。
在属性动画中,可以通过指定目标视图的属性名称和起始值以及结束值,系统会自动根据这些信息来计算出中间过渡值,并将其应用到目标视图上。
属性动画可以实现更加复杂和精细的动画效果,例如借助关键帧来定义关键状态,或者通过设置动画插值器来控制动画的速度曲线。
总的来说,Android动画的实现原理是通过改变视图的属性值来实现动画效果。
不同的动画类型有不同的实现方式,包括补间动画、帧动画和属性动画。
补间动画是通过对目标视图的属性进行变换来实现的,帧动画是逐帧显示不同的图片资源,而属性动画是通过修改目标视图的属性值来实现动画效果。
Rexsee API介绍:Animations动画学习笔记及源码在Android上实现动画,官方的SDK提供了Animations,并且介绍了两种不同模式,分别是:1. Tween Animation:通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果,即是一种渐变动画;2. Frame Animation:顺序播放事先做好的图像,是一种画面转换动画。
同时,Animation由四种类型组成:XML文件:· alpha 渐变透明度动画效果· scale 渐变尺寸伸缩动画效果· translate 画面转换位置移动动画效果· rotate 画面转移旋转动画效果在Java 源码中定义了相应的类,可以使用这些类的方法来获取和操作相应的属性:· AlphaAnimation 渐变透明度动画效果· ScaleAnimation 渐变尺寸伸缩动画效果· TranslateAnimation 画面转换位置移动动画效果· RotateAnimation 画面转移旋转动画效果具体Android的原生就不再多说了,相对复杂,有兴趣的可以直接去看google的SDK。
这里分享了Rexsee的API,基于对原生的封装,可以直接使用JS实现功能调用。
如:【事件】 void onAnimationStart(String id)【说明】当动画开始播放时触发。
在Rexsee社区可以直接查看源码。
同时,新上线的项目中心提供了在线开发服务,不需要单独准备服务器。
同时也有大量的应用以分享的方式开放供查阅,关于动画的具体应用源码也可以在这里查到:/project/Rexsee API:Animations源码Java代码1packagerexsee.core.animation;23importrexsee.core.style.StyleSheet;4importrexsee.core.utilities.RexseeUtilities;5importandroid.view.View;6importandroid.view.animation.AccelerateDecelerateInterpolator;7importandroid.view.animation.AccelerateInterpolator;8importandroid.view.animation.AlphaAnimation;9importandroid.view.animation.Animation;10importandroid.view.animation.AnimationSet;11importandroid.view.animation.AnticipateInterpolator;12importandroid.view.animation.AnticipateOvershootInterpolator;13importandroid.view.animation.BounceInterpolator;14importandroid.view.animation.CycleInterpolator;15importandroid.view.animation.DecelerateInterpolator;16importandroid.view.animation.Interpolator;17importandroid.view.animation.LinearInterpolator;18importandroid.view.animation.OvershootInterpolator;19importandroid.view.animation.RotateAnimation;20importandroid.view.animation.ScaleAnimation;21importandroid.view.animation.TranslateAnimation;2223publicclassAnimationsextendsAnimation{2425publicAnimations(){26super();27}2829publicstaticAnimationgetAnimation(StyleSheetstyle,AnimationListenerliste ner,Viewview,ViewviewParent){30if(view==null)returnnull;31if(viewParent==null){32try{33viewParent=(View)view.getParent();34}catch(Exceptione){35viewParent=view;36}37}38AnimationSetanimation=newAnimationSet(true);39String[]types=style.animation_type.split("\\+");40intlength=0;41animation.setDuration(Integer.parseInt(style.animation_rotate_duration)) ;42animation.setRepeatCount(Integer.parseInt(style.animation_rotate_repeat_ count));43animation.setRepeatMode(style.animation_rotate_repeat_mode.equalsIgnoreC ase("normal")?1:2);44animation.setStartOffset(RexseeUtilities.getLong(style.animation_rotate_ start_time,0));45animation.setInterpolator(getInterPolator(style.animation_rotate_interpo lator));46animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWidt h(),viewParent.getHeight());47}catch(Exceptione){48}49returnanimation;50}51publicstaticAnimationgetAlphaAnimation(StyleSheetstyle,Viewview,Viewview Parent){52Animationanimation=null;53try{54floatfrom=Float.parseFloat(style.animation_alpha_from.replaceAll("%","") )/100;55floatto=Float.parseFloat(style.animation_alpha_to.replaceAll("%",""))/10 0;56animation=newAlphaAnimation(from,to);57animation.setDuration(Integer.parseInt(style.animation_alpha_duration)); 58animation.setRepeatCount(Integer.parseInt(style.animation_alpha_repeat_c ount));59animation.setRepeatMode(style.animation_alpha_repeat_mode.equalsIgnoreCa se("normal")?1:2);60animation.setStartOffset(RexseeUtilities.getLong(style.animation_alpha_s tart_time,0));61animation.setInterpolator(getInterPolator(style.animation_alpha_interpol ator));62animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWidt h(),viewParent.getHeight());63}catch(Exceptione){64}65returnanimation;66}67publicstaticAnimationgetScaleAnimation(StyleSheetstyle,Viewview,Viewview Parent){68Animationanimation=null;69try{70floatscaleCenterX,scaleCenterY;71try{72scaleCenterX=Float.parseFloat(style.animation_scale_center_x.replaceAll( "%",""));73scaleCenterX=scaleCenterX/100;74if(scaleCenterX<0)scaleCenterX=0;75if(scaleCenterX>1)scaleCenterX=1;76}catch(Exceptione){77scaleCenterX=(float)0.5;78}79try{80scaleCenterY=Float.parseFloat(style.animation_scale_center_y.replaceAll( "%",""));81scaleCenterY=scaleCenterY/100;82if(scaleCenterY<0)scaleCenterY=0;83if(scaleCenterY>1)scaleCenterY=1;84}catch(Exceptione){85scaleCenterY=(float)0.5;86}87floatfromX=Float.parseFloat(style.animation_scale_x_from);88floattoX=Float.parseFloat(style.animation_scale_x_to);89floatfromY=Float.parseFloat(style.animation_scale_y_from);90floattoY=Float.parseFloat(style.animation_scale_y_to);91animation=newScaleAnimation(fromX,toX,fromY,toY,Animation.RELATIVE_TO_PA RENT,scaleCenterX,Animation.RELATIVE_TO_PARENT,scaleCenterY);92animation.setDuration(Integer.parseInt(style.animation_scale_duration)); 93animation.setRepeatCount(Integer.parseInt(style.animation_scale_repeat_c ount));94animation.setRepeatMode(style.animation_scale_repeat_mode.equalsIgnoreCa se("normal")?1:2);95animation.setStartOffset(RexseeUtilities.getLong(style.animation_scale_s tart_time,0));96animation.setInterpolator(getInterPolator(style.animation_scale_interpol ator));97animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWidt h(),viewParent.getHeight());98}catch(Exceptione){99}100returnanimation;101}102publicstaticAnimationgetTranslateAnimation(StyleSheetstyle,Viewview,Vie wviewParent){103Animationanimation=null;104try{105floatfromX=Float.parseFloat(style.animation_translate_x_from);106floattoX=Float.parseFloat(style.animation_translate_x_to);107floatfromY=Float.parseFloat(style.animation_translate_y_from);108floattoY=Float.parseFloat(style.animation_translate_y_to);109fromX=fromX/100;110toX=toX/100;111fromY=fromY/100;112toY=toY/100;113animation=newTranslateAnimation(Animation.RELATIVE_TO_PARENT,fromX,Anim ation.RELATIVE_TO_PARENT,toX,Animation.RELATIVE_TO_PARENT,fromY,Animation.R ELATIVE_TO_PARENT,toY);114animation.setDuration(Integer.parseInt(style.animation_translate_durati on));115animation.setRepeatCount(Integer.parseInt(style.animation_translate_rep eat_count));116animation.setRepeatMode(style.animation_translate_repeat_mode.equalsIgn oreCase("normal")?1:2);117animation.setStartOffset(RexseeUtilities.getLong(style.animation_transl ate_start_time,0));118animation.setInterpolator(getInterPolator(style.animation_translate_int erpolator));119animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWid th(),viewParent.getHeight());120}catch(Exceptione){121}122returnanimation;123}124125publicstaticAnimationgetRotate3dyAnimation(StyleSheetstyle,Viewview,Vie wviewParent){126Animationanimation=null;127try{128floatrotate3DCenterX,rotate3DCenterY;129try{130rotate3DCenterX=Float.parseFloat(style.animation_rotate_3dy_center_x.re placeAll("%",""));131rotate3DCenterX=rotate3DCenterX/100;132if(rotate3DCenterX<0)rotate3DCenterX=0;133if(rotate3DCenterX>1)rotate3DCenterX=1;134}catch(Exceptione){135rotate3DCenterX=(float)0.5;136}137rotate3DCenterX=view.getWidth()*rotate3DCenterX;138try{139rotate3DCenterY=Float.parseFloat(style.animation_rotate_3dy_center_y.re placeAll("%",""));140rotate3DCenterY=rotate3DCenterY/100;141if(rotate3DCenterY<0)rotate3DCenterY=0;142if(rotate3DCenterY>1)rotate3DCenterY=1;143}catch(Exceptione){144rotate3DCenterY=(float)0.5;145}146rotate3DCenterY=view.getHeight()*rotate3DCenterY;147floatfrom=RexseeUtilities.getFloat(style.animation_rotate_3dy_from,0f);148floatto=RexseeUtilities.getFloat(style.animation_rotate_3dy_to,90f); 149floatrotate3DDepthZ=RexseeUtilities.getFloat(style.animation_rotate_3dy _depth_z,310.0f);150booleanreverse=(style.animation_rotate_3dy_reverse.equalsIgnoreCase("tr ue"))?true:false;151animation=newRotate3dyAnimation(from,to,rotate3DCenterX,rotate3DCenterY ,rotate3DDepthZ,reverse);152animation.setDuration(RexseeUtilities.getInt(style.animation_rotate_3dy _duration,1000));153animation.setRepeatCount(RexseeUtilities.getInt(style.animation_rotate_ 3dy_repeat_count,0));154animation.setRepeatMode(style.animation_rotate_3dy_repeat_mode.equalsIg noreCase("normal")?1:2);155animation.setStartOffset(RexseeUtilities.getLong(style.animation_rotate _3dy_start_time,0));156animation.setInterpolator(getInterPolator(style.animation_rotate_3dy_in terpolator));157animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWid th(),viewParent.getHeight());158}catch(Exceptione){159}160returnanimation;161}162163publicstaticAnimationgetRotate3dxAnimation(StyleSheetstyle,Viewview,Vie wviewParent){164Animationanimation=null;165try{166floatrotate3DCenterX,rotate3DCenterY;167try{168rotate3DCenterX=Float.parseFloat(style.animation_rotate_3dx_center_x.re placeAll("%",""));169rotate3DCenterX=rotate3DCenterX/100;170if(rotate3DCenterX<0)rotate3DCenterX=0;171if(rotate3DCenterX>1)rotate3DCenterX=1;172}catch(Exceptione){173rotate3DCenterX=(float)0.5;174}175rotate3DCenterX=view.getWidth()*rotate3DCenterX;176try{177rotate3DCenterY=Float.parseFloat(style.animation_rotate_3dx_center_y.re placeAll("%",""));178rotate3DCenterY=rotate3DCenterY/100;179if(rotate3DCenterY<0)rotate3DCenterY=0;180if(rotate3DCenterY>1)rotate3DCenterY=1;181}catch(Exceptione){182rotate3DCenterY=(float)0.5;183}184rotate3DCenterY=view.getHeight()*rotate3DCenterY;185floatfrom=RexseeUtilities.getFloat(style.animation_rotate_3dx_from,0f);186floatto=RexseeUtilities.getFloat(style.animation_rotate_3dx_to,90f); 187floatrotate3DDepthZ=RexseeUtilities.getFloat(style.animation_rotate_3dx _depth_z,310.0f);188booleanreverse=(style.animation_rotate_3dx_reverse.equalsIgnoreCase("tr ue"))?true:false;189animation=newRotate3dxAnimation(from,to,rotate3DCenterX,rotate3DCenterY ,rotate3DDepthZ,reverse);190animation.setDuration(RexseeUtilities.getInt(style.animation_rotate_3dx _duration,1000));191animation.setRepeatCount(RexseeUtilities.getInt(style.animation_rotate_ 3dx_repeat_count,0));192animation.setRepeatMode(style.animation_rotate_3dx_repeat_mode.equalsIg noreCase("normal")?1:2);193animation.setStartOffset(RexseeUtilities.getLong(style.animation_rotate _3dx_start_time,0));194animation.setInterpolator(getInterPolator(style.animation_rotate_3dx_in terpolator));195animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWid th(),viewParent.getHeight());196}catch(Exceptione){197}198returnanimation;199}200publicstaticAnimationgetSkewAnimation(StyleSheetstyle,Viewview,Viewview Parent){201Animationanimation=null;202try{203floatskewCenterX,skewCenterY;204try{205skewCenterX=Float.parseFloat(style.animation_skew_center_x.replaceAll(" %",""));206skewCenterX=skewCenterX/100;207if(skewCenterX<0)skewCenterX=0;208if(skewCenterX>1)skewCenterX=1;209}catch(Exceptione){210skewCenterX=(float)0.5;211}212skewCenterX=view.getWidth()*skewCenterX;213try{214skewCenterY=Float.parseFloat(style.animation_skew_center_y.replaceAll(" %",""));215skewCenterY=skewCenterY/100;216if(skewCenterY<0)skewCenterY=0;217if(skewCenterY>1)skewCenterY=1;218}catch(Exceptione){219skewCenterY=(float)0.5;220}221skewCenterY=view.getHeight()*skewCenterY;222223floatfromX=RexseeUtilities.getFloat(style.animation_skew_x_from,0f);224floattoX=RexseeUtilities.getFloat(style.animation_skew_x_to,1f);225floatfromY=RexseeUtilities.getFloat(style.animation_skew_y_from,0f); 226floattoY=RexseeUtilities.getFloat(style.animation_skew_y_to,1f);227228floatskewDepthZ=RexseeUtilities.getFloat(style.animation_skew_depth_z,3 10.0f);229booleanreverse=(style.animation_skew_reverse.equalsIgnoreCase("true"))? true:false;230animation=newSkewAnimation(fromX,toX,fromY,toY,skewCenterX,skewCenterY, skewDepthZ,reverse);231animation.setDuration(RexseeUtilities.getInt(style.animation_skew_durat ion,1000));232animation.setRepeatCount(RexseeUtilities.getInt(style.animation_skew_re peat_count,0));233animation.setRepeatMode(style.animation_skew_repeat_mode.equalsIgnoreCa se("normal")?1:2);234animation.setStartOffset(RexseeUtilities.getLong(style.animation_skew_s tart_time,0));235animation.setInterpolator(getInterPolator(style.animation_skew_interpol ator));236animation.initialize(view.getWidth(),view.getHeight(),viewParent.getWid th(),viewParent.getHeight());237238}catch(Exceptione){239}240returnanimation;241}242publicstaticInterpolatorgetInterPolator(Stringname){ 243if(name.equalsIgnoreCase("AccelerateDecelerate")){ 244returnnewAccelerateDecelerateInterpolator();245}elseif(name.equalsIgnoreCase("Accelerate")){246returnnewAccelerateInterpolator(10.0f);247}elseif(name.equalsIgnoreCase("Decelerate")){248returnnewDecelerateInterpolator(10.0f);249}elseif(name.equalsIgnoreCase("Anticipate")){250returnnewAnticipateInterpolator(1.0f);251}elseif(name.equalsIgnoreCase("AnticipateOvershoot")){ 252returnnewAnticipateOvershootInterpolator(1.0f,1.5f); 253}elseif(name.equalsIgnoreCase("Overshoot")){254returnnewOvershootInterpolator(1.0f);255}elseif(name.equalsIgnoreCase("Bounce")){256returnnewBounceInterpolator();257}elseif(name.equalsIgnoreCase("Cycle")){258returnnewCycleInterpolator(1);259}elseif(name.equalsIgnoreCase("Linear")){260returnnewLinearInterpolator();261}else{262returnnewLinearInterpolator();263}264} 265 266}。
Android animation 动画背景图自动播放的实现
Android动画背景图自动播放的实现
我们在开发android应用的时候,经常会遇到类似从网络加载大图,在加载的过程中,在图片要显示的ImageView位置,先显示一个转圈的loading动画图,给用户的体验会更好一些,要实现这个动画图很简单,使用在/res/anim中定义xml的方式,通常使用…. 来实现。
例如:<?xml version="1.0" encoding="utf-8"?>
<animation-list android:oneshot="false"
xmlns:android="/apk/res/android">
<item android:duration="100" android:drawable="@drawable/loading_1" />
<item android:duration="100" android:drawable="@drawable/loading_2" />
<item android:duration="100" android:drawable="@drawable/loading_3" />
<item android:duration="100" android:drawable="@drawable/loading_4" />
<item android:duration="100" android:drawable="@drawable/loading_5" />
<item android:duration="100" android:drawable="@drawable/loading_6" />
<item android:duration="100" android:drawable="@drawable/loading_7" />
<item android:duration="100" android:drawable="@drawable/loading_8" />
<item android:duration="100" android:drawable="@drawable/loading_9" />
<item android:duration="100" android:drawable="@drawable/loading_10" />
<item android:duration="100" android:drawable="@drawable/loading_11" />
<item android:duration="100" android:drawable="@drawable/loading_12" />
</animation-list>
不过大多数朋友都会遇到的问题是,动画是做好了,但是界面在加载的时候,动画并不会自动播放,还得通过屏幕点击等事件来触发,这就失去了意义了,实际上,android的动画AnimationDrawable 组件里面有个start()方法用于启动动画播放,但是这个方法不能直接写在onClick,onStart,onResume里面,写进去也是无效的,无法启动动画,只能写在比如事件监听当中,于是我们可以使用点小技巧来实现自动播放
目前我知道的有三种方法:
ImageView imageView = (ImageView)findViewById(R.id.xxx);
方法一:使用Runnalbe()来加载
imageView.setBackgroundResource(R.anim.xxxxx);
final AnimationDrawable animationDrawable = (AnimationDrawable)imageView.getBackgroun d();
imageView.post(new Runnable(){
@Override
public void run(){
animationDrawable.start();
}
});
注意:此处一定要用getBackground();不能用getdrawable()方法,会没效果。
原因如下:由于我们使用的是imageView的setBackgroundResource方法设置的资源背景,相当于布局文件中的android:background属性,这个属性是view类的属性,必须通过getBackground()方法来获取;而getdrawable()是imageview类的方法,必须通过在代码中setImageResource(int)(对应布局文件的android:src)或
setImageDrawable(Drawable drawable)方法设置才可以使用getdrawable()方法。
(详情参考帖子:/forum. ... 1&extra=#pid1627412)
方法二:使用AsyncTask异步加载启动
imageView.setBackgroundResource(R.anim.xxxxx);
AnimationDrawable animationDrawable = (AnimationDrawable)imageView.getBackground(); RunAnim runAnim=new RunAnim();
runAnim.execute("");
class RunAnim extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params){
if(!animationDrawable.isRunning()){
animationDrawable.stop();
animationDrawable.start();
}
return"";
}
}
方法三:通过添加addOnPreDrawListener来自动加载(我是用这个,感觉很好用)imageView.setBackgroundResource(R.anim.xxxxx);
AnimationDrawable animationDrawable = (AnimationDrawable)imageView.getBackground();
//注意这里,如果你的图片控件用的是setImageResource ,你这里应该使用getDrawable(); imageView.getViewTreeObserver().addOnPreDrawListener(preDrawListener);
OnPreDrawListener preDrawListener = new OnPreDrawListener(){
@Override
public boolean onPreDraw(){
animationDrawable.start();
return true; //必须要有这个true返回
}
};
以上三种方法经过测试没有问题,另外网上有一些说使用重写Activity的onWindowFocusChanged()方法来实现,但是还是有不足,得改变焦点才能触发,虽然理论可以
自动实现改变焦点,感觉还是不甚可取。
(/blog/1345.html)。