您的位置:首页 > 产品设计 > UI/UE

Android应用系列:仿MIUI的Toast动画效果实现

2015-01-22 11:41 381 查看
前言

  相信有些人用过MIUI,会发现小米的Toast跟Android传统的Toast特么是不一样的,他会从底部向上飞入,然后渐变消失。看起来效果是挺不错的,但是对于Android原生Toast是不支持自定义动画的。那这个效果到底是怎么实现的呢?下面就来告诉你。。。。

分析

  如果园友看过我的另一篇博客《Android:剖析源码,随心所欲控制Toast显示》,就会知道其实原生Toast就是infate出一个View实例,然后将其加载到WindowManager上面来达到显示效果。我们很多人都知道WindowManager是可以实现一个悬浮在所有应用界面的视图而不会获取焦点,这也就是Toast所需要具备的核心的功能:简约提示信息传递给用户,而不额外执行其他操作;在这里,我们这个效果也是基于WindowManager来实现的。

正文

  我们需要自定义一个Toast的类,但是不需要继承Toast。既然是仿照着写一个自定义Toast,那么我们就从Toast的入口开始完善这个自定义Toast。

新建一个类

view sourceprint?

1.
public
class
MiuiToast {

2.

3.
}


干干净净的不用去继承其他类(除了Object.......)

开始码代码

我们一般使用原生Toast都是直接 Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 其中makeText这个静态方法会返回一个Toast实例,然后调用show方法来显示Toast。

我们先来搞定makeText方法

view sourceprint?

1.
public
static
MiuiToast MakeText(Context context, String text,
boolean
showTime) {

2.
MiuiToast result =
new
MiuiToast(context, text, showTime);

3.
return
result;

4.
}


逻辑简单粗暴,直接调用构造函数实例化一个MiuiToast对象并返回。

接下来该是MiuiToast的构造方法了

view sourceprint?

01.
private
MiuiToast(Context context, String text,
boolean
showTime ){

02.
mShowTime = showTime;
//记录Toast的显示长短类型

03.
mIsShow =
false
;
//记录当前Toast的内容是否已经在显示

04.
mWdm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

05.
//通过Toast实例获取当前android系统的默认Toast的View布局

06.
mToastView = Toast.makeText(context, text, Toast.LENGTH_SHORT).getView();

07.
mTimer =
new
Timer();

08.
//设置布局参数

09.
setParams();

10.
}


在构造方法中,更多的是对数据的初始化,由于设置布局参数比较多,所以单独抽出一个函数来

瞧瞧setParams()方法

view sourceprint?

01.
private
void
setParams() {

02.
mParams =
new
WindowManager.LayoutParams();

03.
mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

04.
mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

05.
mParams.format = PixelFormat.TRANSLUCENT;

06.
mParams.windowAnimations = R.style.anim_view;
//设置进入退出动画效果

07.
mParams.type = WindowManager.LayoutParams.TYPE_TOAST;

08.
mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON

09.
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

10.
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

11.
mParams.gravity = Gravity.CENTER_HORIZONTAL;

12.
mParams.y =
250
;

13.
}


这个设置参数更多是参考源代码中原生Toast的设置参数的类型,在这里我们需要注意的是 mParams.windowAnimations = R.style.anim_view;//设置进入退出动画效果,这个使我们这个仿MIUI的Toast动画实现的基石。其他参数也没什么好讲的,谷歌就是这么设置他们的Toast的哈,接下来我们得看看动画的配置XML。

这个R.style.anim_view的情况呢

view sourceprint?

1.
<resources>

2.
<style name=
'anim_view'
>

3.
<item name=
'@android:windowEnterAnimation'
>
@anim
/anim_in</item>

4.
<item name=
'@android:windowExitAnimation'
>
@anim
/anim_out</item>

5.
</style>

6.
</resources>


这里定义了一个进入动画和退出动画的引用,接下来就是我们设置动画效果的时刻了!

anim_in:Toast的进入动画

view sourceprint?

01.
<set xmlns:android=
'http://schemas.android.com/apk/res/android'
>

02.
<translate

03.
android:fromXDelta=
'0'

04.
android:fromYDelta=
'0'

05.
android:toXDelta=
'0'

06.
android:toYDelta=
'85'

07.
android:duration=
'1'

08.
/>

09.
<translate

10.
android:fromXDelta=
'0'

11.
android:fromYDelta=
'0'

12.
android:toXDelta=
'0'

13.
android:toYDelta=
'-105'

14.
android:duration=
'350'

15.
android:fillAfter=
'true'

16.
android:interpolator=
'@android:anim/decelerate_interpolator'

17.
/>

18.
<alpha

19.
android:fromAlpha=
'0'

20.
android:toAlpha=
'1'

21.
android:duration=
'100'

22.
/>

23.
<translate

24.
android:fromXDelta=
'0'

25.
android:fromYDelta=
'0'

26.
android:toXDelta=
'0'

27.
android:toYDelta=
'20'

28.
android:duration=
'80'

29.
android:fillAfter=
'true'

30.
android:startOffset=
'350'

31.
/>

32.
</set>


在这里我配置了四个动画效果,如果大家要重新设置新的动画效果,尽可以在这里面修改哈。粗略的说几句,由于在加载动画的前后,WindowManager就通过mParams来确定Toast的显示位置,所以第一个translate作用是让Toast在开始载入的时候跳转到进入的位置,而其他的动画就是完成Toast从下端飞入的效果而已,这期间利用了android:startOffset进行时间的控制达到动画的衔接效果。

anim_out:Toast退出动画

view sourceprint?

1.
<set xmlns:android=
'http://schemas.android.com/apk/res/android'
>

2.
<alpha

3.
android:fromAlpha=
'1'

4.
android:toAlpha=
'0'

5.
android:duration=
'800'
/>

6.
</set>


简简单单的一个淡出动画。。。。

然后我们来看下show()方法吧

view sourceprint?

01.
public
void
show(){

02.
if
(!mIsShow){
//如果Toast没有显示,则开始加载显示

03.
mIsShow =
true
;

04.
mWdm.addView(mToastView, mParams);
//将其加载到windowManager上

05.
mTimer.schedule(
new
TimerTask() {

06.
@Override

07.
public
void
run() {

08.
mWdm.removeView(mToastView);

09.
mIsShow =
false
;

10.
}

11.
}, (
long
)(mShowTime ?
3500
:
2000
));

12.
}

13.
}


在show方法中我们会对mIsShow 判断当前的Toast是否已经在显示,如果正在显示我们没理由相信我们会那么SB得再去显示他一次。。

mWdm.addView(mToastView, mParams);将View加载到WindowManager上面,达到类似的悬浮效果,启动定时器,到达指定的时间后将其移除,整个逻辑就是这样了。

因为——Toast!就是这么简单!

给大家瞄瞄效果图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: