打造極緻MaterialDesign動畫風格Button - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 技術分享 >

打造極緻MaterialDesign動畫風格Button

發表時(shí)間:2020-11-5

發布人(rén):融晨科技

浏覽次數:38


========================================================
做者兇qiujuer
專客兇blog.csdn.net/qiujuer
網站兇www.qiujuer.net
課怯兇Genius-Android
孜撬說(shuō)門鲻處兇http://blog.csdn.net/qiujuer/article/details/42471119
—”¨之(zhī)課,用于(yú)課;初教者的(de)心态,庸共勉餓
========================================================


正在(zài)我的(de)沃那粕拘已經有兩篇閉于(yú)Material Design風格的(de)按鈕實現。正在(zài)第一那中隻史岽純的(de)實現了(le/liǎo)動畫的(de)波紋效出(chū)有雅棘而(ér)正在(zài)第兩篇中對垂行了(le/liǎo)必定的(de)裁減取劣化,末了(le/liǎo)實現可能主動挪動到(dào)兩頭腸位的(de)動畫;誠然二者緊可用,但是(shì)正在(zài)我的(de)利用中來(lái)收渾跋扈了(le/liǎo)然必定的(de)紊,裙┬些掏诨裏擊會呈現波紋速度的(de)運道(dào)展夷罾φ谏。
正在(zài)罩位那中粗帶你挨造一個(gè)極緻的(de)Material Design動畫風格Button多少脆少正在(zài)我勘磕牡飽牡瞅平易近圓當焙帽瀕臨了(le/liǎo)。

效出(chū)有雅

小我


[img]http://img.blog.csdn.net/20150107005627266

平易近圓


[img]http://img.blog.csdn.net/20150106224503527
可能看吃觳乜蹦上(shàng)好出(chū)有肚。

闡發


尾先我們來(lái)分解一下平易近圓的(de)兇
[img]http://img.blog.csdn.net/20150106224459468
正在(zài)那裏我朝少前盡了(le/liǎo)最鶴蠡個(gè)按鈕隙荭的(de)持絕多張寬圖片的(de)環境,哪當ツ倒圖片我們可能看出(chū)以(yǐ)下環境兇
  • 平易近圓也(yě)是(shì)采納雲粑火哺,返斂角盡形火哺多少那個(gè)取我末了(le/liǎo)步所夏骣踴韓一樣)
  • 其分集速度尊崇遞加,雲裟的(de)時(shí)辰目畢蘋閃便過
  • 雲粑波紋色采一背出(chū)有變動
  • 控取按鈕合體配風光漸漸加深
  • 裏擊掏诨正在(zài)左下角,但是(shì)哪當ツ倒分集環境來(lái)看其火波雲裟漸漸背按糯控恿闼殇靠近
  • 那些也(yě)便勢兌們必要(yào / yāo)實現的(de)朝分。

實現講理


  • 雲粑分集,第一那中有報告 [Material Design] 叫︺做一個(gè)Material風格、動畫的(de)按鈕(MaterialButton)
  • 兩頭靠近,第兩那中有報告 [Material Design] MaterialButton 效出(chū)有雅盡階 動畫主動挪動盡行對埔妲出(chū)有雅棘出(chū)庸凝有必定的(de)誤好,出(chū)庸凝其誤幸盈于(yú)光陽抵那菲握,拼蟾缁有影忙δ當ツ倒局
  • 分集速度遞加,那個(gè)可能經過過程扇髅動畫的(de) Interpolator 來(lái)辦理,那改在(zài) 滲進排鼓懂裏Animation光陽插值Interpolator類 中有陳細擋厣紹
  • 配風便褂深,那個(gè)不(bù)過便實鄰雲粑波紋下酪畫造一層,乓°的(de)色采漸漸加墒點OK;誠然借必要(yào / yāo)寄看的(de)是(shì)其圓窖糸況。

我們第兩輾市的(de)按畔府所掖啃很哪當ツ倒的(de)好淨我總結出(chū)以(yǐ)下寂兇
  1. 兩頭靠近的(de)速度把持沙不(bù)對
  2. 合體的(de)既≠ Interpolator 類扇髅不(bù)對,誠然一樣是(shì)既≠,但是(shì)可能看出(chū)平易近圓的(de)骛步很快,我後遞加很緩,那個(gè)可能經過過程初初環崮時(shí)辰傳進 Interpolator 好肥辦理
  3. 火蔔仆彩把持不(bù)對,色采該當出(chū)有變動,變鬥崮昊脘風光的(de)色采
  4. 出(chū)左射風光變動的(de)過程,那感旋晨嚯家醒加,同時(shí)那臘一個(gè)細節,其末了(le/liǎo)的(de)色采并出(chū)有加到(dào)最深,哪當ツ倒約蝦帽于(yú)波紋色脖磕80%兩頭
  5. 出(chū)有考慮圓窖糸況,正在(zài)第兩那中如出(chū)有殉柝取實斂角,其波紋粗會超出(chū)圓狡兌後消得降。

代碼


出(chū)有知講你玫鄰做的(de)過程中是(shì)可念過,我們的(de)動畫實鄰映收裏擊 onTouch() 的(de)笨蹦上(shàng)赓絕的(de)該β觸收 onDraw() 而(ér)後畫造來(lái)的(de),取一個(gè)按鈕的(de)分賴楞也(yě)便是(shì)那麽兩改圓,最多爲(wéi / wèi)了(le/liǎo)便當我枚讨賴濫天圓借有一個(gè) onMeasure() .所以(yǐ)我們能裏出(chū)多麽一個(gè)類兇

Class


public class TouchEffectAnimator {


    public TouchEffectAnimator(View mView) {

    }

    public void onMeasure() {

    }

    public void onTouchEvent(final MotionEvent event) {

    }

    public void onDraw(final Canvas canvas) {

    }

    private void startAnimation() {
  
    }

    private void cancelAnimation() {

    }

    private void fadeOutEffect() {
    
    }
}
一個(gè)類,那個(gè)覽傳染感動于(yú)一個(gè)控取,所以(yǐ)我們必要(yào / yāo)傳進一個(gè) View.
而(ér)後我們供給一個(gè) onMeasure() 辦法用于(yú)初初化下度寬度等肥據;onTouchEvent() 誠然使┟來(lái)正在(zài)控取中觸收裏擊腳嗡所用的(de);onDraw() 那個(gè)無薪也(yě)是(shì)控取中調用,用來(lái)畫造所用;一個(gè)動畫誠進要(yào / yāo)平辦繁懲裁撤辦犯,誠然正在(zài)波紋動畫後我們借須依閱是(shì) "濃出(chū)" 的(de)動畫。
我後我麽弘念,其勢兌們須依閱動畫範例不(bù)過便是(shì)那麽多少種,我們何出(chū)有課一路呢集

擺列

public enum TouchEffect {
    Move,
    Ease,
    Ripple,
    None
}
正在(zài)那個(gè)擺輛平辨别代表兇一邊分集一邊挪動到(dào)兩頭,無波紋隻左掃進濃出(chū),純分集出(chū)有挪動的(de)範例,出(chū)有動畫的(de)範例。
下酪們來(lái)看肯複蕩蛐的(de)鄙環境。

靜态鄙


    private static final Interpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator(2.8f);
    private static final Interpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
    private static final int EASE_ANIM_DURATION = 200;
    private static final int RIPPLE_ANIM_DURATION = 300;
    private static final int MAX_RIPPLE_ALPHA = (int) (255 * 0.8);
辨别是(shì)兇動畫既≠、加靠唰出(chū)有雅薊濃進濃出(chū)默認光陽200漢想,分集時(shí)菇憚認300漢想,最哪當ツ倒的(de)團度爲(wéi / wèi)255的(de)80%用于(yú)濃進濃出(chū)。主色爲(wéi / wèi)255 100%。
正在(zài)那裏,既≠效出(chū)有遜市之(zhī)全部一個(gè)2.8,其緊張傳染感動是(shì)使分集效出(chū)有雅正在(zài)呈第盡大(dà)概的(de)快 多少起迪掐蔽小猿瑕),我後期盡大(dà)概的(de)緩多少加強觸摸感觸)

必需鄙


    private View mView;
    private int mClipRadius;
    private int mAnimDuration = RIPPLE_ANIM_DURATION;
    private TouchEffect mTouchEffect = TouchEffect.Move;
    private Animation mAnimation = null;
一個(gè)View,一個(gè)圓角弧度,一個(gè)動畫光陽,一個(gè)動畫範例,最鶴蠡個(gè)動畫類多少正在(zài)那琅春慊無益用屬薪畫,而(ér)實瀝備采納最目本的(de)動畫,采納回調老副接扇髅好肥)

雲粑肮鄙


    private float mMaxRadius;
    private float mRadius;
一個(gè)最哪當ツ倒肮衄一個(gè)當前肮舾.所掖啃最哪當ツ倒肮衄正在(zài)我勘磕牡飽牡剮多種環境兇如出(chū)有雅是(shì)挪動方式那麽其最哪當ツ倒肮殺除六撼區能達到(dào)起碼邊的(de)75%便行了(le/liǎo);如出(chū)有雅實劣分集,如出(chū)有雅映收裏擊的(de)是(shì)最左下角,那麽其殺除地(dì / de)區最好能達到(dào)其對角的(de)少度;更具勾回定理可能裏出(chū)很是(shì)起碼邊的(de)1.25倍。

坐标鄙


    private float mDownX, mDownY;
    private float mCenterX, mCenterY;
    private float mPaintX, mPaintY;
裏蛔鲽背醅兩頭坐背醅當前雲裟坐标

畫筆鄙


    private Paint mPaint = new Paint();
    private RectF mRectRectR = new RectF();
    private Path mRectPath = new Path();
    private int mRectAlpha = 0;
腋;畫背醅一個(gè)地(dì / de)區,一個(gè)地(dì / de)區所逝世潮磕Path略步衄一個(gè)地(dì / de)區團度

濃出(chū)把城


    private boolean isTouchReleased = false;
    private boolean isAnimatingFadeIn = false;
那兩蓋緊張用于(yú)把持濃出(chū)動畫觸收的(de)機會,我們可能那麽背孀
正在(zài)映收一背按碰柝擁濫拾便算分集動畫實現了(le/liǎo)頁蚧背幸掃出(chū)動畫,弄動畫正在(zài)映收開釋時(shí)觸收;如出(chū)有雅映收裏擊後緩速擡起那麽正在(zài)擡起時(shí)肯杜有磕骣有及觸收濃出(chū)動畫,要(yào / yāo)比及分集動畫實現後才觸收;所以(yǐ)一蓋是(shì)是(shì)可開釋按鈕,别的(de)一噶殼是(shì)可動畫渡酒。

動畫監聽


    private Animation.AnimationListener mAnimationListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            isAnimatingFadeIn = true;
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            isAnimatingFadeIn = false;
            // Is un touch auto fadeOutEffect()
            if (isTouchReleased) fadeOutEffect();
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    };
膳春沔圓才朔慫,把吃焖寒才觸收濃出(chū)動畫,那麽那老繭個(gè)監聽器便使┟來(lái)監聽其初步動畫自逢的(de),渡酒後調度值,如出(chū)有雅此時(shí)映收開收按鈕則觸收濃出(chū)效出(chū)有雅。OK,持絕餓

初初化


    public TouchEffectAnimator(View mView) {
        this.mView = mView;
        onMeasure();
    }

    public void onMeasure() {
        mCenterX = mView.getWidth() / 2;
        mCenterY = mView.getHeight() / 2;

        mRectRectR.set(0, 0, mView.getWidth(), mView.getHeight());

        mRectPath.reset();
        mRectPath.addRoundRect(mRectRectR, mClipRadius, mClipRadius, Path.Direction.CW);
    }
正在(zài)控取觸收 onMeasure() 辦法的(de)時(shí)辰回調弄籃媚 onMeasure() 辦犯,正在(zài)弄辦法中我們裏出(chū)戳闼殇坐背醅初初化一個(gè)少圓形地(dì / de)區,而(ér)後目據地(dì / de)區取圓角肮初初化一個(gè)Path略捕。

好肥扇髅


    public void setAnimDuration(int animDuration) {
        this.mAnimDuration = animDuration;
    }

    public TouchEffect getTouchEffect() {
        return mTouchEffect;
    }

    public void setTouchEffect(TouchEffect touchEffect) {
        mTouchEffect = touchEffect;
        if (mTouchEffect == TouchEffect.Ease)
            mAnimDuration = EASE_ANIM_DURATION;
    }

    public void setEffectColor(int effectColor) {
        mPaint.setColor(effectColor);
    }

    public void setClipRadius(int mClipRadius) {
        this.mClipRadius = mClipRadius;
    }
汲杌膳春沔有那麽逗媚鄙,那麽那裏供給了(le/liǎo)一皓辦法用于(yú)初初化利用,辨别是(shì)兇
動畫光陽,獲得動畫範例,扇髅動畫範例,扇髌掀捉色,扇髅控擁濫圓角弧度。

動畫朝分


    private void startAnimation() {
        Animation animation = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if (mTouchEffect == TouchEffect.Move) {
                    mRadius = mMaxRadius * interpolatedTime;
                    mPaintX = mDownX + (mCenterX - mDownX) * interpolatedTime;
                    mPaintY = mDownY + (mCenterY - mDownY) * interpolatedTime;
                } else if (mTouchEffect == TouchEffect.Ripple) {
                    mRadius = mMaxRadius * interpolatedTime;
                }

                mRectAlpha = (int) (interpolatedTime * MAX_RIPPLE_ALPHA);
                mView.invalidate();
            }
        };
        animation.setInterpolator(DECELERATE_INTERPOLATOR);
        animation.setDuration(mAnimDuration);
        animation.setAnimationListener(mAnimationListener);
        mView.startAnimation(animation);
    }

    private void cancelAnimation() {
        if (mAnimation != null) {
            mAnimation.cancel();
            mAnimation.setAnimationListener(null);
        }
    }

    private void fadeOutEffect() {
        Animation animation = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                mRectAlpha = (int) (MAX_RIPPLE_ALPHA - (MAX_RIPPLE_ALPHA * interpolatedTime));
                mView.invalidate();
            }
        };
        animation.setInterpolator(ACCELERATE_INTERPOLATOR);
        animation.setDuration(EASE_ANIM_DURATION);
        mView.startAnimation(animation);
    }

  • 三個(gè)辦法中,裁撤最複純了(le/liǎo),調用時(shí)斷定,而(ér)後裁辰爆并把監聽器扇髅爲(wéi / wèi) null.
  • 濃出(chū)動畫中兇我玫鄰其辦法回調量等髅我們的(de)團度衛久加的(de)方式,哪當ツ倒最哪當ツ倒遞加到(dào)最小;每拆緊刷兄位拆界裏;背萊慮扇髅當光陽,動畫實叭緩而(ér)鶴蠡下變快消得降得降降,而(ér)閡=動畫。
  • 正在(zài)初步動畫辦法中兇我們一樣正在(zài)回調中除我們的(de)鄙肥據;正在(zài)那酪們必要(yào / yāo)斷定,如出(chū)有雅是(shì)通頌又集,那貌鹨們便分集到(dào)洞喀的(de)肮便OK,如出(chū)有雅是(shì)Move 範例我玫硫必要(yào / yāo)變動其坐彼ィ其公式爲(wéi / wèi) C = A+多少B-A)*T0谝後扇髅團度尊崇删少到(dào)最哪當ツ倒,鷗度使┟于(yú)頗姣地(dì / de)區風波粑地(dì / de)區。

觸收辦法


    public void onTouchEvent(final MotionEvent event) {

        if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
            isTouchReleased = true;
            if (!isAnimatingFadeIn) {
                fadeOutEffect();
            }
        }
        if (event.getActionMasked() == MotionEvent.ACTION_UP) {
            isTouchReleased = true;
            if (!isAnimatingFadeIn) {
                fadeOutEffect();
            }
        } else if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            // Gets the bigger value (width or height) to fit the circle
            mMaxRadius = mCenterX > mCenterY ? mCenterX : mCenterY;
            // This circle radius is 75% or fill all
            if (mTouchEffect == TouchEffect.Move)
                mMaxRadius *= 0.75;
            else
                mMaxRadius *= 2.5;

            // Set default operation to fadeOutEffect()
            isTouchReleased = false;
            isAnimatingFadeIn = true;

            // Set this start point
            mPaintX = mDownX = event.getX();
            mPaintY = mDownY = event.getY();

            // This color alpha
            mRectAlpha = 0;

            // Cancel and Start new animation
            cancelAnimation();
            startAnimation();
        }
    }
正在(zài)觸收辦法中,我們辨斃須要(yào / yāo)判犢嗲R∶撤/擡起/按下 早縱。
  1. 正在(zài)裁撤跟擡起早縱中 我們緊盡行烈孀變動按鈕自逢鄙 isTouchReleased 爲(wéi / wèi)開釋棘我毫有犢嗲可渡酒動畫,如出(chū)有雅渡酒則觸收濃出(chū)動畫。
  2. 按下早縱兇計較出(chū)起碼肮衄此中 0.75 代表膳春沔道(dào)的(de)兇75%;2.5代表的(de)是(shì)膳春沔道(dào)的(de) 1.25苯衄那辣瞅爲(wéi / wèi)是(shì)一半,所以(yǐ)乘2 了(le/liǎo);是(shì)罩位朝分該當放正在(zài) onMeasure() 辦法中。
  3. 我後我們扇髅 開釋按鈕鄙 isTouchReleased 爲(wéi / wèi) false,扇髅動畫初步 isAnimatingFadeIn 爲(wéi / wèi) true。獲裏裏蛔鲽背醅扇髅團度爲(wéi / wèi)0,然降先行一拆裁辰爆而(ér)後初步動畫。

onDraw()


    public void onDraw(final Canvas canvas) {
        // Draw Area
        mPaint.setAlpha(mRectAlpha);
        canvas.drawPath(mRectPath, mPaint);

        // Draw Ripple
        if (isAnimatingFadeIn && (mTouchEffect == TouchEffect.Move
                || mTouchEffect == TouchEffect.Ripple)) {
            // Canvas Clip
            canvas.clipPath(mRectPath);
            mPaint.setAlpha(MAX_RIPPLE_ALPHA);
            canvas.drawCircle(mPaintX, mPaintY, mRadius, mPaint);
        }
    }
那個(gè)辦房嗲最鶴蠡個(gè)辦犯,也(yě)是(shì)較閡婺的(de)一改圓,我們的(de)膠匣有雅便靠那個(gè)辦法了(le/liǎo)。
尾先誠然是(shì)畫城景朝分,正在(zài)畫之(zhī)前誠然便是(shì)扇髅配風便夠弄配風光是(shì)一個(gè)随動畫光陽變動瞪,陳細陳兜張春沔動畫朝分。
而(ér)毫有犢嗲但是(shì)平動畫,果爲(wéi / wèi)濃沉勘頁鲇嗅觸收弄辦法但是(shì)來(lái)出(chū)湧造雲粑地(dì / de)區朝分,所以(yǐ)必要(yào / yāo)斷定多少.毫有犢嗲但是(shì)蝕口必要(yào / yāo)畫造雲粑的(de)動畫範例;再而(ér)後便是(shì)畫造陳細的(de)雲粑地(dì / de)區了(le/liǎo),辨别便是(shì)坐标跟肮艋但是(shì)那爛﹄要(yào / yāo)寄看的(de)是(shì),正在(zài)畫造前我們調用了(le/liǎo) canvas.clipPath(mRectPath); 。
canvas.clipPath(mRectPath)兇那個(gè)的(de)傳染感動便是(shì)剪切,意思是(shì)剪強殘冰分,而(ér)後正在(zài)剪切後的(de)畫倉蟻畫造;多麽便辦勒圓角時(shí)溢出(chū)的(de)紊,果爲(wéi / wèi)剪切後的(de)畫布便那麽哪當ツ當ャ便逆霏當汊朝也(yě)勢掇法隐示的(de)。

利用


public class GeniusButton extends Button implements Attributes.AttributeChangeListener {
    private TouchEffectAnimator touchEffectAnimator = null;

    public void setTouchEffect(TouchEffect touchEffect) {
        if (touchEffect == TouchEffect.None)
            touchEffectAnimator = null;
        else {
            if (touchEffectAnimator == null) {
                touchEffectAnimator = new TouchEffectAnimator(this);
                touchEffectAnimator.setTouchEffect(touchEffect);
                touchEffectAnimator.setEffectColor("this color");
                touchEffectAnimator.setClipRadius(20);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (touchEffectAnimator != null)
            touchEffectAnimator.onMeasure();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (touchEffectAnimator != null)
            touchEffectAnimator.onDraw(canvas);
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (touchEffectAnimator != null)
            touchEffectAnimator.onTouchEvent(event);
        return super.onTouchEvent(event);
    }
}
正在(zài)你捉義的(de)控取末着膳春沔的(de)圓法盡行式昌化調用便OK。
實正在(zài)如古來(lái)道(dào)弄動畫類,拼蟾缁有範圍于(yú)Button,你可能任意的(de)扇髅到(dào)你的(de)控詠襞春沔,如TextView 頁可能出(chū)有是(shì)捉義的(de)控取,Android 本逝世的(de)頁可能多少;必要(yào / yāo)扇骼镤中的(de)3個(gè)辦法回調也(yě)便OK;哪當ツ倒家可能嘗嘗;而(ér)後把效出(chū)有雅辨别強一下;稹我感觸很棒的(de)~

附取


算是(shì)闡發完了(le/liǎo),下裏改梢碼跟我闡發時(shí)畫的(de)一皓圖,闆诒鉛表明。


[img]http://img.blog.csdn.net/20150107004651610
[img]http://img.blog.csdn.net/20150107004738000
[img]http://img.blog.csdn.net/20150107004813203

代碼


裏慌鲩抄
========================================================
做者兇qiujuer
專客兇blog.csdn.net/qiujuer
網站兇www.qiujuer.net
課怯兇Genius-Android
孜撬說(shuō)門鲻處兇http://blog.csdn.net/qiujuer/article/details/42471119
—”¨之(zhī)課,用于(yú)課;初教者的(de)心态,庸共勉餓
========================================================

相關案例查看更多