12/08/2018, 14:46

How To Make Circle Custom Progress Bar in Android ?

Đô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 ...

Đô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 awidthMeasureSpec, int heightMeasureSpec) {
        int viewWidthHeight = MeasureSpec.getSize(getResources().getDimensionPixelSize(R.dimen.awidth_height_progress));
        centerX=viewWidthHeight/2;
        centerY=viewWidthHeight/2;
        setMeasuredDimension(viewWidthHeight,viewWidthHeight);
    }
    private void initPixelSize(){
        mWidthArcBG=getResources().getDimensionPixelSize(R.dimen.awidth_arc_background);
        mWidthAcrPrimary=getResources().getDimensionPixelSize(R.dimen.awidth_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.
0