Reprint Strange Annotated Source: Wang 亟亟 's way of Daniel
Continue our material design content, this article is about the progress bar, the previous one is the switch address is as follows: http://blog.csdn.net/ddwhan0123/article/details/50592579
Progress and dynamics
Reduce visual changes as much as possible before users can view and interact with the content, making the application loading process as pleasant as possible. Each operation can only be rendered by an activity indicator, for example, for a refresh operation, you cannot use the Refresh bar and indicate with a dynamic circle.
Indicator type
In the operation, for the completion section to be determined, using the identified indicators, they can give the user a quick understanding of the time required for an operation.
In the operation, for the completion of the partial uncertainty, the user needs to wait for a certain period of time, without informing the user station and the time required, you can use an indeterminate indicator.
There are two types of indicators: a linear progress indicator and a circular progress indicator. You can use any of these to indicate deterministic and nondeterministic operations.
Linear progress Indicator
The linear progress indicator should always be shown from 0% to 100% and must not be reversed from high to low. If there are multiple operations in progress in a queue, use a progress indicator to indicate the overall time required to wait. This way, when the indicator reaches 100%, it will not return to 0% and start again.
The linear progress bar should be placed at the edge of the header or an area of the block.
Post 2 official demos:
Bar-like
Ring-shaped
Implementation of the example
High anti-high imitation, package structure:
OK, let's take a look at the code (the explanation explains the ring-shaped, simple strip)!
finalstatic"http://schemas.android.com/apk/res/android"; int backgroundColor = Color.parseColor("#1E88E5"); publicProgressBarCircularIndeterminate(Context context, AttributeSet attrs) { super(context, attrs); setAttributes(attrs); }
21-30, constructors and methods for invoking initialization
protected void SetAttributes(AttributeSet attrs) {Setminimumheight (UTILS.DPTOPX ( +, Getresources ())); Setminimumwidth (UTILS.DPTOPX ( +, Getresources ()));//set background Color //Color by resource intBacgroundcolor = Attrs.getattributeresourcevalue (Androidxml,"Background",-1);if(Bacgroundcolor! =-1) {SetBackgroundColor (Getresources (). GetColor (Bacgroundcolor)); }Else{//Color by hexadecimal intBackground = Attrs.getattributeintvalue (Androidxml,"Background", -1);if(Background! =-1) SetBackgroundColor (background);ElseSetBackgroundColor (Color.parsecolor ("#1E88E5")); } setminimumheight (Utils.dptopx (3, Getresources ())); }
33-55 rows, gets the XML parameter setting color, sets the minimum size of the value.
protected int Makepresscolor(){intR = ( This. BackgroundColor >> -) &0xFF;intg = ( This. BackgroundColor >>8) &0xFF;intB = ( This. BackgroundColor >>0) &0xFF;//R = (r+90 > 245)? 245:r+90;//G = (g+90 > 245)? 245:g+90;//b = (b+90 > 245)? 245:b+90; returnColor.argb ( -, R, G, b); }
61-79 Line, the implementation of the color gradient, called when the first occurrence occurs.
@Override protectedvoidonDraw(Canvas canvas) { super.onDraw(canvas); iffalse) drawFirstAnimation(canvas); if0) drawSecondAnimation(canvas); invalidate(); }
72-81 lines, the specific drawing of the operation, because to determine whether the first time, so called 2 different methods, we look at each.
floatRadius1 =0;floatRadius2 =0;intCont =0;BooleanFirstanimationover =false;/** * Draw First animation of view * @param Canvas */ Private void drawfirstanimation(Canvas canvas) {if(Radius1 < GetWidth ()/2) {Paint paint =NewPaint (); Paint.setantialias (true); Paint.setcolor (Makepresscolor ()); Radius1 = (Radius1 >= getwidth ()/2)? (float) getwidth ()/2: radius1+1; Canvas.drawcircle (GetWidth ()/2, GetHeight ()/2, RADIUS1, paint); }Else{Bitmap Bitmap = Bitmap.createbitmap (Canvas.getwidth (), Canvas.getheight (), Bitmap.Config.ARGB_8888); Canvas temp =NewCanvas (bitmap); Paint paint =NewPaint (); Paint.setantialias (true); Paint.setcolor (Makepresscolor ()); Temp.drawcircle (GetWidth ()/2, GetHeight ()/2, GetHeight ()/2, paint); Paint Transparentpaint =NewPaint (); Transparentpaint.setantialias (true); Transparentpaint.setcolor (Getresources (). GetColor (Android. R.color.transparent)); Transparentpaint.setxfermode (NewPorterduffxfermode (PorterDuff.Mode.CLEAR));if(cont >= -) {Radius2 = (radius2 >= getwidth ()/2)? (float) getwidth ()/2: radius2+1; }Else{Radius2 = (radius2 >= getwidth ()/2-UTILS.DPTOPX (4, Getresources ()))? (float) getwidth ()/2-UTILS.DPTOPX (4, Getresources ()): radius2+1; } temp.drawcircle (GetWidth ()/2, GetHeight ()/2, Radius2, Transparentpaint); Canvas.drawbitmap (Bitmap,0,0,NewPaint ());if(Radius2 >= getwidth ()/2-UTILS.DPTOPX (4, Getresources ())) cont++;if(Radius2 >= getwidth ()/2) Firstanimationover =true; } }
83-121, the method to be called is drawn for the first time.
If the radius of a circle has a size then the size of the drawing is not based on the size of the space (it must be 0 at first, then slowly self-increment, that is, our gray circle is getting bigger effect)
When it grows to a certain extent, it begins to draw the hollow circle part, and the hollow circle is gradually hollowed out until the size of the control entity is completely animated to stop. The whole change after the end of the bone to determine whether the first time the Firstanimationover state changes
The whole process invalidate (); Makes the logic execute continuously.
intARCD =1;intArcO =0;floatRotateangle =0;intLimite =0;/** * Draw Second animation of view * @param Canvas */ Private void drawsecondanimation(Canvas canvas) {if(ArcO = = limite) arcd+=6;if(Arcd >=290|| ArcO > Limite) {arco+=6; arcd-=6; }if(ArcO > Limite +290) {limite = ArcO; ArcO = limite; ARCD =1; } Rotateangle + =4; Canvas.rotate (Rotateangle,getwidth ()/2, GetHeight ()/2); Bitmap Bitmap = Bitmap.createbitmap (Canvas.getwidth (), Canvas.getheight (), Bitmap.Config.ARGB_8888); Canvas temp =NewCanvas (bitmap); Paint paint =NewPaint (); Paint.setantialias (true); Paint.setcolor (BackgroundColor);//Temp.drawargb (0, 0, 0, 255);Temp.drawarc (NewRECTF (0,0, GetWidth (), GetHeight ()), ArcO, ARCD,true, paint); Paint Transparentpaint =NewPaint (); Transparentpaint.setantialias (true); Transparentpaint.setcolor (Getresources (). GetColor (Android. R.color.transparent)); Transparentpaint.setxfermode (NewPorterduffxfermode (PorterDuff.Mode.CLEAR)); Temp.drawcircle (GetWidth ()/2, GetHeight ()/2, (GetWidth ()/2)-UTILS.DPTOPX (4, Getresources ()), transparentpaint); Canvas.drawbitmap (Bitmap,0,0,NewPaint ()); }
131-160, not the first time the implementation of the drawing, here I will explain the important part of the logic.
if(arcO == limite) arcD+=6; if290 || arcO > limite){ arcO+=6; arcD-=6; } if290){ limite = arcO; arcO = limite; arcD = 1; }
Large Arc maximum value is 290, full on the contraction, in the end all grow, with 2 variables to do the inverse calculation of the difference, 290 is the boundary value
canvas.rotate(rotateAngle,getWidth()/2, getHeight()/2);
Rotation operation, self-increment 4 per angle
Analysis:
Is the first time to go in to draw a scale from the center of the effect, and then all is to walk 290 circular arc enlargement of the infinite cycle of calculation painting, the calculation of this part of the logic or a bit of brain, we can think carefully.
Source: Https://github.com/ddwhan0123/BlogSample/blob/master/MaterialDesignProgress.zip
The Progreesbar of Material design Learning