/* * Copyright (c) 2015 LingoChamp Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.liulishuo.magicprogresswidget; import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; import android.view.View; import java.lang.ref.WeakReference; import cn.dreamtobe.percentsmoothhandler.ISmoothTarget; import cn.dreamtobe.percentsmoothhandler.SmoothHandler; /** * Created by Jacksgong on 12/8/15. * <p/> * 轻量的ProgressBar */ public class MagicProgressBar extends View implements ISmoothTarget { // ColorInt private int fillColor; // ColorInt private int backgroundColor; private Paint fillPaint; private Paint backgroundPaint; private float percent; private boolean isFlat; private SmoothHandler smoothHandler; public MagicProgressBar(Context context) { super(context); init(context, null); } public MagicProgressBar(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public MagicProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public MagicProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context, attrs); } private void init(final Context context, AttributeSet attrs) { if (context == null || attrs == null) { return; } TypedArray typedArray = null; try { typedArray = context.obtainStyledAttributes(attrs, R.styleable.MagicProgressBar); percent = typedArray.getFloat(R.styleable.MagicProgressBar_mpb_percent, 0); fillColor = typedArray.getColor(R.styleable.MagicProgressBar_mpb_fill_color, 0); backgroundColor = typedArray.getColor(R.styleable.MagicProgressBar_mpb_background_color, 0); isFlat = typedArray.getBoolean(R.styleable.MagicProgressBar_mpb_flat, false); } finally { if (typedArray != null) { typedArray.recycle(); } } fillPaint = new Paint(); fillPaint.setColor(fillColor); fillPaint.setAntiAlias(true); backgroundPaint = new Paint(); backgroundPaint.setColor(backgroundColor); backgroundPaint.setAntiAlias(true); } /** * @param fillColor ColorInt */ public void setFillColor(final int fillColor) { if (this.fillColor != fillColor) { this.fillColor = fillColor; this.fillPaint.setColor(fillColor); invalidate(); } } /** * @param backgroundColor ColorInt */ public void setBackgroundColor(final int backgroundColor) { if (this.backgroundColor != backgroundColor) { this.backgroundColor = backgroundColor; this.backgroundPaint.setColor(backgroundColor); invalidate(); } } public int getFillColor() { return this.fillColor; } public int getBackgroundColor() { return this.backgroundColor; } public float getPercent() { return this.percent; } /** * @param percent FloatRange(from = 0.0, to = 1.0) */ public void setPercent(float percent) { percent = Math.min(1, percent); percent = Math.max(0, percent); if (smoothHandler != null) { smoothHandler.commitPercent(percent); } if (this.percent != percent) { this.percent = percent; invalidate(); } } @Override public void setSmoothPercent(float percent) { getSmoothHandler().loopSmooth(percent); } @Override public void setSmoothPercent(float percent, long durationMillis) { getSmoothHandler().loopSmooth(percent, durationMillis); } private SmoothHandler getSmoothHandler() { if (smoothHandler == null) { smoothHandler = new SmoothHandler(new WeakReference<ISmoothTarget>(this)); } return smoothHandler; } /** * @param flat Whether the right side of progress is round or flat */ public void setFlat(final boolean flat) { if (this.isFlat != flat) { this.isFlat = flat; invalidate(); } } private final RectF rectF = new RectF(); // private final Path regionPath = new Path(); // private final Path fillPath = new Path(); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float drawPercent = percent; canvas.save(); final int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); final int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); float fillWidth = drawPercent * width; final float radius = height / 2.0f; rectF.left = 0; rectF.top = 0; rectF.right = width; rectF.bottom = height; // regionPath.reset(); // regionPath.addRoundRect(rectF, radius, radius, Path.Direction.CW); // regionPath.close(); // draw background if (backgroundColor != 0) { canvas.drawRoundRect(rectF, radius, radius, backgroundPaint); // canvas.drawPath(regionPath, backgroundPaint); } // draw fill try { if (fillColor != 0 && fillWidth > 0) { //有锯齿, 无奈放弃 // fillPath.reset(); // rectF.right = fillWidth; // fillPath.addRect(rectF, Path.Direction.CW); // fillPath.close(); // canvas.clipPath(regionPath); // canvas.drawPath(fillPath, fillPaint); if (fillWidth == width) { rectF.right = fillWidth; canvas.drawRoundRect(rectF, radius, radius, fillPaint); return; } if (isFlat) { // draw left semicircle canvas.save(); rectF.right = fillWidth > radius ? radius : fillWidth; canvas.clipRect(rectF); rectF.right = radius * 2; canvas.drawRoundRect(rectF, radius, radius, fillPaint); canvas.restore(); if (fillWidth <= radius) { return; } float leftAreaWidth = width - radius; // draw center float centerX = fillWidth > leftAreaWidth ? leftAreaWidth : fillWidth; rectF.left = radius; rectF.right = centerX; canvas.drawRect(rectF, fillPaint); if (fillWidth <= leftAreaWidth) { return; } // draw right semicircle rectF.left = leftAreaWidth - radius; rectF.right = fillWidth; canvas.clipRect(rectF); rectF.right = width; canvas.drawArc(rectF, -90, 180, true, fillPaint); } else { if (fillWidth <= radius * 2) { rectF.right = fillWidth; canvas.clipRect(rectF); rectF.right = radius * 2; canvas.drawRoundRect(rectF, radius, radius, fillPaint); } else { rectF.right = fillWidth; canvas.drawRoundRect(rectF, radius, radius, fillPaint); } } } } finally { canvas.restore(); } } }