教你打造Android揭面水波動(dòng)畫(huà)庫(kù)-AnimationHelper

好多天沒(méi)出干貨了,今晚寫(xiě)這篇文章花了幾小時(shí)卫玖,大家喜歡的可以GitHub走一波star

AnimationHelper

這是一個(gè)動(dòng)畫(huà)幫助工具庫(kù), 提供簡(jiǎn)單的幫助實(shí)現(xiàn)以下效果的工具類.我將其上傳了Jcenter, 大家可以引用

工程見(jiàn): https://github.com/Jerey-Jobs/AnimationHelper
大家可以star一波哈!

先看一張效果圖:

import/引入方式

project's build.gradle (工程下的 build.gradle)

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
}

module's build.gradle (模塊的build.gradle)

    dependencies {
             compile 'com.github.Jerey-Jobs:AnimationHelper:1.0'
    }

簡(jiǎn)介

Android5.0系統(tǒng)源碼中增加了新的API - ViewAnimationUtils 是其作用就是可以使控件能夠呈現(xiàn)水波一樣展開(kāi)。

源碼介紹也很簡(jiǎn)單, 我們ctrl+左擊該類可看到


public final class ViewAnimationUtils {
    private ViewAnimationUtils() {}
    /**
     * </code></pre>
     *
     * @param view The View will be clipped to the animating circle.
     * @param centerX The x coordinate of the center of the animating circle, relative to
     *                <code>view</code>.
     * @param centerY The y coordinate of the center of the animating circle, relative to
     *                <code>view</code>.
     * @param startRadius The starting radius of the animating circle.
     * @param endRadius The ending radius of the animating circle.
     */
    public static Animator createCircularReveal(View view,
            int centerX,  int centerY, float startRadius, float endRadius) {
        return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
    }
}

這個(gè)類就只有一個(gè)方法, createCircularReveal

參數(shù)1 view: 要實(shí)現(xiàn)波紋效果的view;

參數(shù)2 centerX: 動(dòng)畫(huà)的中心點(diǎn)的x坐標(biāo);

參數(shù)3 centerY:動(dòng)畫(huà)的中心點(diǎn)的y坐標(biāo);

參數(shù)4 startRadius: 動(dòng)畫(huà)開(kāi)始的波紋半徑;

參數(shù)5 endRadius:動(dòng)畫(huà)結(jié)束時(shí)的波紋半徑;

封裝

我們開(kāi)始封裝一個(gè)Helper類, 先實(shí)現(xiàn)View的隱藏和顯示動(dòng)畫(huà)

public class AnimationHelper {

    public static final int MINI_RADIUS = 0;
    public static final int DEFAULT_DURIATION = 500;

    /**
     * 屏蔽Android提示錯(cuò)誤, 5.0以下不做動(dòng)畫(huà)處理
     *
     * @param view
     * @param startRadius
     * @param durationMills
     */
    @SuppressLint("NewApi")
    public static void show(View view, float startRadius, long durationMills) {
        // Android L 以下不做處理,直接顯示
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            view.setVisibility(View.VISIBLE);
            return;
        }

        int xCenter = (view.getLeft() + view.getRight()) / 2;
        int yCenter = (view.getTop() + view.getBottom()) / 2;
        int w = view.getWidth();
        int h = view.getHeight();
        //計(jì)算最大半徑, 邊界效應(yīng)+1
        int endRadius = (int) (Math.sqrt(w * w + h * h) + 1);
        Animator animation = ViewAnimationUtils.createCircularReveal(view,
                xCenter, yCenter, startRadius, endRadius);
        view.setVisibility(View.VISIBLE);
        animation.setDuration(durationMills);
        animation.start();
    }

    @SuppressLint("NewApi")
    public static void hide(final View view, float endRadius, long durationMills, final int visible) {
        // Android L 以下不做處理,直接顯示
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            view.setVisibility(View.INVISIBLE);
            return;
        }

        int xCenter = (view.getLeft() + view.getRight()) / 2;
        int yCenter = (view.getTop() + view.getBottom()) / 2;
        int w = view.getWidth();
        int h = view.getHeight();
        //計(jì)算最大半徑, 邊界效應(yīng)+1
        int startRadius = (int) (Math.sqrt(w * w + h * h) + 1);
        Animator animation = ViewAnimationUtils.createCircularReveal(view,
                xCenter, yCenter, startRadius, endRadius);
        animation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                view.setVisibility(visible);
            }
        });
        animation.setDuration(durationMills);
        animation.start();
    }

    public static void show(View myView) {
        show(myView, MINI_RADIUS, DEFAULT_DURIATION);
    }

    /**
     * 默認(rèn)View隱藏狀態(tài)為 INVISIBLE
     * @param myView
     */
    public static void hide(View myView) {
        hide(myView, MINI_RADIUS, DEFAULT_DURIATION, View.INVISIBLE);
    }

    /*
     * @param myView 要隱藏的view
     * @param endVisible  動(dòng)畫(huà)執(zhí)行結(jié)束是view的狀態(tài), 是View.INVISIBLE 還是GONE
     */
    public static void hide(View myView, int endVisible) {
        hide(myView, MINI_RADIUS, DEFAULT_DURIATION, endVisible);
    }
}

之后我們使用就很簡(jiǎn)單了, 想要顯示一個(gè)View的展示動(dòng)畫(huà), 則

  AnimationHelper.show(mImageView);

隱藏,則

  AnimationHelper.hide(mImageView);

我們看一下,目前的使用的效果:

效果

拓展 - 過(guò)渡動(dòng)畫(huà)

我們可以使用該動(dòng)畫(huà),創(chuàng)造一個(gè)頁(yè)面過(guò)渡動(dòng)畫(huà), 如何弄呢?

可以通過(guò)給我們的DecordView添加一個(gè)View, 然后overridePendingTransition 即可.

以下是代碼:

@SuppressLint("NewApi")
public static void startActivityForResult(
        final Activity thisActivity, final Intent intent, final Integer requestCode,
        final Bundle bundle, final View view,
        int colorOrImageRes, final long durationMills) {
    // SDK 低于LOLLIPOP不做處理,直接跳轉(zhuǎn)
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        if (requestCode == null) {
            thisActivity.startActivity(intent);
        } else if (bundle == null) {
            thisActivity.startActivityForResult(intent, requestCode);
        } else {
            thisActivity.startActivityForResult(intent, requestCode, bundle);
        }
        return;
    }
    int[] location = new int[2];
    view.getLocationInWindow(location);
    final int xCenter = location[0] + view.getWidth() / 2;
    final int yCenter = location[1] + view.getHeight() / 2;
    final ImageView imageView = new ImageView(thisActivity);
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageView.setImageResource(colorOrImageRes);

    final ViewGroup decorView = (ViewGroup) thisActivity.getWindow().getDecorView();
    int w = decorView.getWidth();
    int h = decorView.getHeight();
    decorView.addView(imageView, w, h);

    // 計(jì)算中心點(diǎn)至view邊界的最大距離
    int maxW = Math.max(xCenter, w - xCenter);
    int maxH = Math.max(yCenter, h - yCenter);
    final int finalRadius = (int) Math.sqrt(maxW * maxW + maxH * maxH) + 1;

    Animator anim = ViewAnimationUtils.createCircularReveal(imageView, xCenter, yCenter, 0, finalRadius);
    int maxRadius = (int) Math.sqrt(w * w + h * h) + 1;
    long finalDuration = durationMills;
    /**
     * 計(jì)算時(shí)間
     */
    if (finalDuration == DEFAULT_DURIATION) {
        // 算出實(shí)際邊距與最大邊距的比率
        double rate = 1d * finalRadius / maxRadius;
        // 水波擴(kuò)散的距離與擴(kuò)散時(shí)間成正比
        finalDuration = (long) (DEFAULT_DURIATION * rate);
    }
    anim.setDuration(finalDuration);
    anim.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            if (requestCode == null) {
                thisActivity.startActivity(intent);
            } else if (bundle == null) {
                thisActivity.startActivityForResult(intent, requestCode);
            } else {
                thisActivity.startActivityForResult(intent, requestCode, bundle);
            }

            // 默認(rèn)漸隱過(guò)渡動(dòng)畫(huà).
            thisActivity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
            // 默認(rèn)顯示返回至當(dāng)前Activity的動(dòng)畫(huà).
            view.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Animator anim =
                            ViewAnimationUtils.createCircularReveal(imageView, xCenter, yCenter, finalRadius, 0);
                    anim.setDuration(durationMills);
                    anim.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            super.onAnimationEnd(animation);
                            try {
                                decorView.removeView(imageView);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                    anim.start();
                }
            }, 1000);
        }
    });
    anim.start();
}

使用

AnimationHelper.startActivity(MainActivity.this,
        new Intent(MainActivity.this, LoginActivity.class),
        mStartAvtivityBtn,
        R.color.colorPrimary
);

效果

大家可以star一波哈!

工程地址: https://github.com/Jerey-Jobs/AnimationHelper

哦惠呼,封面圖怕品,



本文作者:Anderson/Jerey_Jobs

博客地址 : http://jerey.cn/

簡(jiǎn)書(shū)地址 : Anderson大碼渣

github地址 : https://github.com/Jerey-Jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市妓笙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌能岩,老刑警劉巖寞宫,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拉鹃,居然都是意外死亡辈赋,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)膏燕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钥屈,“玉大人,你說(shuō)我怎么就攤上這事煌寇』捞悖” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵阀溶,是天一觀的道長(zhǎng)腻脏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)银锻,這世上最難降的妖魔是什么永品? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮击纬,結(jié)果婚禮上鼎姐,老公的妹妹穿的比我還像新娘。我一直安慰自己更振,他們只是感情好炕桨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著肯腕,像睡著了一般献宫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上实撒,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天姊途,我揣著相機(jī)與錄音,去河邊找鬼知态。 笑死捷兰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的负敏。 我是一名探鬼主播贡茅,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼其做!你這毒婦竟也來(lái)了友扰?” 一聲冷哼從身側(cè)響起彤叉,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎村怪,沒(méi)想到半個(gè)月后秽浇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡甚负,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年柬焕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梭域。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斑举,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出病涨,到底是詐尸還是另有隱情富玷,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布既穆,位于F島的核電站赎懦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏幻工。R本人自食惡果不足惜励两,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囊颅。 院中可真熱鬧当悔,春花似錦、人聲如沸踢代。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胳挎。三九已至饼疙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間串远,已是汗流浹背宏多。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工儿惫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留澡罚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓肾请,卻偏偏與公主長(zhǎng)得像留搔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铛铁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容