Android their definition view it Bounceprogressbar

Source: Internet
Author: User
Tags cos

Reprint Please specify source: http://blog.csdn.net/bbld_/article/details/41246247 "Rocko's Blog"


A few days ago downloaded a very long time useless desktop cool dog to use the time, found that the songs loaded in the waiting progress bar effect is good (personal feeling). For example, the following:




Then take advantage of this weekend two days of cold weather, nest in the dormitory put down piles of operating system operations (the eye to copy a lesson of a lot of text ah ... Ah ...) Resolutely decided to tinker it out, and finally the effect such as the following (total feeling a bit discordant ah ·) :




The control can see that the shape of the choice and the use of pictures. Then the next step is the implementation process.

Suggestions for defining the view implementation are not clear see Guo Shen's Blog (View series 4): Android Layoutinflater Principle Analysis, take you step-by-step insight into the view (a) and the big corn this: Android own definition view--onmeasure. Measurespec source code flow thinking specific explanation


Define your own properties

It is common to define a view to use the properties of the view itself, and to rewrite the existing control is not necessary. Well, then what are the unique attributes of our Bounceprogressbar? The first thing to understand is that here Bounceprogressbar does not provide detailed progress performance of the implementation.

Think again: it needs each image size, called singlesrcsize, the type is dimension, the speed of jumping up and down. Call speed. Type is integer, shape, called shape, type is enumerated type, provides the realization of these shapes, original, Circle, Pentagon, rhombus, Heart are all known, and finally the necessary picture resources. Called src, the type is Reference|color. That can be a picture or a color value in a drawable.

Once you have the required attributes, create a resource file in the values directory (with the name arbitrary, as well as the name) to define these attributes, such as the following. The code may be some English, and the level is a bit of slag, but it is generally explained in front:

<?

XML version= "1.0" encoding= "Utf-8"?

><resources> <declare-styleable name= "Bounceprogressbar" > <!--the single child size-- <attr name= "Singlesrcsize" format= "Dimension"/> <!--the bounce animation one-way duration- <attr name= "Speed" format= "integer"/> <!--the child count. Originally wanted to be able to define their own number, but temporary personal implementation of some trouble, so do not add this--<!--<attr name= "Count" format= "integer" min= "1"/>- <!--the Progress child shape--<attr name= "shape" format= "enum" > <enum name= "Origina L "value=" 0 "/> <enum name=" Circle "value=" 1 "/> <enum name=" Pentagon "value=" 2 "/> <enum name= "Rhombus" value= "3"/> <enum name= "Heart" value= "4"/> </attr> <!--the Progress drawable resource--<attr name= "src" format= "Reference|color" ></attr> </declare-styleable></resources>

Then write the Bounceprogressbar class first, for example:

public class Bounceprogressbar extends View {//...}
Now it's possible to use our Bounceprogressbar in the layout. It's important to note here. We need to add the following code. The second line of namespace talent uses our properties and can also put it into the attributes of the root element.

        <org.roc.bounceprogressbar.bounceprogressbar            xmlns:bpb= "Http://schemas.android.com/apk/res-auto"            Android:layout_width= "Wrap_content"            android:layout_height= "wrap_content"            android:layout_ Centerhorizontal= "true"            android:layout_centervertical= "true"            bpb:shape= "Circle"            bpb:singlesrcsize= "8DP"            bpb:speed= "bpb:src="            #6495ED "/>
You define the property. Finally what we have to do is to get it in the code, where to get it, of course, is the Bounceprogressbar class of construction method, the relevant code such as the following:
Public Bounceprogressbar (Context context) {This (context, NULL, 0);} Public Bounceprogressbar (context context, AttributeSet Attrs) {This (context, attrs, 0);} Public Bounceprogressbar (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); Init (attrs);} private void init (AttributeSet attrs) {if (null = = Attrs) {return;} TypedArray a = GetContext (). Obtainstyledattributes (Attrs, r.styleable.bounceprogressbar); speed = A.getint ( r.styleable.bounceprogressbar_speed); size = A.getdimensionpixelsize (r.styleable.bounceprogressbar_ Singlesrcsize, shape = a.getint (r.styleable.bounceprogressbar_shape, 0); src = a.getdrawable ( R.STYLEABLE.BOUNCEPROGRESSBAR_SRC); A.recycle ();}
It is easier to get the property or to remember to recycle the Typedarray.

The first is to get the typedarray we define. Then there is a one-to-go get property value. Then someone may have to say, I clearly did not define r.styleable.bounceprogressbar_xxx these things ah. In fact, this is the position of the index in the Typedarray that the android itself has given us every attribute in the generated declare-styleable. You can not find something like r.styleable.speed, and how it corresponds, click into the R file to know, the value of R.styleable.bounceprogressbar_speed is 1, because speed is the 2nd attribute (0,1.), so you are sure that the position of the property is directly written A.getint (1, 250) is also possible.

The second parameter is the default value.


Shape of a graphic

After the property value is obtained. We are able to do the corresponding processing, here is the drawing shape of the acquisition, using the shape,src and size properties. Speed and size are also mentioned in the next point.

First we observed that three images have some gradient effect. I'm just simply doing the transparency process, which is to be transparent at once, and the effect is to be able to handle it a bit better and possibly optimize it later. The image resources obtained from SRC are drawable, whether colordrawable or bitmapdrawable. We need to convert it to size bitmap, and then use canvas to cut it in shape. As to why we should turn bitmap first, this is my practice. After reading the following operation, suppose there is a better way to communicate.

/** * DRAWABLE→BITMAP (the size is "size") */private Bitmap Drawable2bitmap (drawable drawable) {Bitmap Bitmap = bitmap.cr Eatebitmap (size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas (bitmap);d rawable.setbounds (0, 0, size, size);d Rawable.draw (canvas); return bitmap;}
Bitmap got, shape it we can operate, we first say Circle circle, Diamond Rhombus, pentagram Pentagon, say heart shape heart. Due to some different processing methods.

Like other Shapeimageview I see as if I like to deal with SVG. Look at their code, like this: Https://github.com/siyamed/android-shape-imageview seems a bit of a hassle. My treatment is comparatively simple.


Circle Circle, Diamond Rhombus, pentagram Pentagon

These shapes can be obtained using shapedrawable. We need to bitmapshader the renderer, which is required for the shapedrawable paint brush, and then need an empty bitmap bitmap, and then a Canvas.

For example, the following:

Bitmapshader Bitmapshader = new Bitmapshader (Srcbitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Bitmap Bitmap = bitmap.createbitmap (size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new canvas (bitmap); Path path; Shapedrawable shapedrawable = new shapedrawable (); Shapedrawable.getpaint (). Setantialias (True); Shapedrawable.getpaint (). Setshader (Bitmapshader); shapedrawable.setbounds (0, 0, size, size); Shapedrawable.setalpha (Alpha);
Canvas is the canvas on the shapedrawable. Bitmapshader is a renderer for shapedrawable brush paint. Used to render processing graphics (bitmap from Src drawable), the rendering mode chooses clamp. This means that assuming that the renderer is outside the original boundary range, the range of edge staining is copied.

Round, we can directly use the ready-made to:

Shapedrawable.setshape (New OvalShape ());
This shapedrawable is drawn out of the circle, of course, to call Shapedrawable.draw (canvas), the method, so that the bitmap will turn into a round Srcbitmap (the method passed in the number of parameters), this method of the complete code is given below.

Diamond, we are like this:

Path = new Path ();p Ath.moveto (SIZE/2, 0);p ath.lineto (0, SIZE/2);p Ath.lineto (SIZE/2, size);p ath.lineto (size, SIZE/2 );p ath.close (); Shapedrawable.setshape (new Pathshape (path, size, size));
is a square with a size on the side. Take the midpoint of each edge, and four points are connected together. We know that Android coordinates are generally the top left corner of the screen vertex is the origin of the coordinates, sitting punctuation found we connect the path is close.

So the Pathshape is a diamond. Polygons are almost identical and can be drawn in this way, as are the five angles below.

Description: All of the graphics here are drawn in a square with a length of size in the side.


The principle of the Pentagon is also used Pathshape, only it needs a bit more coordinate points ah. Careful calculation is required to adjust slowly.

Path = new path ();//The Angle of the pentagramfloat radian = (float) (Math.PI * 36/180); float radius = size/2;//in t  He middle of the radius of the pentagonfloat radius_in = (float) (RADIUS * Math.sin (RADIAN/2)/Math.Cos (Radian));//The Starting point of the Polygonpath.moveto ((float) (RADIUS * Math.Cos (RADIAN/2)), 0);p Ath.lineto ((float) (RADIUS * math.c OS (RADIAN/2) + radius_in * Math.sin (Radian)), (float) (Radius-radius * Math.sin (RADIAN/2)));p Ath.lineto ((float) (Radi US * MATH.COS (RADIAN/2) * 2), (float) (Radius-radius * Math.sin (RADIAN/2)));p Ath.lineto ((float) (RADIUS * Math.Cos (RA DIAN/2) + radius_in * Math.Cos (RADIAN/2)), (float) (RADIUS + radius_in * Math.sin (RADIAN/2)));p Ath.lineto ((float) (RA  Dius * Math.Cos (RADIAN/2) + radius * Math.sin (Radian)), (float) (radius + radius * Math.Cos (radian)));p Ath.lineto ((float) (RADIUS * Math.Cos (RADIAN/2)), (float) (radius + radius_in));p Ath.lineto ((float) (RADIUS * Math.Cos (RADIAN/2)-Radiu S * Math.sin (Radian)), (fLoat) (Radius + radius * Math.Cos (radian)));p Ath.lineto ((float) (RADIUS * Math.Cos (RADIAN/2)-radius_in * Math.Cos (Radi AN/2)), (float) (RADIUS + radius_in * Math.sin (RADIAN/2)));p Ath.lineto (0, (float) (Radius-radius * Math.sin (Radian/ 2)));p Ath.lineto ((float) (RADIUS * Math.Cos (RADIAN/2)-radius_in * Math.sin (Radian)), (float) (Radius-radius * math.si N (RADIAN/2)));p ath.close ();//make these points closed Polygonsshapedrawable.setshape (new Pathshape (path, size, size) ;
There's a lot of wiring.

。 Here the drawing of the five-angle shape is based on the angle of the specified five-angle and radius, and then determine the connection starting point. And the next point ... Finally closed, accidentally do not know where to go to.

Heart-shaped Heart

Path to draw the heart shape can not even straight line realization. Just started by using the path of the Quadto (x1, y1, x2, y2) method to draw the Bezier curve to achieve, found that the shape of the picture is not full, more like a cone (brain fill), so give up the way. Then found this about the heart-shaped introduction heart Curve, and then took his fourth method (for example), that is, the use of two oval shape to cut the implementation.



1. Draw an oval shape

   Canvas bitmap Bitmapshader and so on. The above code already has   Path = new Path ();   Paint paint = new paint ();   Paint.setantialias (true);   Paint.setshader (Bitmapshader);   Matrix matrix = new Matrix (); Control rotates   Region regions = new Area ();//crop a section of graphics   RECTF ovalrect = new RECTF (SIZE/4, 0, size-(SIZE/4), size); 
   path.addoval (Ovalrect, Path.Direction.CW);
2. Rotate the graphic. About 45 degrees .

   Matrix.postrotate (SIZE/2, SIZE/2);   Path.transform (matrix, path);


3, select the right half of the shape of the rotation, and use Cancas to draw this half of the heart shape

Path.transform (matrix, path); Region.setpath (Path, new region ((int) SIZE/2, 0, (int) size, (int) size); Canvas.drawpath ( Region.getboundarypath (), paint);



4, repeat 1, 2, 3 at the same time to change the direction angle and cut the area

Matrix.reset ();p ath.reset ();p ath.addoval (Ovalrect, Path.Direction.CW); Matrix.postrotate ( -42, SIZE/2, SIZE/2); Path.transform (matrix, path); Region.setpath (Path, new region (0, 0, (int) SIZE/2, (int) size); Canvas.drawpath ( Region.getboundarypath (), paint);
So we finished the heart-shaped picture cutting work. The resulting bitmap becomes heart-shaped:

This heart can see people.


The next step is to finish the drawing of your heart.



Drawing of view

When it comes to the drawing process of view, the following trilogy is required:

  • Measured--onmeasure (): Determines the size of the view
  • Layout--onlayout (): Determines the position of the view in ViewGroup
  • Draw--ondraw (): How to draw this view.


    Measured amount

    The measurement of the Bounceprogressbar control is still relatively simple. When the height and width of the wrap_content are 5 times times and 4 times times the size, the other case is to specify the width of the height as a detailed measurement of the value is good. Then determine the horizontal position of the three graphs in the control:

    @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); int sizewidth = Measurespec.getsize (widthmeasurespec); int sizeheight = Measurespec.getsize ( HEIGHTMEASURESPEC); int modewidth = Measurespec.getmode (widthmeasurespec); int modeheight = Measurespec.getmode ( HEIGHTMEASURESPEC); Setmeasureddimension (modewidth = = measurespec.exactly)?

    Mwidth = Sizewidth:mwidth, (modeheight = = measurespec.exactly)?

    Mheight = sizeheight:mheight); firstdx = MWIDTH/4-size/2;//horizontal position of first graphic SECONDDX = MWIDTH/2-SIZE/2;//...THIRDDX = 3 * MWIDTH/4-size/2;//...}

    When there is a width height that specifies a detailed value, Mwidth and Mheight are also set to be measured to the sizewidth and Sizeheight.



    Layout

    When it comes to layout, the first thing to understand is that the beat of the image is controlled by the property animation, what is the property animation? Let me say one thing: the ability to animate a property of an object in the form of an animated effect. You can look for information before you know it.

    The layout here determines the operation of the various positions in the view, which is generally not used as a single control. I'm here to initialize the animation and start the operation. The ability to see our Bounceprogressbar is three graphics in the beating.

    The encapsulation of three attributes is as follows:

    /** * firstbitmaptop ' s property. The change of the height through canvas is * onDraw () method. */private Property<bounceprogressbar, integer> firstbitmaptopproperty = new Property<bounceprogressbar, Integer> (Integer.class, "Firstdrawabletop") {@Overridepublic Integer get (Bounceprogressbar obj) {return Obj.firstbitmaptop;} public void Set (Bounceprogressbar obj, Integer value) {obj.firstbitmaptop = Value;invalidate ();};};/ * * secondbitmaptop ' s property. The change of the height through canvas is * onDraw () method. */private Property<bounceprogressbar, integer> secondbitmaptopproperty = new Property<bounceprogressbar, Integer> (Integer.class, "Seconddrawabletop") {@Overridepublic Integer get (Bounceprogressbar obj) {return Obj.secondbitmaptop;} public void Set (Bounceprogressbar obj, Integer value) {obj.secondbitmaptop = Value;invalidate ();};};/ * * thirdbitmaptop ' s property. The change of the height through canvas is * onDraw () method. */private Property<bounceprogRessbar, integer> thirdbitmaptopproperty = new Property<bounceprogressbar, integer> (Integer.class, " Thirddrawabletop ") {@Overridepublic Integer get (Bounceprogressbar obj) {return obj.thirdbitmaptop;} public void Set (Bounceprogressbar obj, Integer value) {obj.thirdbitmaptop = Value;invalidate ();};};
    The code for the OnLayout section is as follows:

    @Overrideprotected void OnLayout (Boolean changed, int left, int top, int. right, int. bottom) {super.onlayout (changed, left, Top, right, bottom), if (bouncer = = NULL | |!bouncer.isrunning ()) {Objectanimator firstanimator = Initdrawableanimator (fir Stbitmaptopproperty, speed, size/2,mheight-size); Objectanimator secondanimator = Initdrawableanimator ( Secondbitmaptopproperty, speed, size/2,mheight-size); Secondanimator.setstartdelay (+); objectanimator Thirdanimator = Initdrawableanimator (Thirdbitmaptopproperty, speed, size/2,mheight-size); Thirdanimator.setstartdelay (Bouncer) = new Animatorset (); Bouncer.playtogether (Firstanimator, SecondAnimator, Thirdanimator); Bouncer.start ();}} Private Objectanimator Initdrawableanimator (Property<bounceprogressbar, integer> property, int duration,int Startvalue, int endvalue) {Objectanimator animator = Objectanimator.ofint (this, property, Startvalue, Endvalue); Animator.setduration (duration); Animator.setrepeatcount (animation.infinite); animAtor.setrepeatmode (Valueanimator.reverse); Animator.setinterpolator (new Accelerateinterpolator ()); return animator ;}
    The value transformation of an animation is from size to mheight-size. The reason to subtract size is that the size range of the view itself is greater than (Mheight, mheight) on the left side of the canvas.


    Draw

    The work done here is not very much. is based on the horizontal position of each image. And the height controlled by the property animation to draw bitmap on the canvas.

    @Overrideprotected synchronized void OnDraw (canvas canvas) {/* Draw three bitmap */firstbitmapmatrix.reset (); Firstbitmapmatrix.posttranslate (FIRSTDX, firstbitmaptop); Secondbitmapmatrix.reset (); Secondbitmapmatrix.settranslate (SECONDDX, secondbitmaptop); Thirdbitmapmatrix.reset (); Thirdbitmapmatrix.settranslate (THIRDDX, thirdbitmaptop); Canvas.drawbitmap (Firstbitmap, FirstBitmapMatrix, MPaint) ; Canvas.drawbitmap (Secondbitmap, Secondbitmapmatrix, Mpaint); Canvas.drawbitmap (Thirdbitmap, ThirdBitmapMatrix, Mpaint);}
    The position is controlled by the matrix. Due to the deformation of the ground at that time, but now to remove the first.

    The overall drawing process is to control the placement of each image on the canvas through property animations, and call the Invalidate () method when the property changes to notify repainting. It seems to be the beating effect. The change in bounce speed is to set the interpolator for the animation to complete.


    Finish
    This article is written here, the complete source code I put on my GitHub (Https://github.com/zhengxiaopeng/BounceProgressBar), welcome you star, fork so it together.

  • Copyright notice: This article blog original article. Blogs, without consent, may not be reproduced.

    Android their definition view it Bounceprogressbar

    Related Article

    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.