Create the ultimate material Design Animation Style button

Source: Internet
Author: User

========================================================
Qiujuer
Blog:Blog.csdn.net/qiujuer
Website:Www.qiujuer.net
Open Source Library:Genius-android
Reprint Please specify Source: http://blog.csdn.net/qiujuer/article/details/42471119

--open source of learning, for open source, beginner's mentality, with June mutual encouragement!
========================================================

Order

In my article there were two button implementations about the material design style. In the first chapter is simply the implementation of the animation ripple effect, and in the second section of the expansion and optimization, the final realization can automatically move to the center of the animation, although both are available, but in my use has found a certain problem, such as some locations click on the operation of the ripple speed problem.

In this chapter you will be presented with an extreme material design animation style button; At least in my opinion it's quite close to the official.

Effect Personal
Official


It can be seen that it's basically almost there.

Analysis

First, let's take a look at the official:


Here I intercepted the last button corresponding to a few pictures of the case, from the picture we can see the following situation:

    • The official also uses circular water waves, non-rounded rectangular waves (this is not the same as I thought at first)
    • Its diffusion rate gradually decreases, the center of the time a basic flash on the
    • The circular ripple color has not changed
    • Control button Overall background color gradually deepened
    • Click on the position in the lower right corner, but from the diffusion point of view the center of the water is gradually moving closer to the button control centre
    • These are the parts we need to implement.

Implementation principle

    • Circular diffusion, the first chapter of [Material Design] teaches you to do a Material style, animated button (Materialbutton)
    • Center Close, the second chapter is about [Material Design] Materialbutton effect advanced animation automatic movement to align the effect, but there is a certain deviation, but the deviation lies in the control of time, does not affect the overall situation
    • The diffusion velocity is decreasing, this can be solved by animating the Interpolator, which is described in detail in the animation time interpolation Interpolator class of penetration comprehension.
    • Background color deepened, this is nothing more than a circular ripple below the next layer, the layer of color gradually deepened on OK; Of course, it is also important to note the fillet situation.

We have a big gap in the second button. I summed up the following points:

    1. The center is moving in the wrong speed control.
    2. Overall deceleration interpolator class setting is not correct, although the same is slowed down, but you can see the official start quickly, and then decline very slow, this can be initialized by the time passed to the Interpolator parameter resolution
    3. Wave color control is not correct, the color should not change, the color of the background color change
    4. Without the background color change process, this process needs to be added, and here is a detail, the final color is not added to the deepest, about the equivalent of about 80% of the ripple color
    5. Without considering the fillet, in the second chapter if the control is rounded, its ripple will go beyond the fillet and disappear.

Code

Do not know whether you do in the process of thinking, our animation is in the user click OnTouch () on the basis of the constant Refresh trigger OnDraw () and then drawn, with a button of the joint point is so two places, up to the convenience of our combination of places there is a Onmeasure (). So we can draw a class like this:

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 () { c13/>}}
A class that acts on a control, so we need to pass in a View.

Then we provide a onmeasure () method for initializing data such as height width, ontouchevent () is of course used to trigger a click event in the control; OnDraw () This is called in the control, which is used to draw the , an animation of course need to start methods and cancellation methods, of course, after the Ripple animation we also need to "fade out" animation.

Then we think, it is the type of animation we need is just a few, why don't we fit together?

Enumeration
public enum Toucheffect {    Move,    Ease,    Ripple,    None}
In this enumeration are represented:one side of the diffuser moves to the center, no ripple only fades, pure diffusion does not move the type, no animated type。

Let's take a look at the variables in the main class.

static variables

    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 = $;    private static final int ripple_anim_duration =;    private static final int max_ripple_alpha = (int) (255 * 0.8);
are: animation deceleration, acceleration effect, fade default time 200 milliseconds, diffusion time default 300 milliseconds, the maximum transparency is 255 of 80% for fading. The main color is 255 100%.

Here, the deceleration effect of all a 2.8, its main role is to make the diffusion effect in the initial as fast as possible (play to hide the small circle), and later as slow as possible (enhanced touch feeling)

Required variables

    Private View MView;    private int Mclipradius;    private int manimduration = ripple_anim_duration;    Private Toucheffect mtoucheffect = Toucheffect.move;    Private Animation manimation = null;
A view, a rounded arc, an animation time, an animation type, and the last animation class (where property animations are not used, but prepare to use the most basic animations, using callbacks to set parameters directly)

Circle RADIUS Variable

    private float Mmaxradius;    private float Mradius;
A maximum radius, a current radius, a maximum radius, in my opinion there are a number of cases: if it is a mobile mode, the maximum radius of the sweep region can reach the longest side of the 75% on the line; if it is pure diffusion, if the user clicks on the bottom right corner, then its sweep area is best to reach its diagonal length And a more Pythagorean theorem can be drawn to 1.25 times times the longest side.

Coordinate variables

    Private float mdownx, mdowny;    Private float Mcenterx, mcentery;    Private float mpaintx, mpainty;
Click Coordinates, center coordinates, current circle coordinates

Brush variables

    Private Paint Mpaint = new paint ();    Private RECTF mrectrectr = new RECTF ();    Private path Mrectpath = new Path ();    private int mrectalpha = 0;
A brush, an area, a path path generated by a region, a region transparency

Fade Control variables

    Private Boolean istouchreleased = false;    Private Boolean Isanimatingfadein = false;
These two variables are primarily used to control the timing of fade-out animation triggering, and we can think of:

When the user has been pressing the control, even if the diffusion animation is finished and does not fade out the animation, the animation is released when the user triggers; If the user is lifted immediately after clicking on the lift will not trigger the fade animation, wait until the diffusion animation is completed before triggering; So one variable is whether to release the button and whether the animation ends.

Animation monitoring

    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) {        }    };
Just said above, control its release trigger fade animation, then here this listener is used to listen to its start animation state, after the end of the adjustment value, if the user released the button will trigger fade effect. OK, go on!

Initialization

    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);    }
When the control triggers the Onmeasure () method, callback the class's Onmeasure () method, in which we derive its central coordinates, initialize a rectangular area, and then initialize a path path based on the region and radius of the fillet.

Parameter settings

    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;    }
Since there are so many variables, here are a few ways to initialize the use, namely:

Animation time, gets the animation type, sets the animation type, sets the color, sets the fillet radian of the control.

Animation section

    private void Startanimation () {Animation Animation = new Animation () {@Override protect Ed void applytransformation (float interpolatedtime, transformation t) {if (Mtoucheffect = = Toucheffect.mov                    E) {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 PR otected 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); }

    • Three methods, cancellation is the simplest, the call is judged, then canceled, and the listener is set to null.
    • Fade out Animation: We set our transparency in its method callbacks to a descending form, from the largest to the smallest; Refresh the interface each time, followed by setting its time, the animation is slow and then quickly disappear, and then start the animation.
    • In the Start animation method: We are also in the callback in addition to our variable data, here we need to judge, if it is normal diffusion, then we will spread to the corresponding radius is OK, if the move type we need to change its coordinates. The formula is C = a + (b-a) *t, and then the transparency is gradually increased to the maximum, which is used for all areas of the non-circular area.


Trigger method

    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 he ight) to fit the circle Mmaxradius = Mcenterx > Mcentery?            Mcenterx:mcentery; This circle radius was 75% or fill all if (mtoucheffect = = toucheffect.move) Mmaxradius *= 0.7            5;            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 (); }    }
In the triggering method, we need to judge separately: Cancel/lift/press.

    1. In the cancel and lift operations we have all done: change the button state variable istouchreleased to release, and then determine whether to end the animation, if the end of the trigger fade animation .
    2. Press operation: Calculates the longest radius, where 0.75 represents the above: 75%; 2.5 means 1.25 times times the above, because it is half, so multiply by 2 ; This part should be placed in the Onmeasure () method.
    3. Then we set the release button variable istouchreleased to False, set the animation to start Isanimatingfadein to true. Get the click Coordinates, set the transparency to 0, then cancel once, then start the animation .


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);        }    }
This method is the last and the more central one, and our results depend on this method.

First of all, of course, draw the background part, before the painting is of course set the background color, this background color is a change with the amount of animation time, detailed in the animation section above.

Then decide whether to start the animation, because the fade-out will also trigger the method but do not draw the circular area part, so you need to judge, then determine whether it is a need to draw a circular animation type, and then to draw a specific circular area, respectively, is the coordinates and radius; but it's important to note that Before drawing we call Canvas.clippath (Mrectpath);.

Canvas.clippath (Mrectpath): This function is cut, meaning to cut the canvas portion, and then draw on the cut canvas, which solves the problem of the fillet overflow, because the cut canvas is so big you can even draw outside is not displayed.

Use

public class Geniusbutton extends Button implements Attributes.attributechangelistener {private toucheffectanimator to    Ucheffectanimator = null; public void Settoucheffect (Toucheffect toucheffect) {if (Toucheffect = = Toucheffect.none) Toucheffectan        Imator = 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.onmea        Sure (Widthmeasurespec, heightmeasurespec);    if (toucheffectanimator! = null) toucheffectanimator.onmeasure (); } @Override protected void OnDraw (canvas canvas) {if (toucheffectanimator! = null) Toucheffectani Mator.ondraw (CANVAS);    Super.ondraw (canvas); } @Override public boolean ontouchevent (Motionevent event) {if (toucheffectanimator! = null) Touc        Heffectanimator.ontouchevent (event);    Return Super.ontouchevent (event); }}
It is OK to instantiate the call as above in your custom control.
In fact, now the animation class, not limited to the button, you can arbitrarily set up on your control, such as TextView can not be custom control, Android native can also, only need to set the 3 method callback is OK; you can try it. And then switch the effect separately; it feels great.

Attachment

Analysis is finished, the following is attached to the source code and my analysis of some drawings, auxiliary interpretation.

Figure




Code

Click to view

========================================================
Qiujuer
Blog:Blog.csdn.net/qiujuer
Website:Www.qiujuer.net
Open Source Library:Genius-android
Reprint Please specify Source: http://blog.csdn.net/qiujuer/article/details/42471119

--open source of learning, for open source, beginner's mentality, with June mutual encouragement!
========================================================

Create the ultimate material Design Animation Style button

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.