ProgressButton的实现

一向对UI不是太感兴趣,不过项目中遇到了还是得去做,做这个ProgressButton还是费了不少功夫,不过效果还可以,这里先记下,以后可能还会用到。只贴代码,原理就不多说了。

public class ProgressButton extends Button {

    public static final int MODE_BUTTON = 0;

    public static final int MODE_PROGRESS = 1;

    private Paint mBackgroundPaint;

    private Paint mTextPaint;

    private int mProgress = -1;

    /**
     * 进度条填充色
     */
    private int mPbColor = Color.GREEN;

    /**
     * 进度条字体颜色
     */
    private int mPbTextColor = Color.WHITE;

    /**
     * 原始按钮字体颜色
     */
    private int mTextColor;

    private int mWidth, mHeight;

    private Drawable mBackgroundDrawable;

    private Bitmap mBackgroundBitmap;

    private RectF mRectSrc;

    private int mMode;

    private PorterDuffXfermode mXfermode;

    public ProgressButton(Context context) {
        this(context, null);
    }

    public ProgressButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public ProgressButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProgressButton);
        mPbColor = a.getColor(R.styleable.ProgressButton_ProgressButton_pbColor, Color.GREEN);
        mPbTextColor = a.getColor(R.styleable.ProgressButton_ProgressButton_pbTextColor, Color.WHITE);
        a.recycle();
    }

    private void init(Context context, AttributeSet attrs) {
        initAttrs(context, attrs);

        mTextColor = getCurrentTextColor();

        mBackgroundPaint = new Paint();
        mBackgroundPaint.setAntiAlias(true);
        mBackgroundPaint.setStyle(Paint.Style.FILL);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(getTextSize());
        mTextPaint.setColor(mTextColor);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            //解决文字有时候画不出问题
            setLayerType(LAYER_TYPE_SOFTWARE, mTextPaint);
        }

        mBackgroundDrawable = getBackground();
        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);
    }

    public void setProgress(int progress) {
        if (progress > mProgress) {
            mProgress = progress;
            invalidate();
        }
    }

    public void setButtonMode(int mode) {
        mMode = mode;

        if (mode == MODE_BUTTON) {
            setBackgroundDrawable(mBackgroundDrawable);
            mProgress = -1;
        } else if (mode == MODE_PROGRESS) {
            setBackgroundResource(0);
        } else {
            throw new UnsupportedOperationException("Unknown mode " + mode);
        }
    }

    private void releaseBgBitmap() {
        if (mBackgroundBitmap != null) {
            mBackgroundBitmap.recycle();
            mBackgroundBitmap = null;
        }
    }

    public boolean isProgressMode() {
        return mMode == MODE_PROGRESS;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        if (w > 0 && h > 0 && w != oldw && h != oldh) {
            mWidth = w;
            mHeight = h;
            mRectSrc = new RectF(0, 0, mWidth, mHeight);

            if (mBackgroundBitmap != null) {
                releaseBgBitmap();
            }

            mBackgroundBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(mBackgroundBitmap);

            /**
             * 这个不能掉
             */
            mBackgroundDrawable.setBounds(0, 0, mWidth, mHeight);

            mBackgroundDrawable.draw(canvas);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mWidth > 0 && mHeight > 0 && isProgressMode()) {
            int saveCount = canvas.saveLayer(mRectSrc, mBackgroundPaint, Canvas.ALL_SAVE_FLAG);

            canvas.drawBitmap(mBackgroundBitmap, null, mRectSrc, mBackgroundPaint);

            mBackgroundPaint.setXfermode(mXfermode);

            mBackgroundPaint.setColor(mPbColor);
            mBackgroundPaint.setStyle(Paint.Style.FILL);
            canvas.drawRect(0, 0, mWidth * mProgress / 100, mHeight, mBackgroundPaint);

            mBackgroundPaint.setXfermode(null);

            drawText(canvas);

            canvas.restoreToCount(saveCount);
        }
    }

    private void drawText(Canvas canvas) {
        float progress = mProgress * 0.01f;
        LinearGradient shader = new LinearGradient(0, 0, mWidth, 0, new int[]{
                mPbTextColor, mTextColor
        }, new float[]{
                progress, progress + 0.001f
        }, Shader.TileMode.CLAMP);

        mTextPaint.setShader(shader);

        String text = getText().toString();
        float textWidth = mTextPaint.measureText(text);
        float baseX = (mWidth - textWidth) / 2;
        float baseY = mHeight / 2 - (mTextPaint.descent() + mTextPaint.ascent()) / 2;
        canvas.drawText(text, baseX, baseY, mTextPaint);
    }

    public void destroy() {
        releaseBgBitmap();
    }
}

值得一提的是如何将Nine Patch Drawable转化为Bitmap,如下:

mBackgroundBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mBackgroundBitmap);
mBackgroundDrawable.setBounds(0, 0, mWidth, mHeight);
mBackgroundDrawable.draw(canvas);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值