Android Studio精彩案例(六)《使用一个Demo涵盖补间动画所有知识》
转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客
元旦假期里,闲的无事,看到美团加载数据的动画,就突想写个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涵盖补间动画所有知识》的更多相关文章
- Android Studio精彩案例(一)《ActionBar和 ViewPager版仿网易新闻客户端》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了能更好的分享高质量的文章,所以开设了此专栏.文章代码都以Android Studio亲测运行,读者朋友可在后面直接下载源码.该专栏 ...
- Android Studio精彩案例(七)《ToolBar使用详解<一>》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 本文参考博客:http://blog.csdn.net/h_zhang/article/details/51232773 http:/ ...
- Android Studio精彩案例(五)《JSMS短信验证码功能实现》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 很多应用刚打开的时候,让我们输入手机号,通过短信验证码来登录该应用.那么,这个场景是怎么实现的呢?其实是很多开放平台提供了短信验证功能 ...
- Android Studio精彩案例(二)《仿微信动态点击底部tab切换Fragment》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 现在很多的App要么顶部带有tab,要么就底部带有tab.用户通过点击tab从而切换不同的页面(大部分情况时去切换fragment). ...
- Android Studio精彩案例(四)《DrawerLayout使用详解仿网易新闻客户端侧边栏 》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了提高兴趣,咱们开头先看看最终要实现什么样的效果: 侧拉菜单在Android应用中非常常见,它的实现方式太多了,今天我们就说说使用G ...
- Android Studio精彩案例(三)《模仿微信ViewPage+Fragment实现方式二》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 写在前面的话:此专栏是博主在工作之余所写,每一篇文章尽可能写的思路清晰一些,属于博主的"精华"部分,不同于以往专栏 ...
- [转]Android Studio系列教程六--Gradle多渠道打包
转自:http://www.stormzhang.com/devtools/2015/01/15/android-studio-tutorial6/ Android Studio系列教程六--Grad ...
- Android Studio系列教程六--Gradle多渠道打包
Android Studio系列教程六--Gradle多渠道打包 2015 年 01 月 15 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzh ...
- Android笔记(六十四) android中的动画——补间动画(tweened animation)
补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效 ...
随机推荐
- UVA-562 Dividing coins---01背包+平分钱币
题目链接: https://vjudge.net/problem/UVA-562 题目大意: 给定n个硬币,要求将这些硬币平分以使两个人获得的钱尽量多,求两个人分到的钱最小差值 思路: 它所给出的n个 ...
- pandas(七)数据规整化:清理、转换、合并、重塑之合并数据集
pandas对象中的数据可以通过一些内置的方式进行合并: pandas.merge 可根据一个或多个键将不同的DataFrame中的行连接起来. pandas.concat可以沿着一条轴将多个对象堆叠 ...
- C++ 多态的实现及原理
C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数.如果对象类型是派生类,就调用派生类的函数:如果对象类型是基类 ...
- Windows下安装Python3和Django
下载python3 首先去 python的官网 下载最新稳定版的python3, 我下载的时候python3的最新版本是3.6.5. 亦可点击 此链接 直接下载. 安装python3 傻瓜式安装,注意 ...
- [Linux]_ELVE_ssh登录远程阿里服务器
0x00 背景 最近新开了一个服务器,每次都用网页操作太麻烦,索性就用软件登录(貌似界面还有vim支持的也比网页的好),在网上寻找半天,找到一个软件,感觉特别好, 名叫:mobaxterm,好像是免 ...
- 八:Vue下的国际化处理
p { margin-bottom: 0.25cm; line-height: 120% } 1:首先安装 Vue-i8n npm install vue-i18n --save 注:-save-de ...
- 洛谷P3233 [HNOI2014]世界树
虚树= = #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring&g ...
- empty()和size()的优劣
通常下面代码: if(c.size() == 0) if(c.empty()) 我们会觉得它们是是等价的. 为何empty()比较好? 主要是他们之间的效率有一定差距: empty对任意的容器都是常数 ...
- VK Cup 2017 - Round 2
FallDream打的AB都FFT了,只剩一个我打的C,没进前一百,之后看看马拉松复活赛有没机会呗. A. Voltage Keepsake 题目大意:n个东西,每个东西一开始有bi能源,每秒消耗ai ...
- hdu 4453 splay
Looploop Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...