转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客

元旦假期里,闲的无事,看到美团加载数据的动画,就突想写个Demo把动画知识集成一下。后来想了想,还是直接用一个Demo来把所有动画知识穿插起来算了,该Demo涉及大多数动画应用场景。本篇案例,使用补间动画完成一个简单的动画功能集,会涉及多种形式的动画实现(即使补间动画很老套,但一些简单的动画功能还是可以选择它的)。其实在实际开发中也能看到这些影子。例如很多应用刚打开时候会有一些简单的动画效果,有的应用切换Activity的时候,也带有简单的平移动画效果更美观点,有的应用输入用户名密码错误会有抖动效果等等。同时会自定义View方式自定义一个进度条,模拟美团加载;模拟wifi链接网络;由于几个Activity功能差不多,我对其做一个简单的封装,抽取了BaseActivity。本案例,就是基于这些动画特性做的简化而形成的一个大Demo[界面丑陋,勿喷]。

GitHub下载源代码,打开代码传送门----------------->>>https://github.com/codeydl/App01

本文参考博客:参考博客1:Android 用Animation-list实现逐帧动画

参考博客2:(模拟美团客户端进度提示框)

先提前浏览一下Demo的效果图:

那么,咱们就从头慢慢来分析这个Demo吧,因为这属于老知识了,网上有很多详细的解析,而且比较简单,又有源代码可以下载,下面只给出核心代码和解析。

一、展示Splash动画

1、动画代码

这里使用旋转、缩放、渐变动画知识,启动Splash动画向导。一般实际项目中,可以在加载动画的时候,进行访问网络数据、拷贝本地数据库等耗时业务,而动画还可以起到对项目介绍的功能。

加载Splash我们可以使用下面代码完成:

//比例动画
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(2000); //渐变动画
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(2000); //旋转动画
RotateAnimation rotateAnimation = new RotateAnimation(0,360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(2000); //动画集合,所有动画一起飞
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation); //启动动画
mRl_splash_view.startAnimation(animationSet);

使用动画集AnimationSet加载前述三种动画,然后使用一个View对象启动这个动画,把动画集合对象加载进去。

2、自定义的进度条

在播放动画的时候,我们在图片下方加上一个自定义进度条,这就用到自定义进度条的功能,本质上还是使用动画知识。自定义进度条,我们可以按照下面步骤完成:

1)、在res下新建anim文件,创建my_progress.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/progess">
<!--自定义进度条,依托旋转动画。只需要引入一张图片即可。然后在需要使用该进度条的地方
ProgressBar位置下面。引入进度条:方式、android:indeterminateDrawable="@anim/my_progress"引入默认进度条
android:indeterminateDuration="800"修改旋转一圈耗费的时间-->
</rotate>

上边我们@drawable/给出一张图片就行了

然后在需要使用这个自定义进度条的地方引入就好了,引入方式上边已经注释。

2)、引入自定义进度条

<ProgressBar
android:indeterminateDrawable="@anim/my_progress"
android:indeterminateDuration="800"

3、界面切换

界面切换使用Handler延时两秒后,完成进入主界面操作

Handler发消息方

//两秒后发消息进入设置界面
mHandler.sendEmptyMessageDelayed(1,2000);

然后Handler接收消息方代码:

private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
//进入Step1Activity
Intent intent = new Intent(SplashActivity.this,Step1Activity.class);
startActivity(intent);
finish();
break; default:
break;
}
}
};

二、进入几个设置界面

由于几个设置界面只是为了展示切换Activity时平移的效果,几个功能大同小异。我把活动抽取了一下,在每个活动里面只需要简单的几行代码,就能完成效果。

1、先完成活动可切换

我们从第二个活动入手,说明为何要抽取基类。

第二个活动布局代码就两个按钮:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_step2_activiity"
android:layout_width="match_parent"
android:layout_height="match_parent"
> <Button
android:onClick="next"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="下一步"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/> <Button
android:onClick="pre"
android:layout_alignParentBottom="true"
android:text="上一步"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/> </RelativeLayout>

那么其他的活动与之类似,我们给Button设置了可点击事件。那么在每一个活动里面都会有同样的效果,即点击下一步动画切换下一个活动;点击上一步动画切换下一个活动。按钮事件通过next(View v){}方式实现,那么所有活动肯定有多余代码量,因此向上抽取同样功能,代码如下:

public void next(View v){
//启动下一个活动
nextActivity();
}

以及:

public void pre(View v){
preActivity();
}

以进入一下个活动为分析点:

我们发现调用了nextActivity();这个是一个抽象方法,让子类实现,点击下一步按钮,实际调用具体子类的该方法。因为,抽取了基类,还要实现下一步切换没有什么其他好的方式去实现。那么这个方法具体子类如何实现呢?

我们往往可能会直接重写该方法:

@Override
protected void nextActivity() {
    Intent intent = new Intent(this,Setup3Activity,class);
startActivity(intent);
finish();

}

那么我们又要想了,所有启动下一个活动都要重复写代码,反过来启动上一个活动也要写类似的Intent....这样的代码,因而切换活动可以写在基类里面。怎么实现呢?

在基类里面定义一个方法就好了,它的功能用于专门启动任意一个活动:

public  void startActivity(Class activity){
Intent intent = new Intent(this,activity);
startActivity(intent);
finish();
}

子类如果想启动某一个活动,只需要重写上边的方法,并且传入要启动的活动.class就好了。比如我活动二中想启动Setup3Activity,以及启动Setup1Activity:

@Override
protected void nextActivity() {
startActivity(Step3Activity.class);
} @Override
protected void preActivity() {
startActivity(Step1Activity.class);
}

是不是节省好多代码?哈哈,那是肯定的。完成了活动切换,然后考虑活动切换的动画切换

2、Activity动画切换效果写前分析:

1)、分析

最好的解释,莫过于图片。我用一张图片分析了切换的原理:

经过上图的分析,就可以给出切换下一个活动和切换上一个活动的动画xml了。以点击下一步时候需要的动画为出发点:

2)代码:

next_in.xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="100%"
android:toXDelta="0"
android:duration="300"
> </translate>

next_out.xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:duration="300"
android:toXDelta="-100%"
android:toYDelta="0"> </translate>

3)、基类里面加入活动切换的代码:

使用API

overridePendingTransition();

由于动画切换也是每个活动所具备的,因此还可以写在基类里面:

public void nextAnimation(){
//加入动画方式启动下一个活动
overridePendingTransition(R.anim.next_in,R.anim.next_out);
} public void preAnimation(){
//加入动画方式启动上一个活动
overridePendingTransition(R.anim.pre_in,R.anim.pre_out);
}

只需要在基类点击方法next(View v){}和pre(View v){}里面调用一下就好了。

public void next(View v){
................
//使用动画
nextAnimation();
}

以及:

public void pre(View v){
..............
preAnimation();
}

以及在Setup3Activity进入主界面时候的动画(点击完成按钮,进入主界面):

public void complete(View v){
startActivity(MainActivity.class);
overridePendingTransition(R.anim.bottom_in,R.anim.top_out);
}

三、主活动界面布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"> <LinearLayout
android:layout_weight="1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_activity_main_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入内容"/> <Button
android:id="@+id/btn_activity_main_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"/>
</LinearLayout> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"> <ImageView
android:layout_centerHorizontal="true"
android:id="@+id/animationIV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5px"
android:src="@drawable/animation1"/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"> <Button
android:id="@+id/buttonA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="5px"
android:text="顺序显示"/> <Button
android:id="@+id/buttonB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="5px"
android:text="停止"/> <Button
android:id="@+id/buttonC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="5px"
android:text="倒序显示"/>
</LinearLayout> </RelativeLayout>
</LinearLayout>

这里第EditText与紧跟的button是一组。点击登录按钮,如果EditText无内容,就实现EditText抖动效果。如果有内容点击就弹出自定义对话框,实现模拟美团加载数据功能。最底下是一组,模拟wifi链接动画效果。

那么就一点点来实现出来吧:

1、监听EditText是否空,为空实现抖动效果:

抖动效果本质上其实就是平移动画,加入一个周期即可。

<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXDelta="0"
android:interpolator="@anim/cycle_8"
android:toXDelta="10" />
<!--平移10dp长度;interpolator动画插入器:表示动画循环多少次-->

平移10个单位,500毫秒完成一个周期。引入一个周期:

<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:cycles="8" />
<!--动画插入器-->

在代码中点击button,抖动效果代码如下:

//抖动效果
Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.shake);
etactivitymaincontent.startAnimation(animation);//给edittext加入动画

2、最底部完成wifi链接动画:

此时也是动画效果,使用多张动画,完成隔一段时间切换不同图片,达到动态效果。

方式如下:

在drawable下面,新建animation1(用于顺序动画)和animation2.(用于逆序动画)

只针对animation1做分析:

<?xml version="1.0" encoding="utf-8"?>
<!--
根标签为animation-list,其中oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画
根标签下,通过item标签对动画中的每一个图片进行声明
android:duration 表示展示所用的该图片的时间长度
-->
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true"
>
<item android:drawable="@drawable/icon1" android:duration="150"></item>
<item android:drawable="@drawable/icon2" android:duration="150"></item>
<item android:drawable="@drawable/icon3" android:duration="150"></item>
<item android:drawable="@drawable/icon4" android:duration="150"></item>
<item android:drawable="@drawable/icon5" android:duration="150"></item>
<item android:drawable="@drawable/icon6" android:duration="150"></item>
</animation-list>

加入多张图片,并制定了动画展示时间。oneshot=true表示动画只播放一次。如果制定为fasle则不停的播放了。

那马在代码中,我们可以同过下面方式加入动画:

animationIV.setImageResource(R.drawable.animation1);
mAnimationDrawable = (AnimationDrawable) animationIV.getDrawable();
mAnimationDrawable.start();

把自定义动画xml作为参数设置到setImageResource中设置一个资源,再调用getDrawable方法返回值Drawable,注意这里强转为AnimationDrawable,只有这个对象才可以启动这种方式的动画。

当点击停止的时候:

mAnimationDrawable.stop();

animation2原理一模一样。

3、模拟美团登录加载数据

1)、布局:

<ImageView
android:id="@+id/iv_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/frame_meituan"/>

主要说明一下imageview。他通过android:background="@drawable/frame_meituan"引入一个动画xml文件。这个文件原理跟上边的模拟wifi效果又是一样的了。动画效果也是两张图片不停地切换。

2)、自定义对话

模拟美团登录效果,其实也是两张动画的不停切换。原理和上边一样。只不过这里加入了自定义对话框功能:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initView();
initData();
} private void initData() {
// 通过ImageView对象拿到背景显示的AnimationDrawable
mAnimation = (AnimationDrawable) mIvLoading.getBackground(); //主界面点击登录,立即调用这里的动画显示功能
mAnimation.start(); //设置正在加载中信息
mTvLoading.setText(mLoadingTip);
} private void initView() {
//加载自定义布局,此时MyDialog已经有了该布局的样子
setContentView(R.layout.progress_dialog);// 显示界面
mTvLoading = (TextView) findViewById(R.id.tv_loading);
mIvLoading = (ImageView) findViewById(R.id.iv_loading);
}

ProgressDialog不是ViewGroup,自定义布局通过setContentView方法加载进来自定义的布局。要重写onCreate,加入一个自定义布局,并且拿到布局中的实例。当外界初始化Dialog的时候,就会调用onCreate方法。初始化数据我们得到imageview的动画实例,这里同样强制转换为AnimationDrawable,只有这个对象才可以启动这种方式的动画。可见,只要外界一创建自定义对话框对象,就能启动该布局,而且启动动画,调用.show()方法,可以展示该自定义对话框。

当外界调用取消对话框的时候,我们要调用dismiss()方法。因而,我们需要在关闭的时候加入结束动画的代码:

@Override
public void dismiss() {
super.dismiss();
//对话框关闭,同时关闭掉动画。节约资源
mAnimation.stop();
mAnimation = null;
}

构造方法,肯定是传入需要的上下文(这个上下文必须是Activity类型的),需要的设置的文本提示内容,如下:

public MyDialog(Context context,String content) {
super(context);
this.mContext = context;
this.mLoadingTip = content;
}

3)、引用该自定义的对话框。

//模拟美团登录
mDialog = new MyDialog(this, "正在加载中");
mDialog.show();
Handler handler =new Handler();
handler.postDelayed(new Runnable() { @Override
public void run() { mDialog.dismiss();
}
}, 3000);//3秒钟后调用dismiss方法隐藏;如果有访问网络,可以设置访问网络成功后的监听,再停止对话框

就像使用系统对话框一样,使用这个自定义对话框就好了。我们展示对话框后,并使用handler延时3秒关闭对话框。很简单。

上边实现步骤,我写的很详细,写了好久啊。看完记得加关注点赞啊~

最后,再看看实现的效果吧!

看完的朋友可以关注下,或者微信扫描下方二维码,关注公众号也可以:

打开微信搜索公众号  Android程序员开发指南  或者手机扫描下方二维码 在公众号阅读更多Android文章。

微信公众号图片:

Android Studio精彩案例(六)《使用一个Demo涵盖补间动画所有知识》的更多相关文章

  1. Android Studio精彩案例(一)《ActionBar和 ViewPager版仿网易新闻客户端》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了能更好的分享高质量的文章,所以开设了此专栏.文章代码都以Android Studio亲测运行,读者朋友可在后面直接下载源码.该专栏 ...

  2. Android Studio精彩案例(七)《ToolBar使用详解<一>》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 本文参考博客:http://blog.csdn.net/h_zhang/article/details/51232773 http:/ ...

  3. Android Studio精彩案例(五)《JSMS短信验证码功能实现》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 很多应用刚打开的时候,让我们输入手机号,通过短信验证码来登录该应用.那么,这个场景是怎么实现的呢?其实是很多开放平台提供了短信验证功能 ...

  4. Android Studio精彩案例(二)《仿微信动态点击底部tab切换Fragment》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 现在很多的App要么顶部带有tab,要么就底部带有tab.用户通过点击tab从而切换不同的页面(大部分情况时去切换fragment). ...

  5. Android Studio精彩案例(四)《DrawerLayout使用详解仿网易新闻客户端侧边栏 》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了提高兴趣,咱们开头先看看最终要实现什么样的效果: 侧拉菜单在Android应用中非常常见,它的实现方式太多了,今天我们就说说使用G ...

  6. Android Studio精彩案例(三)《模仿微信ViewPage+Fragment实现方式二》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 写在前面的话:此专栏是博主在工作之余所写,每一篇文章尽可能写的思路清晰一些,属于博主的"精华"部分,不同于以往专栏 ...

  7. [转]Android Studio系列教程六--Gradle多渠道打包

    转自:http://www.stormzhang.com/devtools/2015/01/15/android-studio-tutorial6/ Android Studio系列教程六--Grad ...

  8. Android Studio系列教程六--Gradle多渠道打包

    Android Studio系列教程六--Gradle多渠道打包 2015 年 01 月 15 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzh ...

  9. Android笔记(六十四) android中的动画——补间动画(tweened animation)

    补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效 ...

随机推荐

  1. UVA-562 Dividing coins---01背包+平分钱币

    题目链接: https://vjudge.net/problem/UVA-562 题目大意: 给定n个硬币,要求将这些硬币平分以使两个人获得的钱尽量多,求两个人分到的钱最小差值 思路: 它所给出的n个 ...

  2. pandas(七)数据规整化:清理、转换、合并、重塑之合并数据集

    pandas对象中的数据可以通过一些内置的方式进行合并: pandas.merge 可根据一个或多个键将不同的DataFrame中的行连接起来. pandas.concat可以沿着一条轴将多个对象堆叠 ...

  3. C++ 多态的实现及原理

    C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数.如果对象类型是派生类,就调用派生类的函数:如果对象类型是基类 ...

  4. Windows下安装Python3和Django

    下载python3 首先去 python的官网 下载最新稳定版的python3, 我下载的时候python3的最新版本是3.6.5. 亦可点击 此链接 直接下载. 安装python3 傻瓜式安装,注意 ...

  5. [Linux]_ELVE_ssh登录远程阿里服务器

    0x00  背景 最近新开了一个服务器,每次都用网页操作太麻烦,索性就用软件登录(貌似界面还有vim支持的也比网页的好),在网上寻找半天,找到一个软件,感觉特别好, 名叫:mobaxterm,好像是免 ...

  6. 八:Vue下的国际化处理

    p { margin-bottom: 0.25cm; line-height: 120% } 1:首先安装 Vue-i8n npm install vue-i18n --save 注:-save-de ...

  7. 洛谷P3233 [HNOI2014]世界树

    虚树= = #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring&g ...

  8. empty()和size()的优劣

    通常下面代码: if(c.size() == 0) if(c.empty()) 我们会觉得它们是是等价的. 为何empty()比较好? 主要是他们之间的效率有一定差距: empty对任意的容器都是常数 ...

  9. VK Cup 2017 - Round 2

    FallDream打的AB都FFT了,只剩一个我打的C,没进前一百,之后看看马拉松复活赛有没机会呗. A. Voltage Keepsake 题目大意:n个东西,每个东西一开始有bi能源,每秒消耗ai ...

  10. hdu 4453 splay

    Looploop Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...