2.3.7 ProgressBar (Progress Bar)
Category Android Basic Tutorial
Introduction to This Section:
This section introduces the ProgressBar, a fundamental UI control in Android. The ProgressBar has many application scenarios, such as when a user is logging in and the background is sending a request, as well as waiting for the server to return information, which is when a progress bar is used. Or when performing some time-consuming operations that require a longer waiting time, without a prompt, users might think the program has crashed or the phone has frozen, which greatly reduces the user experience. Therefore, adding a progress bar where time-consuming operations are needed, to let users know that the program is running and to intuitively inform users of the current task's progress! Using a progress bar can bring such convenience! Alright, let's start explaining the content of this section~ By the way, the official API documentation for ProgressBar is: ProgressBar
1. Common Attribute Explanation and Basic Example
From the official documentation, we see such a class hierarchy diagram:
The ProgressBar inherits from the View class, with direct subclasses including AbsSeekBar and ContentLoadingProgressBar. Among them, the subclasses of AbsSeekBar include SeekBar and RatingBar, which shows that these two are also implemented based on the ProgressBar.
Explanation of Common Attributes:
>
android:max: The maximum value of the progress bar
android:progress: The value of the progress bar that has been completed
android:progressDrawable: Set the Drawable object corresponding to the track
android:indeterminate: If set to true, the progress bar does not accurately display the progress
android:indeterminateDrawable: Set the Drawable object for the progress bar that does not display progress
android:indeterminateDuration: Set the duration of the progress bar that does not accurately display progress
android:secondaryProgress: Secondary progress bar, similar to video playback where one is the current playback progress and the other is the buffering progress, the former is set through the progress attribute!
Correspondingly, in Java, we can call the following methods:
>
getMax(): Returns the upper limit of the range of this progress bar
getProgress(): Returns the progress
getSecondaryProgress(): Returns the secondary progress
incrementProgressBy(int diff): Specifies the increased progress
isIndeterminate(): Indicates whether the progress bar is in indeterminate mode
setIndeterminate(boolean indeterminate): Sets indeterminate mode
Next, let's take a look at the example of the default progress bar provided by the system!
Example of System Default ProgressBar:
Running Effect Picture:
Implementation Layout Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<!-- System-provided circular progress bars, in order of large, medium, and small -->
<ProgressBar
style="@android:style/Widget.ProgressBar.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ProgressBar
style="@android:style/Widget.ProgressBar.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- System-provided horizontal progress bar -->
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="18" />
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:indeterminate="true" />
</LinearLayout>
Well, apart from the second one, the rest are not very appealing... The system-provided ones definitely cannot meet our needs! Next, let's explain how we handle the progress bar in actual development!
2. Using Animation to Replace the Circular ProgressBar
The first solution is to use a set of continuous images to form a frame animation. When a progress diagram is needed, make the animation visible, and when it is not needed, make the animation invisible! And this animation is usually implemented using AnimationDrawable! Okay, let's define an AnimationDrawable file:
PS: The images used: [ProgressBar Image Material Package.zip Set this parameter to the aforementioned animation resource, but the size of the progress bar pattern cannot be directly modified; it requires modification in the Java code. If you set the width and height and these dimensions are too large, you will see multiple progress bars... weigh the pros and cons yourself.
3. Custom Circular Progress Bar
>
You may feel frustrated after reading section 2, thinking "Wow, this is so misleading, using an animation to deceive people, haha," but in actual development, it's like this. Of course, the above situation only applies to occasions where progress does not need to be displayed. If you need to display progress, it's useless. Alright, let's look at a simple custom circular progress bar from the internet next! The code is quite simple, easy to understand, and if you're interested, you can take a look or make relevant extensions.
Running effect picture:
Implementation code:
Custom View class:
/**
* Created by Jay on 2015/8/5 0005.
*/
public class CirclePgBar extends View {
private Paint mBackPaint;
private Paint mFrontPaint;
private Paint mTextPaint;
private float mStrokeWidth = 50;
private float mHalfStrokeWidth = mStrokeWidth / 2;
private float mRadius = 200;
private RectF mRect;
private int mProgress = 0;
//Target value, change as you wish
private int mTargetProgress = 90;
private int mMax = 100;
private int mWidth;
private int mHeight;
public CirclePgBar(Context context) {
super(context);
init();
}
public CirclePgBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CirclePgBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
//Initialize related parameters
private void init() {
mBackPaint = new Paint();
mBackPaint.setColor(Color.WHITE);
mBackPaint.setAntiAlias(true);
mBackPaint.setStyle(Paint.Style.STROKE);
mBackPaint.setStrokeWidth(mStrokeWidth);
mFrontPaint = new Paint();
mFrontPaint.setColor(Color.GREEN);
mFrontPaint.setAntiAlias(true);
mFrontPaint.setStyle(Paint.Style.STROKE);
mFrontPaint.setStrokeWidth(mStrokeWidth);
mTextPaint = new Paint();
mTextPaint.setColor(Color.GREEN);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(80);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
//Override the onMeasure method for measuring size and the core method onDraw() for drawing the View
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getRealSize(widthMeasureSpec);
mHeight = getRealSize(heightMeasureSpec);
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
initRect();
float angle = mProgress / (float) mMax * 360;
canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius, mBackPaint);
canvas.drawArc(mRect, -90, angle, false, mFrontPaint);
canvas.drawText(mProgress + "%", mWidth / 2 + mHalfStrokeWidth, mHeight / 2 + mHalfStrokeWidth, mTextPaint);
if (mProgress < mTargetProgress) {
mProgress += 1;
invalidate();
}
}
public int getRealSize(int measureSpec) {
int result = 1;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.UNSPECIFIED) {
//Calculate by yourself
result = (int) (mRadius * 2 + mStrokeWidth);
} else {
result = size;
}
return result;
}
private void initRect() {
if (mRect == null) {
mRect = new RectF();
int viewSize = (int) (mRadius * 2);
int left = (mWidth - viewSize) / 2;
int top = (mHeight - viewSize) / 2;
int right = left + viewSize;
int bottom = top + viewSize;
mRect.set(left, top, right, bottom);
}
}
}
Then add the following to the layout file:
```xml <com.jay.progressbardemo.CirclePgBar android:layout_width="match_parent" android:layout_height="
2.3.7 ProgressBar (Progress Bar)
2.5.4 AutoCompleteTextView (Auto-Complete Text Box) Basic Usage
2.5.8 Notification (Status Bar Notification) Detailed Explanation
3.6 Responding to System Setting Events (Configuration Class)
[4.2.3 Service Expert
8.3.4 Paint API - Xfermode and PorterDuff Detailed Explanation (I)
8.3.5 Paint API - Xfermode and PorterDuff Detailed Explanation (II)
8.3.6 Paint API - Xfermode and PorterDuff Detailed Explanation (III)
8.3.7 Paint API - Xfermode and PorterDuff Detailed Explanation (IV)
8.3.8 Paint API - Xfermode and PorterDuff Detailed Explanation (V)
8.3.14 Paint Several Enum/Constant Values and ShadowLayer Shadow Effect
8.3.17 Detailed Explanation of Canvas API (Part 2) - Collection of Clipping Methods
8.3.18 Detailed Explanation of Canvas API (Part 3) - Matrix and drawBitmapMesh
8.4.3 Android Animation Collection - Property Animation - First Encounter
8.4.4 Android Animation Collection - Property Animation - Re-encounter
[10.4 Vibrator]