Example sharing of cool horizontal and annular progress bars in Android applications _android

Source: Internet
Author: User
Tags drawtext getcolor

I. Overview
recently need to use the progress bar, faith does not repeat the principle of making wheels, on the GitHub on the search for some, see a few feel more good-looking progressbar, such as: Daimajia. A simple look at the code, the basic is inherited from view, thoroughly at the end of the customization of a progress bar. Staring at the gorgeous scroll bar, suddenly feel, why to write a scroll through the view, the system has provided the ProgressBar and its characteristics, we do not need to rebuild a, but the system is relatively ugly, different versions are not necessarily the same. So come to our goal: Change the way the system ProgressBar.
Yes, we do not have to go from 0 to build a ProgressBar, although the people look bad, but the characteristics and stability is just, we just need for its entire under the OK.
Next, we put down the effect chart:
1, the horizontal progress bar

2, the circular progress bar

Yes, this is our progress bar effect, the horizontal imitation of the Daimajia progress bar appearance. But we inherit ProgressBar, simple for its entire capacity, the code is clear and understandable. Why is that understandable?
Horizontal that progress bar, we will DrawLine () and DrawText (), then through the getwidth () to the width of the control, and then through the getprogress () to get progress, proportional control of the length of the drawing line, the word position is not minutes.

Two, implementing
  Horizontal scroll bar drawing definitely requires some properties, such as the color, width, color, size, and so on of the progress that has/hasn't been reached.
  Originally, I wanted to extract some properties from the system ProgressBar progressdrawable, and draw the required parameters from the inside. But, ultimately, it complicates the code. So you end up using custom attributes instead. When it comes to customizing attributes, you should be no stranger.
1, Horizontalprogressbarwithnumber
(1) Custom properties
Values/attr_progress_bar.xml:

<?xml version= "1.0" encoding= "Utf-8"?> <resources> <declare-styleable name= "Horizontalprogressbarwit Hnumber "> <attr name=" progress_unreached_color format= "color"/> <attr name= "Progress_reached_color "format=" Color "/> <attr name=" progress_reached_bar_height "format=" Dimension "/>" <attr name= "Progr" Ess_unreached_bar_height "format=" Dimension "/> <attr name=" progress_text_size "format=" Dimension "/>"  
    Lt;attr name= "Progress_text_color" format= "color"/> <attr name= "Progress_text_offset" format= "Dimension"/> <attr name= "progress_text_visibility" format= "enum" > <enum name= "visible" value= "0"/> ; enum name= "Invisible" value= "1"/> </attr> </declare-styleable> <declare-styleable name= "Roundprogressbarwidthnumber" > <attr name= "radius" format= "Dimension"/> </declare-styleable> &l 

 T;/resources>

(2) construct to get

public class Horizontalprogressbarwithnumber extends ProgressBar {private static final int default_text_size = 10; 
  private static final int default_text_color = 0XFFFC00D1; 
  private static final int default_color_unreached_color = 0XFFD3D6DA; 
  private static final int default_height_reached_progress_bar = 2; 
  private static final int default_height_unreached_progress_bar = 2; 
 
  private static final int default_size_text_offset = 10; 
  /** * Painter of all drawing things/protected Paint mpaint = new Paint (); 
  /** * Color of progress number */protected int mtextcolor = Default_text_color; 
 
  /** * Size of text (SP) */protected int mtextsize = sp2px (default_text_size); 
 
  /** * Offset of Draw progress/protected int mtextoffset = dp2px (Default_size_text_offset); /** * Height of reached progress bar */protected int mreachedprogressbarheight = DP2PX (default_height_reached_ 
 
  Progress_bar); 
  /** * Color of reached bar */protected int mreachedbarcolor = Default_text_color; 
  /** * Color of unreached Bar */protected int munreachedbarcolor = Default_color_unreached_color; /** * Height of unreached progress bar */protected int munreachedprogressbarheight = DP2PX (default_height_unre 
  Ached_progress_bar); 
   
  /** * View width except padding * * protected int mrealwidth; 
 
  Protected Boolean mifdrawtext = true; 
 
  protected static final int VISIBLE = 0; 
  Public Horizontalprogressbarwithnumber (context, AttributeSet attrs) {This (context, attrs, 0); } public Horizontalprogressbarwithnumber (context context, AttributeSet attrs, int defstyle) {Super (CO 
     
    ntext, attrs, defstyle); 
 
    Sethorizontalscrollbarenabled (TRUE); 
 
    Obtainstyledattributes (ATTRS); 
    Mpaint.settextsize (mtextsize); 
 
  Mpaint.setcolor (Mtextcolor); }/** * Get the styled attributes * * @parAM Attrs */private void Obtainstyledattributes (AttributeSet attrs) {//init values from custom attributes Final TypedArray attributes = GetContext (). Obtainstyledattributes (Attrs, R.styleable.horizontalprogressbar 
 
    Withnumber); 
            Mtextcolor = attributes. GetColor (R.styleable.horizontalprogressbarwithnumber_progress_text_color, 
    Default_text_color); 
        mtextsize = (int) attributes.getdimension (r.styleable.horizontalprogressbarwithnumber_progress_text_size, 
 
    Mtextsize); Mreachedbarcolor = attributes. GetColor (R.styleable.horizontalprogressbarwithnumber_progress_reache 
    D_color, Mtextcolor); Munreachedbarcolor = attributes. GetColor (r.styleable.horizontalprogressbarwithnumber_progress_unre 
    Ached_color, Default_color_unreached_color); Mreachedprogressbarheight = (int) attributes. Getdimension (R.Styleable. 
    Horizontalprogressbarwithnumber_progress_reached_bar_height, Mreachedprogressbarheight); Munreachedprogressbarheight = (int) attributes. Getdimension (r.styleable.horizontalprogressbarwithn 
    Umber_progress_unreached_bar_height, Munreachedprogressbarheight); Mtextoffset = (int) attributes. Getdimension (r.styleable.horizontalprogressbarwithnumber_progress_t 
 
    Ext_offset, Mtextoffset); 
            int textvisible = attributes. GetInt (r.styleable.horizontalprogressbarwithnumber_progress_text_visibility, 
    VISIBLE); 
    if (textvisible!= VISIBLE) {mifdrawtext = false; 
  } attributes.recycle (); 

 }

Well, it looks like the code is pretty long, but it's all about getting custom properties, and there's no technical content.

(3) Onmeasure
Just not out of the OnDraw inside write on the line, why to change the onmeasure, mainly because we all attributes such as the progress bar width to allow users to customize, so our measurement also have to change slightly.

@Override 
protected synchronized void onmeasure (int widthmeasurespec, 
    int heightmeasurespec) 
{ 
  int Heightmode = Measurespec.getmode (heightmeasurespec); 
 
  if (Heightmode!= measurespec.exactly) 
  { 
 
    float textHeight = (mpaint.descent () + mpaint.ascent ()); 
    int exceptheight = (int) (Getpaddingtop () + getpaddingbottom () + Math 
        . Max (Math.max Mreachedprogressbarheight, 
            munreachedprogressbarheight), Math.Abs (TextHeight)); 
 
    Heightmeasurespec = Measurespec.makemeasurespec (exceptheight, 
        measurespec.exactly); 
  } 
  Super.onmeasure (Widthmeasurespec, Heightmeasurespec); 
 
} 

Width We do not change, so the custom attribute does not involve width, height, only consider not exactly situation (user explicitly specified, we will ignore), according to padding and progress bar width to calculate what you want, if not exactly, We carry out exceptheight encapsulation and pass the control to the measurement height.
after the measurement, to our OnDraw ~ ~ ~
(4) OnDraw

@Override protected synchronized void OnDraw (Canvas Canvas) {canvas.save (); 
 
    The brush translates to the specified paddingleft, getheight ()/2 position, noting that the coordinates are later 0,0 canvas.translate (Getpaddingleft (), GetHeight ()/2); 
    Boolean noneedbg = false; 
    Current rate of progress and total value float radio = getprogress () * 1.0f/getmax (); 
    The reached width float progressposx = (int) (MREALWIDTH * radio); 
 
    The drawn text String text = getprogress () + "%"; 
    Get the width and height of the font float textWidth = mpaint.measuretext (text); 
 
    float TextHeight = (mpaint.descent () + mpaint.ascent ())/2; If the end is reached, the unreachable progress bar does not need to draw the if (Progressposx + textWidth > mrealwidth) {progressposx = Mrealwidth-textwi 
      Dth 
    noneedbg = true; 
    //Draw the reached progress float endx = PROGRESSPOSX-MTEXTOFFSET/2; 
      if (EndX > 0) {mpaint.setcolor (mreachedbarcolor); 
      Mpaint.setstrokewidth (Mreachedprogressbarheight); 
    Canvas.drawline (0, 0, endx, 0, Mpaint); 
//Draw Text    if (mifdrawtext) {mpaint.setcolor (mtextcolor); 
    Canvas.drawtext (text, Progressposx,-textheight, Mpaint); 
      //Draw the progress bar if (!noneedbg) {Float start = progressposx + MTEXTOFFSET/2 + textWidth; 
      Mpaint.setcolor (Munreachedbarcolor); 
      Mpaint.setstrokewidth (Munreachedprogressbarheight); 
    Canvas.drawline (Start, 0, mrealwidth, 0, Mpaint); 
 
  } canvas.restore (); @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, old 
    W, OLDH); 
 
  Mrealwidth = W-getpaddingright ()-Getpaddingleft (); 

 }

In fact, the core method is OnDraw, but, OnDraw is also very simple, draw lines, draw text, draw lines, the end.

There are two simple helper methods:

/** 
 * DP 2 px 
 * 
 * * @param 
 dpval 
/protected int dp2px (int dpval) 
{return 
  (int) Typedvalue.applydimension (Typedvalue.complex_unit_dip, 
      Dpval, Getresources (). Getdisplaymetrics ()); 
 
/** 
 * SP 2 px 
 * 
 * @param spval 
 * @return 
/protected int sp2px (int spval) 
{ 
  return (int) typedvalue.applydimension (typedvalue.complex_unit_sp, 
      Spval, Getresources (). Getdisplaymetrics () ); 
 
} 

Well, our horizontal progress to this end, is not very simple ~ ~ If you are a custom view, you also have to consider the progress update, consider the state of the destruction and recovery and other complex things.
Next look at our Roundprogressbarwidthnumber circular progress bar.

2, Roundprogressbarwidthnumber
the circular progress bar and the horizontal progress bar basic variables are consistent, so I let Roundprogressbarwidthnumber extends Horizontalprogressbarwithnumber.
Then what needs to be changed is the measurement and OnDraw:
Complete code:

Package Com.zhy.view; 
Import Android.content.Context; 
Import Android.content.res.TypedArray; 
Import Android.graphics.Canvas; 
Import Android.graphics.Paint.Cap; 
Import Android.graphics.Paint.Style; 
Import Android.graphics.RectF; 
 
Import Android.util.AttributeSet; 
 
Import COM.ZHY.LIBRARY.VIEW.R; public class Roundprogressbarwidthnumber extends Horizontalprogressbarwithnumber {/** * Mradius of view * 
 
  /private int mradius = dp2px (30); 
  Public Roundprogressbarwidthnumber {This (context, NULL); 
 
    Public Roundprogressbarwidthnumber (context, AttributeSet attrs) {Super (context, attrs); 
    Mreachedprogressbarheight = (int) (munreachedprogressbarheight * 2.5f); 
    TypedArray ta = context.obtainstyledattributes (attrs, R.styleable.roundprogressbarwidthnumber); 
    Mradius = (int) ta.getdimension (R.styleable.roundprogressbarwidthnumber_radius, Mradius); 
 
    Ta.recycle (); Mtextsize = SP2PX (14); 
    Mpaint.setstyle (Style.stroke); 
    Mpaint.setantialias (TRUE); 
    Mpaint.setdither (TRUE); 
 
  Mpaint.setstrokecap (Cap.round); @Override protected synchronized void onmeasure (int widthmeasurespec, int heightmeasurespec) {int h 
    Eightmode = Measurespec.getmode (Heightmeasurespec); 
 
    int widthmode = Measurespec.getmode (Widthmeasurespec); 
 
    int paintwidth = Math.max (Mreachedprogressbarheight, munreachedprogressbarheight); 
          if (Heightmode!= measurespec.exactly) {int exceptheight = (int) (Getpaddingtop () + Getpaddingbottom () 
      + Mradius * 2 + paintwidth); 
    Heightmeasurespec = Measurespec.makemeasurespec (Exceptheight, measurespec.exactly); 
          } if (Widthmode!= measurespec.exactly) {int exceptwidth = (int) (Getpaddingleft () + getpaddingright () 
      + Mradius * 2 + paintwidth); Widthmeasurespec = Measurespec.makemeasurespec (Exceptwidth, Measurespec.exactly); 
 
  } super.onmeasure (Heightmeasurespec, Heightmeasurespec); 
    @Override protected synchronized void OnDraw (Canvas Canvas) {String text = getprogress () + "%"; 
    Mpaint.gettextbounds (text, 0, Text.length (), mtextbound); 
    float textWidth = mpaint.measuretext (text); 
 
    float TextHeight = (mpaint.descent () + mpaint.ascent ())/2; 
    Canvas.save (); 
    Canvas.translate (Getpaddingleft (), Getpaddingtop ()); 
    Mpaint.setstyle (Style.stroke); 
    Draw unreaded Bar Mpaint.setcolor (Munreachedbarcolor); 
    Mpaint.setstrokewidth (Munreachedprogressbarheight); 
    Canvas.drawcircle (Mradius, Mradius, Mradius, Mpaint); 
    Draw reached Bar Mpaint.setcolor (Mreachedbarcolor); 
    Mpaint.setstrokewidth (Mreachedprogressbarheight); 
    float sweepangle = getprogress () * 1.0F/GETMAX () * 360; 
    Canvas.drawarc (New RECTF (0, 0, Mradius * 2, Mradius * 2), 0, Sweepangle, false, Mpaint); Draw Text Mpaint.setstyle (Style.fill); 
 
    Canvas.drawtext (text, MRADIUS-TEXTWIDTH/2, Mradius-textheight, Mpaint); 
 
  Canvas.restore (); 

 } 
 
}

First, obtain its proprietary attribute Mradius, then measure according to this property, and the measurement completes the drawing;
What about the drawing process?
Draw a smaller circle first, then draw a thicker radian, stacked together on the line. The text, drawing in the middle ~ ~ ~ Overall, no code volume.
OK, two progress bar is here, is not a lot easier to find. Overall design, there are some problems, if the extraction of a baseprogressbar for public properties, and then different kinds of progress bar inheritance to achieve their own measurement and appearance, so that the structure may be clearer ~ ~ ~

Third, the use
Layout file

<scrollview xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http:// Schemas.android.com/tools "xmlns:zhy=" Http://schemas.android.com/apk/res-auto "android:layout_width=" Match_ Parent "android:layout_height=" match_parent "> <linearlayout android:layout_width=" Match_parent "a ndroid:layout_height= "match_parent" android:orientation= "vertical" android:padding= "25DP" > <com.zh Y.view.horizontalprogressbarwithnumber android:id= "@+id/id_progressbar01" android:layout_width= "match_parent 
 
     
 
    "Android:layout_height=" wrap_content "android:layout_margintop=" 50dip "android:padding=" 5DP "/> <com.zhy.view.horizontalprogressbarwithnumber android:layout_width= "Match_parent" android:l ayout_height= "Wrap_content" android:layout_margintop= "50dip" android:padding= "5DP" android:progress= " "Zhy:progress_text_color=" #ffF53B03 "Zhy:p rogress_unreached_color= "#ffF7C6B7"/> <com.zhy.view.roundprogressbarwidthnumber android:id= "@+id/id _progress02 "android:layout_width=" match_parent "android:layout_height=" Wrap_content "Android:layout_" margintop= "50dip" android:padding= "5DP" android:progress= "a"/> <com.zhy.view.roundprogressbar Widthnumber android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:layout_m 
      argintop= "50dip" android:padding= "5DP" android:progress= "a" zhy:progress_reached_bar_height= "20DP" Zhy:progress_text_color= "#ffF53B03" zhy:radius= "60DP"/> </LinearLayout> </scrollview& 

 Gt

Mainactivity

Package Com.zhy.sample.progressbar; 
Import android.app.Activity; 
Import Android.os.Bundle; 
 
Import Android.os.Handler; 
Import Com.zhy.annotation.Log; 
 
Import Com.zhy.view.HorizontalProgressBarWithNumber; 
  public class Mainactivity extends activity {private Horizontalprogressbarwithnumber Mprogressbar; 
 
  private static final int msg_progress_update = 0x110; Private Handler Mhandler = new Handler () {@Log public void Handlemessage (Android.os.Message msg) {int P 
      rogress = Mprogressbar.getprogress (); 
      Mprogressbar.setprogress (++progress); 
         
      if (progress >=) {mhandler.removemessages (msg_progress_update); 
    } mhandler.sendemptymessagedelayed (msg_progress_update, 100); 
  }; 
 
  }; 
    @Log @Override protected void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
    Setcontentview (R.layout.activity_main); Mprogressbar = (horizontalprogressbarwithnumber) FindvieWbyid (R.ID.ID_PROGRESSBAR01); 
 
  Mhandler.sendemptymessage (msg_progress_update); 

 } 
 
}
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.