How To Make Circle Custom Progress Bar in Android ?
Bài đăng này đã không được cập nhật trong 7 năm
Đôi khi một ứng dụng hay đến từ những chi tiết nhỏ. hầu như tất cả ứng dụng mobi android hiện này đều sử dụng đến ProgressBar nên hôm nay mình xin phép được viết một bài về việc custom 1 Progress Bar Circle. Chúng ta bắt đầu vào công việc thôi.
Video Demo
Tạo Project App
- mình sẽ tạo 1 project có tên là CustomProgreessBar in android studio và trong project mình sẽ có tạo 2 file java
- file CustomProgressBar mình sẽ custom lại view
- file MainAcitivity sẽ là file main.
Bắt đầu vào công việc Custom View
- Để cho tiện theo dõi mình sẽ copy đoạn code file CustomProgressBar.java sau đó mình sẽ giải thích những đoạn code quan trọng trong file
package com.example.toanpc.customprogressbar;
/**
* Created by toanpc on 26/02/2017.
*/
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
public class CustomProgressBar extends View {
private Paint mArcPaintBackground;
private Paint mArcPaintPrimary;
private final Rect mTextBounds = new Rect();
private int mProgress;
private Paint mTextPaint;
private int centerX;
private int centerY;
private int mWidthArcBG;
private int mWidthAcrPrimary;
private int mTextSizeProgress;
public CustomProgressBar(Context context) {
super(context);
init(context);
}
public CustomProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewWidthHeight = MeasureSpec.getSize(getResources().getDimensionPixelSize(R.dimen.width_height_progress));
centerX=viewWidthHeight/2;
centerY=viewWidthHeight/2;
setMeasuredDimension(viewWidthHeight,viewWidthHeight);
}
private void initPixelSize(){
mWidthArcBG=getResources().getDimensionPixelSize(R.dimen.width_arc_background);
mWidthAcrPrimary=getResources().getDimensionPixelSize(R.dimen.width_arc_primary);
mTextSizeProgress=getResources().getDimensionPixelSize(R.dimen.text_size_progress);
}
private void init(Context ctx) {
initPixelSize();
mArcPaintBackground = new Paint();
mArcPaintBackground.setDither(true);
mArcPaintBackground.setStyle(Paint.Style.STROKE);
mArcPaintBackground.setColor(ContextCompat.getColor(getContext(),R.color.colorArcBG));
mArcPaintBackground.setStrokeWidth(mWidthArcBG);
mArcPaintBackground.setAntiAlias(true);
mArcPaintPrimary = new Paint();
mArcPaintPrimary.setDither(true);
mArcPaintPrimary.setStyle(Paint.Style.STROKE);
mArcPaintPrimary.setColor(ContextCompat.getColor(getContext(),R.color.colorAccent));
mArcPaintPrimary.setStrokeWidth(mWidthAcrPrimary);
mArcPaintPrimary.setAntiAlias(true);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(mTextSizeProgress);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(ContextCompat.getColor(getContext(),android.R.color.black));
mTextPaint.setStrokeWidth(2);
}
public void setProgress(int progress) {
mProgress = progress;
invalidate();
requestLayout();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
RectF rect = new RectF(0+10, 0+10, canvas.getWidth()-10, canvas.getHeight()-10);
canvas.drawArc(rect, 270, 360, false, mArcPaintBackground);
canvas.drawArc(rect, 270, -(360 * (mProgress / 100f)), false, mArcPaintPrimary);
drawTextCentred(canvas);
}
public void drawTextCentred(Canvas canvas) {
String text=mProgress+"%";
mTextPaint.getTextBounds(text, 0,text.length() , mTextBounds);
canvas.drawText(text, centerX - mTextBounds.exactCenterX(), centerY - mTextBounds.exactCenterY(), mTextPaint);
}
}
- để tạo thành được một progressBar như trong video ta cần 2 vòng tròn và một text nằm giữa progressbar:
RectF rect = new RectF(0+10, 0+10, canvas.getWidth()-10, canvas.getHeight()-10);
// dòng lệnh này nhằm tạo ra vòng tròn thứ nhất có màu xám
canvas.drawArc(rect, 270, 360, false, mArcPaintBackground);
// dòng lệnh này tạo ra vòng tròn có màu hồng
canvas.drawArc(rect, 270, -(360 * (mProgress / 100f)), false, mArcPaintPrimary);
- sau khi đã tạo được 2 vòng trong ta tiếp tục xử lý thêm 1 chút về phần text, ở đây mình muốn text luôn nằm giữa ProgressBar Circle
public void drawTextCentred(Canvas canvas) {
String text=mProgress+"%";
mTextPaint.getTextBounds(text, 0,text.length() , mTextBounds);
canvas.drawText(text, centerX - mTextBounds.exactCenterX(), centerY - mTextBounds.exactCenterY(), mTextPaint);
}
- Ngoài việc sử dụng đoạn code trên giúp text nằm giữa vòng tròng bạn cũng có thể sử dụng StaticLayout nếu trường hợp text của bạn quá dài so với độ rộng của progressbar.
- Vậy là xong việc CustomProgressBar giờ mở file MainAcitivity bạn chỉ cần thêm dòng code:
progressBar.setProgress(seekBar.getProgress());
Kết Luận
- Tại sao chúng ta phải sử dụng thư viện với những cái mà chúng ta có thể làm ?
- Chỉ bằng một số dòng code một ít tìm tòi và một ít logic bạn đã có thể có được 1 progressBar Circle đẹp mà không phải import thư viện ngoài vào bên trong app của mình.
All rights reserved