package com.cmeiyuan.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.ClipDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import com.cmeiyuan.widget.R; public class ProgressView extends View { public static final int DRAW_FROM_START = 1; public static final int DRAW_FROM_CENTER = 2; public static final int DRAW_FROM_END = 3; private static final float CLIP_FACTOR = 0.05f; private int mPositiveDrawableResId; private int mNegativeDrawableResId; private Drawable mPositiveDrawable; private Drawable mNegativeDrawable; private Drawable mPositiveClipDrawable; private Drawable mNegativeClipDrawable; private float mProgressValue = 0.0f; private float mScaleFactor = 1.0f; private int mDrawType = DRAW_FROM_START; public ProgressView(Context context) { this(context, null); } public ProgressView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); /** 可配属性设置 */ final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressView, defStyleAttr, 0); mProgressValue = a.getFloat(R.styleable.ProgressView_progress, 0); mDrawType = a.getInt(R.styleable.ProgressView_drawType, 1); mPositiveDrawable = a .getDrawable(R.styleable.ProgressView_positiveDrawable); mNegativeDrawable = a .getDrawable(R.styleable.ProgressView_negativeDrawable); mPositiveDrawableResId = a.getResourceId( R.styleable.ProgressView_positiveDrawable, 0); mNegativeDrawableResId = a.getResourceId( R.styleable.ProgressView_negativeDrawable, 0); a.recycle(); caculateScaleFactor(); } private void caculateScaleFactor() { if (mDrawType == DRAW_FROM_CENTER) { mScaleFactor = 0.5f; } else { mScaleFactor = 1.0f; } } public void setDrawType(int type) { this.mDrawType = type; } public int getDrawType() { return mDrawType; } public void setProgress(float progress) { this.mProgressValue = progress; invalidate(); } public float getProgress() { return mProgressValue; } public void setPositiveDrawable(Drawable drawable) { this.mPositiveDrawable = drawable; } public void setNegativeDrawable(Drawable drawable) { this.mNegativeDrawable = drawable; } public void setPositiveResource(int resId) { this.mPositiveDrawable = null; this.mPositiveDrawableResId = resId; } public void setNegativeResource(int resId) { this.mNegativeDrawable = null; this.mNegativeDrawableResId = resId; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); caculateScaleFactor(); if (mProgressValue > 0) { drawPositiveProgress(canvas); } else if (mProgressValue < 0) { drawNegativeProgress(canvas); } } private Drawable getPositiveDrawable(float percent) { Drawable drawable = null; if (mPositiveDrawable == null && mPositiveDrawableResId != 0) { mPositiveDrawable = getContext().getResources().getDrawable( mPositiveDrawableResId); } drawable = mPositiveDrawable; if (mDrawType == DRAW_FROM_CENTER) { return drawable; } if (mPositiveDrawable != null && Math.abs(percent) <= CLIP_FACTOR) { if (mPositiveClipDrawable == null) { mPositiveClipDrawable = new ClipDrawable(mPositiveDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL); } drawable = mPositiveClipDrawable; } return drawable; } private Drawable getNegativeDrawable(float percent) { Drawable drawable = null; if (mNegativeDrawable == null && mNegativeDrawableResId != 0) { mNegativeDrawable = getContext().getResources().getDrawable( mNegativeDrawableResId); } drawable = mNegativeDrawable; if (mDrawType == DRAW_FROM_CENTER) { return drawable; } if (mNegativeDrawable != null && Math.abs(percent) <= CLIP_FACTOR) { if (mNegativeClipDrawable == null) { mNegativeClipDrawable = new ClipDrawable(mNegativeDrawable, Gravity.RIGHT, ClipDrawable.HORIZONTAL); } drawable = mNegativeClipDrawable; } return drawable; } private void drawPositiveProgress(Canvas canvas) { float percent = Math.abs(mProgressValue); Drawable drawable = getPositiveDrawable(percent); if (drawable != null) { int pl = getPaddingLeft(); int pt = getPaddingTop(); int pr = getPaddingRight(); int pb = getPaddingBottom(); int totalWidth = getWidth() - pl - pr; int totalHeight = getHeight() - pt - pb; int w = (int) (totalWidth * percent * mScaleFactor); int h = totalHeight; if (drawable instanceof ClipDrawable) { drawable.setBounds(0, 0, totalWidth, totalHeight); drawable.setLevel((int) (percent * 10000 * 0.9f)); } else { drawable.setBounds(0, 0, w, h); } pl += (1 - mScaleFactor) * totalWidth; canvas.translate(pl, pt); drawable.draw(canvas); canvas.translate(-pl, -pt); } } private void drawNegativeProgress(Canvas canvas) { float percent = Math.abs(mProgressValue); Drawable drawable = getNegativeDrawable(percent); if (drawable != null) { int pl = getPaddingLeft(); int pt = getPaddingTop(); int pr = getPaddingRight(); int pb = getPaddingBottom(); int totalWidth = getWidth() - pl - pr; int totalHeight = getHeight() - pt - pb; int w = (int) (totalWidth * percent * mScaleFactor); int h = totalHeight; if (drawable instanceof ClipDrawable) { drawable.setBounds(0, 0, totalWidth, totalHeight); drawable.setLevel((int) (percent * 10000 * 0.9f)); pl -= (1 - mScaleFactor) * totalWidth; } else { drawable.setBounds(0, 0, w, h); pl += totalWidth * mScaleFactor - w; } canvas.translate(pl, pt); drawable.draw(canvas); canvas.translate(-pl, -pt); } } }