美文网首页
Android_自定义控件_进度控价

Android_自定义控件_进度控价

作者: 书虫大王X | 来源:发表于2019-10-30 22:29 被阅读0次

    要实现的功能:

    功能 代码流程

    画贝塞尔曲线:

    //画贝塞尔曲线
    
    public class waveView extends View {
    
        private ValueAnimator va;
        private Paint mPaint;
        private Path mPath;
    //    屏幕密度
        int  density = (int)(getResources().getDisplayMetrics().density);
    //    波长
        private int waveLength = 200*density;
    //    波峰
        private int waveCrest = 70*density;
    //    动画起始点的偏移值
        private int speed;
        private int lineColor = Color.BLACK;
        private int lineSize = 10;
    
    
        public waveView(Context context) {
            this(context,null);
        }
    
        public waveView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
        private void init() {
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setColor(lineColor);
            mPaint.setStrokeWidth(lineSize);
            mPaint.setStyle(Paint.Style.STROKE);
    
        }
      @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            startWave();
        }
    
        private void startWave(){
    
            va = ValueAnimator.ofInt(0,waveLength);
            va.setDuration(500);
            va.setRepeatCount(ValueAnimator.INFINITE);
            va.setRepeatMode(ValueAnimator.RESTART);
            va.setInterpolator(new LinearInterpolator());
            va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
    //                获取当前值
                    speed = (int)valueAnimator.getAnimatedValue();
                    invalidate();
                }
            });
            va.start();
        }
        public void stopWave(){
            if (va != null) {
                va.cancel();
            }
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            mPath = new Path();
    //        计算有几个完整的周期
            int count = getWidth()/waveLength;
    //        设置wave的起始点
            mPath.moveTo(-waveLength+speed,getHeight()/2);
    //        获取中垂线
            int center = (int)getPivotY();
    //        确定曲线的路径
            for(int start = -waveLength+speed;start < getWidth();start += waveLength){
                mPath.cubicTo(start,center,start + waveLength/4,center-waveCrest,start + waveLength/2,center);
                mPath.cubicTo(start + waveLength/2,center,start + waveLength*3/4,center+waveCrest,start + waveLength,center);
            }
    
            canvas.drawPath(mPath,mPaint);
        }
    
        public void setLineColor(int lineColor) {
            this.lineColor = lineColor;
            mPaint.setColor(lineColor);
        }
    
        public void setLineSize(int lineSize) {
            this.lineSize = lineSize;
            mPaint.setStrokeWidth(lineSize);
        }
    
        public void setWaveCrest(int waveCrest) {
            this.waveCrest = waveCrest;
        }
    
        public void setWaveLength(int waveLength) {
            this.waveLength = waveLength;
        }
    }
    

    画百分数文本和外圈圆环:

    public class circleView extends View {
    
    //    控件的外圈
        Paint circlePaint;
    //    控件的百分数
        Paint textPaint;
        private int lineWidth = 5;
        private int lineColor = Color.BLACK;
        private int textColor = Color.GRAY;
        private int textSize = 50;
        private String text = "100%";
    //    百分数的进度
        private float progress;
        //文字与中心线的距离
        private int centerSpace;
    
    
        public circleView(Context context) {
            this(context,null);
        }
    
        public circleView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            circlePaint.setColor(lineColor);
            circlePaint.setStyle(Paint.Style.STROKE);
            circlePaint.setStrokeWidth(lineWidth);
    
            textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            textPaint.setColor(textColor);
            textPaint.setStyle(Paint.Style.STROKE);
            textPaint.setTextSize(textSize);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            int radius = Math.min(getWidth(),getHeight()/2) - 2*lineWidth;
    //        getPivotX 获取中心点
            canvas.drawCircle(getPivotX(),getPivotY(),radius,circlePaint);
    
            text = (int)(progress)+"%";
    //        计算文本的宽度
            int width = (int) textPaint.measureText(text);
    //        获取文字矩阵
            Paint.FontMetricsInt fn = textPaint.getFontMetricsInt();
            canvas.drawText(text,getPivotX() - width/2,getPivotY() + (-fn.ascent)/2+centerSpace,textPaint);
        }
    
    
    //    定义一系列的setget方法,供外部对控件属性进行设置
        public void setLineColor(int lineColor) {
            this.lineColor = lineColor;
            circlePaint.setColor(lineColor);
        }
    
        public void setLineWidth(int lineWidth) {
            this.lineWidth = lineWidth;
            circlePaint.setStrokeWidth(lineWidth);
        }
    
        public void setText(String text) {
            this.text = text;
        }
    
        public void setTextColor(int textColor) {
            this.textColor = textColor;
            textPaint.setColor(textColor);
        }
    
        public void setTextSize(int textSize) {
            this.textSize = textSize;
            textPaint.setStrokeWidth(textSize);
        }
    
        public void setProgress(float progress) {
            this.progress = progress;
            if (this.progress >= 100) {
                this.progress = 100;
            }
            invalidate();
        }
    
        public float getProgress() {
            return progress;
        }
    
        public void setCenterSpace(int centerSpace) {
            this.centerSpace = centerSpace;
        }
    }
    
    

    继承viewGroup承载两个视图:

    public class waveLodingView extends ViewGroup {
    
    //    文本的进程
        private float progress;
        circleView cv;
        waveView wv;
    
        public waveLodingView(Context context) {
            this(context,null);
        }
    
        public waveLodingView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
    //    viewGroup中,通过子视图来确定容器的尺寸(权力大过xml中的布局)
    //    1.先调用这个函数测量控件的尺寸
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
    //    3.在这里对控件进行布局
        //    对所有子视图进行布局
    //    i:left   i1:top  i2:right i3:button
        @Override
        protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
            cv = new circleView(getContext());
            cv.setLineColor(Color.RED);
            cv.setLineWidth(40);
            cv.setCenterSpace(-80);
            cv.layout(0,0,getWidth(),getHeight());
            addView(cv);
    
            wv = new waveView(getContext());
            wv.setWaveCrest(30);
            wv.setWaveLength(100);
            wv.setLineColor(Color.RED);
            wv.layout(getWidth()/4,getHeight()/2-30,getWidth()*3/4,getHeight()/2+30);
            addView(wv);
        }
    
    //    2.在这里控件的尺寸已经确定
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
        }
    
        public void setProgress(float progress) {
            this.progress = progress;
            cv.setProgress(progress);
            if (progress >= 100) {
                wv.stopWave();
            }
        }
        public float getProgress() {
            return progress;
        }
    }
    
    

    在xml创建waveLodingView 视图:

       <xn.ky.a1027_zdy_1.waveLodingView
           android:id="@+id/load"
           android:layout_width="300dp"
           android:layout_height="300dp"
           android:layout_centerInParent="true">
       </xn.ky.a1027_zdy_1.waveLodingView>
    

    在MainActivity中实现waveLodingView 的onTouch方法:

    public class MainActivity extends AppCompatActivity {
    
        waveLodingView lodingView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            lodingView = findViewById(R.id.load);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN){
    
                new Timer().schedule(new TimerTask() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
    //                        将任务抛到主线程
                            @Override
                            public void run() {
                                lodingView.setProgress(lodingView.getProgress() + 5);
                            }
                        });
    
                    }
                },0,100);
            }
            return true;
        }
    }
    
    成果展示

    相关文章

      网友评论

          本文标题:Android_自定义控件_进度控价

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