• Android应用系列:仿MIUI的Toast动画效果实现(有图有源码)


    前言

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

    分析

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

    正文

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

    新建一个类

    public class MiuiToast {
    
    }

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

    开始码代码

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

    我们先来搞定makeText方法

    public static MiuiToast MakeText(Context context, String text, boolean showTime) {
        MiuiToast result = new MiuiToast(context, text, showTime);
        return result;
    }

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

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

    private MiuiToast(Context context, String text, boolean showTime ){
        mShowTime = showTime;//记录Toast的显示长短类型
        mIsShow = false;//记录当前Toast的内容是否已经在显示
        mWdm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        //通过Toast实例获取当前android系统的默认Toast的View布局
        mToastView = Toast.makeText(context, text, Toast.LENGTH_SHORT).getView();
        mTimer = new Timer();
        //设置布局参数
        setParams();
    }

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

    瞧瞧setParams()方法

    private void setParams() {
        mParams = new WindowManager.LayoutParams();
        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
        mParams.format = PixelFormat.TRANSLUCENT;  
        mParams.windowAnimations = R.style.anim_view;//设置进入退出动画效果
        mParams.type = WindowManager.LayoutParams.TYPE_TOAST;  
        mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        mParams.gravity = Gravity.CENTER_HORIZONTAL;
        mParams.y = 250;
    }

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

    这个R.style.anim_view的情况呢

    <resources>
        <style name="anim_view">
            <item name="@android:windowEnterAnimation">@anim/anim_in</item>
            <item name="@android:windowExitAnimation">@anim/anim_out</item>
        </style>
    </resources>

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

    anim_in:Toast的进入动画

    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="0"
            android:toYDelta="85"
            android:duration="1"
            />
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="0"
            android:toYDelta="-105"
            android:duration="350"
            android:fillAfter="true"
            android:interpolator="@android:anim/decelerate_interpolator"
            />
        <alpha 
            android:fromAlpha="0"
            android:toAlpha="1"
            android:duration="100"
            />
        <translate
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="0"
            android:toYDelta="20"
            android:duration="80"
            android:fillAfter="true"
            android:startOffset="350"
            />
    </set>

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

    anim_out:Toast退出动画

    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <alpha 
            android:fromAlpha="1"
            android:toAlpha="0"
            android:duration="800"/>
    </set>

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

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

    public void show(){
        if(!mIsShow){//如果Toast没有显示,则开始加载显示
            mIsShow = true;
            mWdm.addView(mToastView, mParams);//将其加载到windowManager上
            mTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    mWdm.removeView(mToastView);
                    mIsShow = false;
                }
            }, (long)(mShowTime ? 3500 : 2000));
        }
    }

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

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

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

    给大家瞄瞄效果图

    源码请戳这里(点我吧

    作者:enjoy风铃
    出处:http://www.cnblogs.com/net168/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则下次不给你转载了。

  • 相关阅读:
    自编码变分贝叶斯(转载)
    加载Pytorch中的预训练模型及部分结构的导入
    pytorch读入图片并显示np.transpose(np_image, [1, 2, 0])
    高斯分布、多维高斯分布、各向同性的高斯分布及多元高斯分布之间的KL散度
    pytorch中的上采样(上采样,转置卷积,上池化,PixelShuffle)
    卷积算法动画演示
    PL/SQL编程基础
    PL/SQL Dev 调试
    PL/SQL Dev的安装与连接远程数据库
    Bean Form DTO VO Entity
  • 原文地址:https://www.cnblogs.com/net168/p/4237528.html
Copyright © 2020-2023  润新知