English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Android Custom Progress Bar Rounded Horizontal Progress Bar Example Detailed Explanation

1.This article will introduce you to the writing of custom progress bars, which is relatively simple, but there are still some knowledge points that need to be paid attention to:

invalidate() method
Application of RectF method
Application of onMeasure method

2.Principle

Paint3Layered rounded rectangles, the bottom layer is black, the second layer is gray, and the top layer is the progress bar color. The example is as follows:

3.Effect diagram

 

There are many other methods to implement rounded progress bars, such as filling rounded images in the Progress control and stretching the image to achieve the desired effect, although it sounds simple, it is still somewhat麻烦 to implement.

4.Explanation method

(1invalidate() method

invalidate() is used to refresh the View and must be performed on the UI thread. For example, when modifying the display of a view, you need to call invalidate() to see the re-drawn interface. The invocation of invalidate() removes the previous old view from the main UI thread queue. This method is generally used in custom controls.

(2)Application of RectF method

RectF is a method used to draw rectangles.

RectF(left, top, right, bottom), the meanings of the four parameters are the distances from the parent control to the top, left, right, and bottom margins of the rectangle. The following is illustrated by a diagram:

The drawRoundRect method is used to draw rounded rectangles. Its parameters are as follows:
Parameter Description

rect: The RectF object.
rx: The radius of the rounded corner in the x direction.
ry: The radius of the rounded corner in the y direction.
paint: The pen used for drawing.

(3)onMeasure method

Specify the size of a custom control on the screen. The two parameters of the onMeasure method are the size passed by the upper-level control, and they are a combination of mode and size. You need to get the mode by MeasureSpec.getMode(widthMeasureSpec) and get the size by MeasureSpec.getSize(widthMeasureSpec).

The several modes of onMeasure are EXACTLY, AT_MOST, and UNSPECIFIED.

[1]MeasureSpec.EXACTLY

50dip

[2]MeasureSpec.AT_MOST

MeasureSpec.AT_MOST indicates the maximum size. When the layout_width or layout_height of the control is specified as WRAP_CONTENT, the size of the control generally changes with the size of its child space or content. At this time, the size of the control only needs to be less than the maximum size allowed by the parent control. Therefore, the mode is AT_MOST, and the size provides the maximum size allowed by the parent control.

[3]MeasureSpec.UNSPECIFIED

MeasureSpec.UNSPECIFIED indicates an unspecified size, which is not common. Generally, the parent control is an AdapterView, and the mode is passed through the measure method.

5.activity_main.xml file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
xmlns:tools="http://schemas.android.com/tools"
android:id="@"+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.progresstest.MainActivity"
tools:ignore="MergeRootFrame" >
<com.example.progresstest.ProgressViewTest 
android:id="@"+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

6.ProgressViewTest.java file

package com.example.progresstest;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
public class ProgressViewTest extends View {
/**Maximum value of the progress bar*/
private float maxCount;
/**Current value of the progress bar*/
private float currentCount;
/**Pen*/
private Paint mPaint;
private int mWidth, mHeight;
public ProgressViewTest(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public ProgressViewTest(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ProgressViewTest(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
/***
* Set the maximum progress value
* @param maxCount
*/
public void setMaxCount(float maxCount) {
this.maxCount = maxCount;
}
/**
* Get the maximum progress value
*/
public double getMaxCount(){
return maxCount;
}
/***
* Set the current progress value
* @param currentCount
*/
public void setCurrentCount(float currentCount) {
this.currentCount = currentCount > maxCount ?63; maxCount : currentCount;
/**
* invalidate() is used to refresh the View, and it must be performed in the UI thread. For example, when modifying the display of a view,
* Call invalidate() to see the re-drawn interface. The call to invalidate() is to remove the previous old view from the main UI
* Pop from the thread queue. 
*/
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mPaint = new Paint();
//Set anti-aliasing effect
mPaint.setAntiAlias(true);
//Set the pen color
mPaint.setColor(Color.BLACK);
int round = mHeight/2;
/**
* RectF: draw a rectangle, the four parameters are left, top, right, bottom
* The type is a single-precision floating-point number
*/
RectF rf = new RectF(0, 0, mWidth, mHeight);
/*Draw a rounded rectangle with the background color of the pen*/
canvas.drawRoundRect(rf, round, round, mPaint);
/*Set the internal progress to gray*/
mPaint.setColor(Color.rgb(211, 211, 211))
RectF rectBlackBg = new RectF(2, 2, mWidth-2, mHeight-2);
canvas.drawRoundRect(rectBlackBg, round, round, mPaint);
//Set the progress bar progress and color
float section = currentCount/maxCount;
RectF rectProgressBg = new RectF(3, 3, (mWidth-3)*section, mHeight-3);
if(section != 0.0f) {
mPaint.setColor(Color.GREEN);
} else {
mPaint.setColor(Color.TRANSPARENT);
}
canvas.drawRoundRect(rectProgressBg, round, round, mPaint);
}
//dip * scale + 0.5f * (dip >= 0 &63; 1 : -1)
private int dipToPx(int dip){
float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dip * scale + 0.5f * (dip >= 0 &63; 1 : -1))//Add 0.5It is for rounding off
}
/**Specify the size of the custom control on the screen, the two parameters of the onMeasure method are provided by the upper control layer
* The size passed in, which is a value that combines mode and size, requires MeasureSpec.getMode(widthMeasureSpec)
* Obtain the mode, MeasureSpec.getSize(widthMeasureSpec) gets the size
* 
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
//MeasureSpec.EXACTLY, exact size
if (widthSpecMode == MeasureSpec.EXACTLY || widthSpecMode == MeasureSpec.AT_MOST) {
mWidth = widthSpecSize;
} else {
mWidth = 0;
}
//MeasureSpec.AT_MOST, maximum size, as long as it does not exceed the maximum size allowed by the parent control, MeasureSpec.UNSPECIFIED, unspecified size
if (heightSpecMode == MeasureSpec.AT_MOST || heightSpecMode == MeasureSpec.UNSPECIFIED) {
mHeight = dipToPx(20);
} else {
mHeight = heightSpecSize;
}
//Set the actual size of the control
setMeasuredDimension(mWidth, mHeight);
}
}

MainActivity.java file

package com.example.progresstest;
import android.support.v7.app ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class MainActivity extends ActionBarActivity {
private ProgressViewTest progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progress = (ProgressViewTest) findViewById(R.id.progressbar);
progress.setMaxCount(100);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <=progress.getMaxCount(); i++) {
Message msg = new Message();
msg.arg1 = i;
msg.what = 0x01;
handler.sendMessage(msg);
try {
//Every 0.1Second progress forward1
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
Handler handler = new Handler(){
public void handleMessage(Message msg) {
if(msg.what==0x01{
progress.setCurrentCount(msg.arg1);
}
};
};
}

The above-mentioned is the detailed explanation of the rounded horizontal progress bar example of Android custom progress bar introduced by the editor to everyone. I hope it will be helpful to everyone. If you have any questions, please leave a message, and the editor will reply to everyone in time. Thank you very much for everyone's support for the Naoan tutorial website!

Statement: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email to report violations, and provide relevant evidence. Once verified, this site will immediately delete the infringing content.)

You May Also Like