美文网首页Android自定义Viewandroid技术专栏安卓UI
Android 自定义View--ProgressBar篇(三)

Android 自定义View--ProgressBar篇(三)

作者: 枫羽望空 | 来源:发表于2018-09-28 11:13 被阅读30次

    1、概述

    1.1 目的 :

    在我们的日常开发中,有很多Android UI界面上有一些特殊或者特别的控件与界面,是Android自带的控件所不能满足的,需要我们自己定制一些适合的控件来完成。

    1.2 Android自定义View步骤 :

    1. 自定义属性;
    2. 选择和设置构造方法;
    3. 重写onMeasure()方法;
    4. 重写onDraw()方法;
    5. 重写onLayout()方法;
    6. 重写其他事件的方法(滑动监听等)。

    2、代码实现

    2.1 自定义属性:

    我们通常将自定义属性定义在/values/attr.xml文件中(attr.xml文件需要自己创建)。

         <declare-styleable name="SaleProgressView">
            <attr name="sideColor" format="color" />
            <attr name="textColor" format="color" />
            <attr name="sideWidth" format="dimension" />
            <attr name="overText" format="string" />
            <attr name="nearOverText" format="string" />
            <attr name="textSize" format="dimension" />
            <attr name="isNeedAnim" format="boolean" />
        </declare-styleable>
    

    2.2 实现方法含义

    1、在OnMeasure()方法中,测量自定义控件的大小,使自定义控件能够自适应布局各种各样的需求。
    2、在OnDraw()方法中,利用哼哈二将(Canvas与Paint)来绘制要显示的内容。
    3、在OnLayout()方法中来确定控件显示位置。
    4、在OnTouchEvent()方法处理控件的触摸事件。、

    [图片上传失败...(image-57f412-1538104403176)]

    2.3 继承View实现代码

    package com.fly.myview.progressbar;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.RectF;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.view.View;
    
    import com.fly.myview.R;
    
    import java.text.DecimalFormat;
    
    /**
     * <pre>
     *           .----.
     *        _.'__    `.
     *    .--(Q)(OK)---/$\
     *  .' @          /$$$\
     *  :         ,   $$$$$
     *   `-..__.-' _.-\$$$/
     *         `;_:    `"'
     *       .'"""""`.
     *      /,  FLY  ,\
     *     //         \\
     *     `-._______.-'
     *     ___`. | .'___
     *    (______|______)
     * </pre>
     * 包    名 : com.fly.myview.processbar
     * 作    者 : FLY
     * 创建时间 : 2017/9/26
     * <p>
     * 描述: 仿淘宝抢购进度条
     */
    
    public class SaleProgressView extends View{
    
        //商品总数
        private int totalCount;
        //当前卖出数
        private int currentCount;
        //动画需要的
        private int progressCount;
        //售出比例
        private float scale;
        //边框颜色
        private int sideColor;
        //文字颜色
        private int textColor;
        //边框粗细
        private float sideWidth;
        //边框所在的矩形
        private Paint sidePaint;
        //背景矩形
        private RectF bgRectF;
        private float radius;
        private int width;
        private int height;
        private PorterDuffXfermode mPorterDuffXfermode;
        private Paint srcPaint;
        private Bitmap fgSrc;
        private Bitmap bgSrc;
    
        private String nearOverText;
        private String overText;
        private float textSize;
    
        private Paint textPaint;
        private float nearOverTextWidth;
        private float overTextWidth;
        private float baseLineY;
        private Bitmap bgBitmap;
        private boolean isNeedAnim;
    
        public SaleProgressView(Context context) {
            this(context,null);
        }
    
        public SaleProgressView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            initAttrs(context,attrs);
            initPaint();
        }
    
        private void initAttrs(Context context, AttributeSet attrs) {
            //存储资源数组的容器,通过obtaiStyledAttributes()方法创建,调用recycle()方法把它释放
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SaleProgressView);
            //获取XML数据,初始化控件
            sideColor = ta.getColor(R.styleable.SaleProgressView_sideColor,0xffff3c32);
            textColor = ta.getColor(R.styleable.SaleProgressView_textColor,0xffff3c32);
            sideWidth = ta.getDimension(R.styleable.SaleProgressView_sideWidth,dp2px(2));
            overText = ta.getString(R.styleable.SaleProgressView_overText);
            nearOverText = ta.getString(R.styleable.SaleProgressView_nearOverText);
            textSize = ta.getDimension(R.styleable.SaleProgressView_textSize,sp2px(16));
            isNeedAnim = ta.getBoolean(R.styleable.SaleProgressView_isNeedAnim,true);
            ta.recycle();
        }
    
    
        private void initPaint() {
            sidePaint = new Paint(Paint.ANTI_ALIAS_FLAG);  //消除锯齿
    
           /**
            *  Paint.Style.FILL:填充内部
            *  Paint.Style.FILL_AND_STROKE  :填充内部和描边
            *  Paint.Style.STROKE  :描边
            */
            sidePaint.setStyle(Paint.Style.STROKE);
            //画笔样式为空心时,设置空心画笔的宽度
            sidePaint.setStrokeWidth(sideWidth);
            //设置画笔颜色
            sidePaint.setColor(sideColor);
    
            srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
            textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            textPaint.setStyle(Paint.Style.FILL);
            //设置字体大小
            textPaint.setTextSize(textSize);
    
            mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
            nearOverTextWidth = textPaint.measureText(nearOverText);
            overTextWidth = textPaint.measureText(overText);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            //获取View的宽高
            width = getWidth();
            height = getHeight();
    
            //圆角半径
            radius = height / 2.0f;
            //留出一定的间隙,避免边框被切掉一部分
            if (bgRectF == null) {
                bgRectF = new RectF(sideWidth, sideWidth, width - sideWidth, height - sideWidth);
            }
    
            if (baseLineY == 0.0f) {
                Paint.FontMetricsInt fm = textPaint.getFontMetricsInt();
                baseLineY = height / 2 - (fm.descent / 2 + fm.ascent / 2);
            }
    
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            if(!isNeedAnim){
                progressCount = currentCount;
            }
    
            if (totalCount == 0) {
                scale = 0.0f;
            } else {
                scale = Float.parseFloat(new DecimalFormat("0.00").format((float) progressCount / (float) totalCount));
            }
    
            drawSide(canvas);
            drawBg(canvas);
            drawFg(canvas);
            drawText(canvas);
    
            //这里是为了演示动画方便,实际开发中进度只会增加
            if(progressCount!=currentCount){
                if(progressCount<currentCount){
                    progressCount++;
                }else{
                    progressCount--;
                }
                postInvalidate();
            }
    
        }
    
        //绘制背景边框
        private void drawSide(Canvas canvas) {
            canvas.drawRoundRect(bgRectF, radius, radius, sidePaint);
        }
    
        //绘制背景
        private void drawBg(Canvas canvas) {
            if (bgBitmap == null) {
                bgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            }
    
            //Canvas是画布,对Canvas进行旋转、平移、缩放等操作
            Canvas bgCanvas = new Canvas(bgBitmap);
            if (bgSrc == null) {
                bgSrc = BitmapFactory.decodeResource(getResources(), R.mipmap.bg);
            }
            //将Canvas还原成矩形
            bgCanvas.drawRoundRect(bgRectF, radius, radius, srcPaint);
    
            srcPaint.setXfermode(mPorterDuffXfermode);
            //画图片
            bgCanvas.drawBitmap(bgSrc, null, bgRectF, srcPaint);
    
            canvas.drawBitmap(bgBitmap, 0, 0, null);
            srcPaint.setXfermode(null);
        }
    
        //绘制进度条
        private void drawFg(Canvas canvas) {
            if (scale == 0.0f) {
                return;
            }
            Bitmap fgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas fgCanvas = new Canvas(fgBitmap);
            if (fgSrc == null) {
                fgSrc = BitmapFactory.decodeResource(getResources(),R.mipmap.fg);
            }
            fgCanvas.drawRoundRect(
                    new RectF(sideWidth, sideWidth, (width - sideWidth) * scale, height - sideWidth),
                    radius, radius, srcPaint);
    
            srcPaint.setXfermode(mPorterDuffXfermode);
            fgCanvas.drawBitmap(fgSrc, null, bgRectF, srcPaint);
    
            canvas.drawBitmap(fgBitmap, 0, 0, null);
            srcPaint.setXfermode(null);
        }
    
        //绘制文字信息
        private void drawText(Canvas canvas) {
            String scaleText = new DecimalFormat("#%").format(scale);
            String saleText = String.format("已抢%s件", progressCount);
    
            float scaleTextWidth = textPaint.measureText(scaleText);
    
            Bitmap textBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas textCanvas = new Canvas(textBitmap);
            textPaint.setColor(textColor);
    
            if (scale < 0.8f) {
                textCanvas.drawText(saleText, dp2px(10), baseLineY, textPaint);
                textCanvas.drawText(scaleText, width - scaleTextWidth - dp2px(10), baseLineY, textPaint);
            } else if (scale < 1.0f) {
                textCanvas.drawText(nearOverText, width / 2 - nearOverTextWidth / 2, baseLineY, textPaint);
                textCanvas.drawText(scaleText, width - scaleTextWidth - dp2px(10), baseLineY, textPaint);
            } else {
                textCanvas.drawText(overText, width / 2 - overTextWidth / 2, baseLineY, textPaint);
            }
    
            textPaint.setXfermode(mPorterDuffXfermode);
            textPaint.setColor(Color.WHITE);
            textCanvas.drawRoundRect(
                    new RectF(sideWidth, sideWidth, (width - sideWidth) * scale, height - sideWidth),
                    radius, radius, textPaint);
            canvas.drawBitmap(textBitmap, 0, 0, null);
            textPaint.setXfermode(null);
        }
    
        private int dp2px(float dpValue) {
            float scale = getContext().getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
        private int sp2px(float spValue) {
            float scale = getContext().getResources().getDisplayMetrics().scaledDensity;
            return (int) (spValue * scale + 0.5f);
        }
    
        public void setTotalAndCurrentCount(int totalCount, int currentCount) {
            this.totalCount = totalCount;
            if (currentCount > totalCount) {
                currentCount = totalCount;
            }
            this.currentCount = currentCount;
            postInvalidate();
        }
    }
    
    
    
    

    3、使用

      
        <com.fly.myview.progressbar.SaleProgressView
            android:id="@+id/spv"
            android:layout_width="220dp"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            app:nearOverText="@string/nearOverText"
            app:overText="@string/overText" />
    

    4.效果

    效果图

    希望对各位朋友有帮助,谢谢!!!!

    相关文章

      网友评论

        本文标题:Android 自定义View--ProgressBar篇(三)

        本文链接:https://www.haomeiwen.com/subject/nwwuoftx.html