Custom View implementation Pendulum effect progress bar Pendulumview

Source: Internet
Author: User

I saw an iOS component Pendulumview on the Internet, which realized the animation effect of the pendulum. Because the native progress bar does not look good, you can customize the view to achieve this effect, and later can be used to load the page's progress bar.

No more nonsense, first.

The bottom black Edge is recorded accidentally recorded, can be ignored.

Since it's a custom view, we'll follow the standard process, the first step, custom attribute custom properties

Creating a Property file

Create a new Attrs.xml file in the Res->values directory of your Android project with the following file contents:

[HTML] View plain copy

<?xml version= "1.0" encoding= "Utf-8"?>

<resources>

<declare-styleable name= "Pendulumview" >

<attr name= "Globenum" format= "integer"/>

<attr name= "Globecolor" format= "Color"/>

<attr name= "Globeradius" format= "Dimension"/>

<attr name= "Swingradius" format= "Dimension"/>

</declare-styleable>

</resources>

Where Declare-styleable's Name property is used to reference the property file in code. The Name property, in general, is the class name of our custom view, which is more intuitive.

Using Styleale, the system can do many constants (int[] arrays, subscript constants) and so on, to simplify our development work, such as the following code in the use of r.styleable.pendulumview_golbenum and so on is the system for our automatic generation.

The Globenum property represents the number of small balls, Globecolor represents the ball color, Globeradius represents the sphere radius, and the Swingradius represents the swing Radius Read property value

Reading a property value through Typedarray in a custom view's construction method can also get the property value through AttributeSet, but if the property value is a reference type, then only the ID is obtained, and the real property value is still to be obtained by resolving the ID. And Typedarray directly helped us to complete the above work.

[Java] View plain copy

Public Pendulumview (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);

To read a custom property value using Typedarray

TypedArray ta = context.getresources (). Obtainattributes (Attrs, r.styleable.pendulumview); int count = Ta.getindexcount ();

for (int i = 0; i < count; i++) {

int attr = Ta.getindex (i);

Switch (attr) {

Case R.styleable.pendulumview_globenum:

Mglobenum = Ta.getint (attr, 5);

Break

Case R.styleable.pendulumview_globeradius:

Mgloberadius = Ta.getdimensionpixelsize (attr, (int) typedvalue.applydimension (typedvalue.complex_unit_px, 16, Getresources (). Getdisplaymetrics ());

Case R.styleable.pendulumview_globecolor:

Mglobecolor = Ta.getcolor (attr, Color.Blue);

Case R.styleable.pendulumview_swingradius:

Mswingradius = Ta.getdimensionpixelsize (attr, (int) typedvalue.applydimension (typedvalue.complex_unit_px, 16, Getresources (). Getdisplaymetrics ());

}

}

Ta.recycle (); Avoid problems the next time you read

Mpaint = new Paint ();

Mpaint.setcolor (Mglobecolor);

}

Overriding the Onmeasure () method

[Java] View plain copy

@Override

protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); int widthmode = Measurespec.getmode (widthmeasurespec); int widthsize = Measurespec.getsize ( WIDTHMEASURESPEC); int heightmode = Measurespec.getmode (heightmeasurespec); int heightsize = Measurespec.getsize ( HEIGHTMEASURESPEC);//height for ball radius + swing radius

int height = Mgloberadius + mswingradius;//width = Swing radius + (number of balls-1) * Ball diameter int width = Mswingradius + Mgloberadius * 2 * (mglobenum -1) + mswingradius;//If the measurement mode is exactly, use the recommended value directly, such as not for exactly (general handling wrap_content case), use your own calculated width-height setmeasureddimension ( Widthmode = = measurespec.exactly)? Widthsize:width, (Heightmode = = measurespec.exactly)? Heightsize:height);}

which

[Java] View plain copy

int height = Mgloberadius + mswingradius;<pre name= "code" class= "java" >int width = Mswingradius + Mgloberadius * 2 * (mGlobeNum-1) + Mswingradius; used to process the measurement mode for the At_most, generally the width of the custom view setting in order to wrap_content, at this time through the number of small balls, radius, swing radius, etc. to calculate the width of the view, such as:

Take the number of balls 5 as an example, the size of the view is red rectangular region rewrite OnDraw () method

650) this.width=650; "Src=" Http://s4.51cto.com/wyfs02/M00/87/53/wKiom1fc6TiB4XeRAAAQZR33f_8699.png-wh_500x0-wm_3 -wmp_4-s_3577198470.png "title=" 1.png "alt=" Wkiom1fc6tib4xeraaaqzr33f_8699.png-wh_50 "/>

[Java] View plain copy

@Override

protected void OnDraw (canvas canvas) {

Super.ondraw (canvas);

Draw other balls except the left and right two balls

for (int i = 0; i < mGlobeNum-2; i++) {canvas.drawcircle (Mswingradius + (i + 1) * 2 * Mgloberadius, Mswingradius, mGl Oberadius, mpaint);}

if (Mleftpoint = = NULL | | mrightpoint = = NULL) {//Initialize the most left and right ball coordinates

Mleftpoint = new Point (Mswingradius, mswingradius); mrightpoint = new Point (Mswingradius + Mgloberadius * 2 * (Mglobenum- 1), Mswingradius);//Start Swinging animation

Startpendulumanimation ();

}

Draw left and right balls

Canvas.drawcircle (Mleftpoint.x, Mleftpoint.y, Mgloberadius, Mpaint); Canvas.drawcircle (MRightPoint.x, MRightPoint.y , Mgloberadius, mpaint);}

The OnDraw () method is the key to customizing view, where the view is drawn in the body of the method. The code first draws a small ball other than the left-most-right ball, and then judges the coordinate values of the two spheres, if it is the first draw and the coordinate value is empty, the two spherical coordinates are initialized and the animation is turned on. Finally, by mleftpoint,mrightpoint the x, Y value, draw left and right two balls.

Where Mleftpoint,mrightpoint are Android.graphics.Point objects, they are used only to store the x, Y coordinate information of the left and right balls.

Using Property animations

[Java] View plain copy

public void Startpendulumanimation () {

Using Property animations

Final Valueanimator anim = Valueanimator.ofobject (new Typeevaluator () {@Override

Public Object evaluate (float fraction, object Startvalue, Object Endvalue) {//Parameter fraction is used to indicate the completion of the animation, We calculate the current animation value based on it double angle = math.toradians (fraction); int x = (int) ((mswingradius-mgloberadius) * Math.sin (angle)) ; int y = (int) ((mswingradius-mgloberadius) * Math.Cos (angle)); Point point = new Point (x, y);

return point;

}

}, New Point (), New Point ());

Anim.addupdatelistener (New Valueanimator.animatorupdatelistener () {@Override

public void Onanimationupdate (Valueanimator animation) {Point point = (point) animation.getanimatedvalue ();// Get the current fraction value

float fraction = anim.getanimatedfraction ();//Determine whether the fraction is first reduced and then increased, that is, whether it is in the upward swing state//In each of the upward swing when the ball is switched

if (lastslope && fraction > mlastfraction) {isnext =!isnext;

}

By constantly changing the left and right ball of x, Y coordinate value to achieve the animation effect//Use Isnext to determine whether the left small ball motion, or the isnext of the ball if (a) {

When the left ball swings, the right ball is placed in the initial position

Mrightpoint.x = Mswingradius + Mgloberadius * 2 * (mGlobeNum-1); mrightpoint.y = Mswingradius;

Mleftpoint.x = Mswingradius-point.x;

Mleftpoint.y = Mgloberadius + point.y;

} else {

When the right ball swings, the left ball is placed in the initial position

Mleftpoint.x = Mswingradius;

Mrightpoint.y = Mswingradius;

Mrightpoint.x = Mswingradius + (mGlobeNum-1) * Mgloberadius * 2 + point.x;mrightpoint.y = Mgloberadius + point.y;

}

Invalidate ();

Lastslope = fraction < mlastfraction;

Mlastfraction = fraction;

}

});

Set Perpetual loop Playback

Anim.setrepeatcount (valueanimator.infinite);//set cycle mode to play in reverse order

Anim.setrepeatmode (Valueanimator.reverse); anim.setduration (200);

Set up the tween to control the rate at which the animation changes

Anim.setinterpolator (New Decelerateinterpolator ()); Anim.start ();

}

The Valueanimator.ofobject method is used so that the point object can be manipulated and more visually specific. There is also the use of the Ofobject method of the custom Typeevaluator object, resulting in a fraction value, which is a decimal number changed from 0-1. Therefore, the latter two parameters of the method Startvalue (new Point ()), Endvalue () is not meaningful, or can directly not write, here is written mainly for the sake of understanding. The same can be obtained directly using the Valueanimator.offloat (0f, 1f) method to obtain a fractional change from 0-1.

[Java] View plain copy

Final Valueanimator anim = Valueanimator.ofobject (new Typeevaluator () {@Override

Public Object evaluate (float fraction, object Startvalue, Object Endvalue) {//Parameter fraction is used to indicate the completion of the animation, We calculate the current animation value based on it double angle = math.toradians (fraction); int x = (int) ((mswingradius-mgloberadius) * Math.sin (angle)) ; int y = (int) ((mswingradius-mgloberadius) * Math.Cos (angle)); Point point = new Point (x, y);

return point;

}

}, New Point (), New Point ());

by fraction, we calculate the angular change value when the ball swings, and the value represented by the 0-90 degree Mswingradius-mgloberadius is the length of the Green Line in the figure, the direction of the swing, The path of the center of the ball is an arc with a radius of (Mswingradius-mgloberadius), with a change of x value (Mswingradius-mgloberadius) *sin (angle), The Change y value is (mswingradius-mgloberadius) *cos (angle) corresponds to the ball of the actual center coordinates of (mswingradius-x,mgloberadius+y) The right ball motion is similar to the left, only the direction is different. The right ball is the actual center coordinate (Mswingradius + (mGlobeNum-1) * Mgloberadius * 2 + x,mgloberadius+y) visible on both sides of the ball's ordinate is the same, only the horizontal axis is different.

[Java] View plain copy

float fraction = anim.getanimatedfraction ();//Determine whether the fraction is first reduced and then increased, that is, whether it is in the upward swing state//In each of the upward swing when the ball is switched

if (lastslope && fraction > mlastfraction) {isnext =!isnext;

}

Record whether the last fraction has been reduced

[Java] View plain copy

Lastslope = fraction < mlastfraction;

Record the last fraction

Mlastfraction = fraction;

These two pieces of code is used to calculate when to switch the motion of the ball, the animation set the loop playback, and the loop mode for the reverse play, so the animation of a period of the ball is thrown together with the small ball falling process. In this procedure, the value of fraction is first 0 to 1, and then 1 to 0. So when is the beginning of a new cycle of animation? is in the small ball is about to throw up, at this time to switch the ball, you can achieve the left side of the ball drop after the right ball thrown up, the right ball fell after the left small ball cast animation effect.

So how do you capture this point in time?

The fraction value increases continuously when the ball is thrown, and the fraction value decreases when the ball falls. The moment the ball is about to be thrown is the moment when the fraction from diminishing to increasing. The code records whether the last fraction is decreasing, and then compares whether this time the fraction is increasing, if two conditions are set up to switch the ball of motion.

[Java] View plain copy

Anim.setduration (200);

Set up the tween to control the rate at which the animation changes

Anim.setinterpolator (New Decelerateinterpolator ()); Anim.start ();

Set the duration of the animation to 200 milliseconds, the reader can change the value to achieve the purpose of modifying the ball swing speed.

Set the animation of the tween, because the ball is thrown is a gradual deceleration of the process, falling is a gradual acceleration of the process, so use decelerateinterpolator to achieve deceleration effect, in reverse play for the acceleration effect.


This article is from the "12063979" blog, please be sure to keep this source http://12073979.blog.51cto.com/12063979/1853371

Custom View implementation Pendulum effect progress bar Pendulumview

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.