zoukankan      html  css  js  c++  java
  • 自定义View圆环

    //自定义View类

    public class MyRoundProcess extends View {
    
        /**
         * 自定义属性:
         * <p/>
         * 1. 外层圆的颜色 roundColor
         * <p/>
         * 2. 弧形进度圈的颜色 rouncProgressColor
         * <p/>
         * 3. 中间百分比文字的颜色 textColor
         * <p/>
         * 4. 中间百分比文字的大小 textSize
         * <p/>
         * 5. 圆环的宽度(以及作为弧形进度的圆环宽度)
         * <p/>
         * 6. 圆环的风格(Paint.Style.FILL  Paint.Syle.Stroke)
         */
    
    
        private static final String TAG = "MyRoundProcess";
    
        private int mWidth;
        private int mHeight;
    
        private Paint mPaint;
        private Paint mTextPaint;
    
        private float progress = 0f;
        private final float maxProgress = 100f; // 不可以修改的最大值
    
        //region 自定义属性的值
        int roundColor;
        int roundProgressColor;
        int textColor;
        float textSize;
        //endregion
    
        // 画笔的粗细(默认为40f, 在 onLayout 已修改)
        private float mStrokeWidth = 40f;
        private ValueAnimator mAnimator;
        private float mLastProgress = -1;
    
        public MyRoundProcess(Context context) {
            this(context, null);
        }
    
        public MyRoundProcess(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MyRoundProcess(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            // 初始化属性
            initAttrs(context, attrs, defStyleAttr);
    
            // 初始化点击事件
            initClickListener();
        }
    
        /**
         * 初始化属性
         *
         * @param context
         * @param attrs
         * @param defStyleAttr
         */
        private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
            TypedArray a = null;
            try {
                a = context.obtainStyledAttributes(attrs, R.styleable.MyRoundProcess);
    
                roundColor = a.getColor(R.styleable.MyRoundProcess_roundColor, getResources().getColor(android.R.color.darker_gray));
                roundProgressColor = a.getColor(R.styleable.MyRoundProcess_roundProgressColor, getResources().getColor(android.R.color.holo_red_dark));
                textColor = a.getColor(R.styleable.MyRoundProcess_textColor, getResources().getColor(android.R.color.holo_blue_dark));
                textSize = a.getDimension(R.styleable.MyRoundProcess_textSize, 22f);
    
            } finally {
                // 注意,别忘了 recycle
                a.recycle();
            }
        }
    
        /**
         * 初始化点击事件
         */
        private void initClickListener() {
            setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    // 重新开启动画
                    restartAnimate();
                }
            });
        }
    
        /**
         * 当开始布局时候调用
         */
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
    
            // 获取总的宽高
            mWidth = getMeasuredWidth();
            mHeight = getMeasuredHeight();
    
            // 初始化各种值
            initValue();
    
            // 设置圆环画笔
            setupPaint();
    
            // 设置文字画笔
            setupTextPaint();
        }
    
        /**
         * 初始化各种值
         */
        private void initValue() {
            // 画笔的粗细为总宽度的 1 / 15
            mStrokeWidth = mWidth / 15f;
        }
    
        /**
         * 设置圆环画笔
         */
        private void setupPaint() {
            // 创建圆环画笔
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setColor(roundColor);
            mPaint.setStyle(Paint.Style.STROKE); // 边框风格
            mPaint.setStrokeWidth(mStrokeWidth);
        }
    
        /**
         * 设置文字画笔
         */
        private void setupTextPaint() {
            mTextPaint = new Paint();
            mTextPaint.setAntiAlias(true);
            mTextPaint.setColor(textColor);
            mTextPaint.setTextSize(textSize);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            // 第一步:绘制一个圆环
            mPaint.setStrokeWidth(mStrokeWidth);
            mPaint.setColor(roundColor);
    
            float cx = mWidth / 2.0f;
            float cy = mHeight / 2.0f;
            float radius = mWidth / 2.0f - mStrokeWidth / 2.0f;
            canvas.drawCircle(cx, cy, radius, mPaint);
    
            // 第二步:绘制文字
            String text = ((int) (progress / maxProgress * 100)) + "%";
            Rect bounds = new Rect();
            mTextPaint.getTextBounds(text, 0, text.length(), bounds);
            canvas.drawText(text, mWidth / 2 - bounds.width() / 2, mHeight / 2 + bounds.height() / 2, mTextPaint);
    
            // 第三步:绘制动态进度圆环
            mPaint.setDither(true);
            mPaint.setStrokeJoin(Paint.Join.BEVEL);
            mPaint.setStrokeCap(Paint.Cap.ROUND); //  设置笔触为圆形
    
            mPaint.setStrokeWidth(mStrokeWidth);
            mPaint.setColor(roundProgressColor);
            RectF oval = new RectF(0 + mStrokeWidth / 2, 0 + mStrokeWidth / 2,
                    mWidth - mStrokeWidth / 2, mHeight - mStrokeWidth / 2);
    
            canvas.drawArc(oval, 0, progress / maxProgress * 360, false, mPaint);
        }
    
        /**
         * 重新开启动画
         */
        private void restartAnimate() {
            if (mLastProgress > 0) {
                // 取消动画
                cancelAnimate();
                // 重置进度
                setProgress(0f);
                // 重新开启动画
                runAnimate(mLastProgress);
            }
        }
    
        /**
         * 设置当前显示的进度条
         *
         * @param progress
         */
        public void setProgress(float progress) {
            this.progress = progress;
    
            // 使用 postInvalidate 比 postInvalidat() 好,线程安全
            postInvalidate();
        }
    
    
        /**
         * 开始执行动画
         *
         * @param targetProgress 最终到达的进度
         */
        public void runAnimate(float targetProgress) {
            // 运行之前,先取消上一次动画
            cancelAnimate();
    
            mLastProgress = targetProgress;
    
            mAnimator = ValueAnimator.ofObject(new FloatEvaluator(), 0, targetProgress);
            // 设置差值器
            mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float value = (float) animation.getAnimatedValue();
                    setProgress(value);
                }
            });
    
            mAnimator.setDuration((long) (targetProgress * 33));
            mAnimator.start();
        }
    
        /**
         * 取消动画
         */
        public void cancelAnimate() {
            if (mAnimator != null && mAnimator.isRunning()) {
                mAnimator.cancel();
            }
        }
    }

    //res下建values-w820dp下建attrs.xml和dimens.xml文件

    //attrs
    <resources>
    
        <declare-styleable name="MyRoundProcess">
            <attr name="roundColor" format="color"/>
            <attr name="roundProgressColor" format="color"/>
            <attr name="textColor" format="color" />
            <attr name="textSize" format="dimension" />
        </declare-styleable>
    
    </resources>
    //dimens
    <resources>
        <!-- Example customization of dimensions originally defined in res/values/dimens.xml
             (such as screen margins) for screens with more than 820dp of available width. This
             would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
        <dimen name="activity_horizontal_margin">64dp</dimen>
    </resources>

    //布局

     <cn.ifavor.roundprogress.view.MyRoundProcess
            android:layout_centerInParent="true"
            android:background="@android:color/white"
            android:id="@+id/my_round_process"
    
            app:roundColor="@android:color/darker_gray"
            app:roundProgressColor="@android:color/holo_red_dark"
            app:textSize="22sp"
            app:textColor="@android:color/holo_blue_bright"
    
            android:layout_width="200dip"
            android:layout_height="200dip"/>

    //MainActivity

    public class MainActivity extends AppCompatActivity{
    
        private MyRoundProcess mRoundProcess;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 初始化组件
            initViews();
        }
    
        /**
         * 初始化组件
         * init views
         */
        private void initViews() {
            mRoundProcess = (MyRoundProcess) findViewById(R.id.my_round_process);
            // 开启动画
            mRoundProcess.runAnimate(90);
        }
    
        /**
         * Activity 销毁时,取消动画
         * (cancel animation when activity destoryed)
         */
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mRoundProcess != null){
                mRoundProcess.cancelAnimate();
            }
        }
    }
  • 相关阅读:
    Django(app的概念、ORM介绍及编码错误问题)
    Django(完整的登录示例、render字符串替换和redirect跳转)
    Construct Binary Tree from Preorder and Inorder Traversal
    Single Number II
    Single Number
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Binary Tree Zigzag Level Order Traversal
    Recover Binary Search Tree
    Add Binary
  • 原文地址:https://www.cnblogs.com/yu12/p/7640630.html
Copyright © 2011-2022 走看看