zoukankan      html  css  js  c++  java
  • 自定义圆形的progressBar进阶——线程篇

    自定义圆形的progressBar进阶

    上一篇教程讲解如何设计一个自定义的进度条,这篇主要结合线程来设计如何结合线程的思想使进度条自行跑动。比如我们开发的时候需要,开启子线程去下载东西或者实时的检测进度,并显示出来,这个时候就用到了线程。

    一、自定义的圆形的progressBar

    将上一篇的RoundnessProgressBar.java复制过来

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.os.SystemClock;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
    
     * 自定义绚丽的ProgressBar.
    
     */
    
    public class RoundnessProgressBar extends View {
    
        /**
         * 进度条所占用的角度
         */
        private static final int ARC_FULL_DEGREE = 300;
        //进度条个数
        private static final int COUNT = 100;
        //每个进度条所占用角度
        private static final float ARC_EACH_PROGRESS = ARC_FULL_DEGREE * 1.0f / (COUNT - 1);
    
        /**
         * 弧线细线条的长度
         */
        private int ARC_LINE_LENGTH;
    
        /**
         * 弧线细线条的宽度
         */
        private int ARC_LINE_WIDTH;
    
        /**
         * 组件的宽,高
         */
        private int width, height;
    
        /**
         * 进度条最大值和当前进度值
         */
        private float max, progress;
    
        /**
         * 绘制弧线的画笔
         */
        private Paint progressPaint;
    
        /**
         * 绘制文字的画笔
         */
        private Paint textPaint;
    
        /**
         * 绘制文字背景圆形的画笔
         */
        private Paint textBgPaint;
    
        /**
         * 圆弧的半径
         */
        private int circleRadius;
    
        /**
         * 圆弧圆心位置
         */
        private int centerX, centerY;
    
        public RoundnessProgressBar(Context context) {
            super(context);
            init();
        }
    
        public RoundnessProgressBar(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public RoundnessProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            progressPaint = new Paint();
            progressPaint.setAntiAlias(true);
            textPaint = new Paint();
            textPaint.setColor(Color.WHITE);
            textPaint.setAntiAlias(true);
            textBgPaint = new Paint();
            textBgPaint.setAntiAlias(true);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            if (changed){
                width = getWidth();
                height = getHeight();
                //计算圆弧半径和圆心点
                circleRadius = Math.min(width, height) / 2;
                ARC_LINE_LENGTH = circleRadius / 6;
                ARC_LINE_WIDTH = ARC_LINE_LENGTH / 8;
                centerX = width / 2;
                centerY = height / 2;
            }
    
            super.onLayout(changed, left, top, right, bottom);
        }
    
        private Rect textBounds = new Rect();
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            float start = (360 - ARC_FULL_DEGREE) >> 1; //进度条起始角度
            float sweep1 = ARC_FULL_DEGREE * (progress / max); //进度划过的角度
            //绘制进度条
            progressPaint.setColor(Color.parseColor(calColor(progress / max, "#ffff0000", "#ff00ff00")));
            progressPaint.setStrokeWidth(ARC_LINE_WIDTH);
            float drawDegree = 1.6f;
            while (drawDegree <= ARC_FULL_DEGREE) {
                double a = (start + drawDegree) / 180 * Math.PI;
                float lineStartX = centerX - circleRadius * (float) Math.sin(a);
                float lineStartY = centerY + circleRadius * (float) Math.cos(a);
                float lineStopX = lineStartX + ARC_LINE_LENGTH * (float) Math.sin(a);
                float lineStopY = lineStartY - ARC_LINE_LENGTH * (float) Math.cos(a);
                if (drawDegree > sweep1) {
                    //绘制进度条背景
                    progressPaint.setColor(Color.parseColor("#88aaaaaa"));
                    progressPaint.setStrokeWidth(ARC_LINE_WIDTH >> 1);
                }
                canvas.drawLine(lineStartX, lineStartY, lineStopX, lineStopY, progressPaint);
                drawDegree += ARC_EACH_PROGRESS;
            }
    
            //绘制文字背景圆形
            textBgPaint.setStyle(Paint.Style.FILL);//设置填充
            textBgPaint.setColor(Color.parseColor("#41668b"));
            canvas.drawCircle(centerX, centerY, (circleRadius - ARC_LINE_LENGTH) * 0.8f, textBgPaint);
            textBgPaint.setStyle(Paint.Style.STROKE);//设置空心
            textBgPaint.setStrokeWidth(2);
            textBgPaint.setColor(Color.parseColor("#aaaaaaaa"));
            canvas.drawCircle(centerX, centerY, (circleRadius - ARC_LINE_LENGTH) * 0.8f, textBgPaint);
    
            //上一行文字
            textPaint.setTextSize(circleRadius >> 1);
            String text = (int) (100 * progress / max) + "";
            float textLen = textPaint.measureText(text);
            //计算文字高度
            textPaint.getTextBounds("8", 0, 1, textBounds);
            float h1 = textBounds.height();
            canvas.drawText(text, centerX - textLen / 2, centerY - circleRadius / 10 + h1 / 2, textPaint);
            //分
            textPaint.setTextSize(circleRadius >> 3);
            textPaint.getTextBounds("%", 0, 1, textBounds);
            float h11 = textBounds.height();
            canvas.drawText("%", centerX + textLen / 2 + 5, centerY - circleRadius / 10 + h1 / 2 - (h1 - h11), textPaint);
    
            //下一行文字
            textPaint.setTextSize(circleRadius / 6);
            text = "检测进度";
            textLen = textPaint.measureText(text);
            canvas.drawText(text, centerX - textLen / 2, centerY + circleRadius / 2.5f, textPaint);
        }
        public void setMax(int max) {
            this.max = max;
            invalidate();
        }
    
        //动画切换进度值(异步)
        public void setProgress(final float progress) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    float oldProgress = RoundnessProgressBar.this.progress;
                    for (int i = 1; i <= 100; i++) {
                        RoundnessProgressBar.this.progress = oldProgress + (progress - oldProgress) * (1.0f * i / 100);
                        postInvalidate();
                        SystemClock.sleep(20);
                    }
                }
    
            }).start();
        }
    
        //直接设置进度值(同步)
        public void setProgressSync(float progress) {
            this.progress = progress;
            invalidate();
        }
    
        /**
         * 计算渐变效果中间的某个颜色值。
         * 仅支持 #aarrggbb 模式,例如 #ccc9c9b2
         */
    
        public String calColor(float fraction, String startValue, String endValue) {
            int start_a, start_r, start_g, start_b;
            int end_a, end_r, end_g, end_b;
    
            //start
            start_a = getIntValue(startValue, 1, 3);
            start_r = getIntValue(startValue, 3, 5);
            start_g = getIntValue(startValue, 5, 7);
            start_b = getIntValue(startValue, 7, 9);
    
            //end
            end_a = getIntValue(endValue, 1, 3);
            end_r = getIntValue(endValue, 3, 5);
            end_g = getIntValue(endValue, 5, 7);
            end_b = getIntValue(endValue, 7, 9);
            return "#" + getHexString((int) (start_a + fraction * (end_a - start_a)))
                    + getHexString((int) (start_r + fraction * (end_r - start_r)))
                    + getHexString((int) (start_g + fraction * (end_g - start_g)))
                    + getHexString((int) (start_b + fraction * (end_b - start_b)));
        }
    
        //从原始#AARRGGBB颜色值中指定位置截取,并转为int.
        private int getIntValue(String hexValue, int start, int end) {
            return Integer.parseInt(hexValue.substring(start, end), 16);
        }
    
        private String getHexString(int value) {
            String a = Integer.toHexString(value);
            if (a.length() == 1) {
                a = "0" + a;
            }
            return a;
        }
    
    }
    

    二、布局文件

    新建一个布局文件activity_main.xml,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:custom="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:layout_gravity="center">
        <com.example.progressbar.RoundnessProgressBar
            android:id="@+id/circular_pb"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center"
            android:layout_marginTop="25dp"
            android:layout_weight="0.43"
            android:visibility="visible"
            />
        <Button
            android:id="@+id/button"
            android:text="开启线程"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/circular_pb"
            android:layout_centerHorizontal="true"/>
    
    </RelativeLayout>
    

    这里将按钮设计为点击按钮后开启线程,在子线程对进度条进行加加。然后在将其显示出来。

    三、MainActivity.java实现

    然后再MainActivity.java文件中加载布局,使用线程,使用这个progressBar。子线程每隔1秒将进度条加1,然后显示出来。

    public class MainActivity extends AppCompatActivity {
        private RoundnessProgressBar pb;
        public Handler handler = new Handler();
        private  int percent = 0;
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                pb.setProgressSync(percent);
                    try {
                        Thread.sleep(1000);
                        percent++;
    //                  handler.post(runnable);
                        if (percent==100){//设置进度条最大值为100.如果跑到100就重新跑,这里重新跑的时候会有出错的现象
                            percent=0;
                            pb.setProgress(0);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
    
    
    
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ActionBar actionBar = getSupportActionBar();
            if (actionBar!=null){
                actionBar.hide();
            }
            Button button = findViewById(R.id.button);
            pb = findViewById(R.id.circular_pb);
            pb.setMax(100);
            pb.setProgress(0);
    
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new Thread(){
                        @Override
                        public void run() {
                            super.run();
                            while (true){
                                handler.post(runnable);
                                pb.setProgressSync(percent);
                            }
    
                        }
                    }.start();
                }
            });
    
        }
    }
    

    这样在这里就实现了使用子线程来自动的每隔一秒将进度条加一。这里就不附上具体的进度条的跑动视频了。
    在这里插入图片描述

    注:功能实现出来了,但是不清楚设计的线程对不对。自己也在正学Android开发。如果设计的思想有错误,欢迎提出错误。

  • 相关阅读:
    htmilunit-- 针对抓取js生成的数据
    httpClient get方式抓取数据
    post方式的数据抓取
    利用win10自带的系统配置禁止开机启动项和程序
    linq中怎么实现多条件关联的左右连接
    win10提示管理员已阻止你运行此应用,如何强制运行
    远程连接SQL Server 2014遇到的问题和解决
    eclipse中删除多余的tomcat server
    resultMap之collection聚集
    empty()和remove()的区别
  • 原文地址:https://www.cnblogs.com/hequnwang/p/13949952.html
Copyright © 2011-2022 走看看