zoukankan      html  css  js  c++  java
  • Android中自定义水球

    如图所示:

    自定义属性:

    在values下创建attrs.xml 文件

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <declare-styleable name="WaveProgressView">
            <attr name="radius" format="dimension|reference" />
            <attr name="radius_color" format="color|reference" />
            <attr name="progress_text_color" format="color|reference" />
            <attr name="progress_text_size" format="dimension|reference" />
            <attr name="progress_color" format="color|reference" />
            <attr name="progress" format="float" />
            <attr name="maxProgress" format="float" />
        </declare-styleable>
    
    
    </resources>
    

     样式 styles.xml 中

    <style name="WaveProgressViewDefault">
            <item name="radius">55dp</item>
            <item name="progress_text_color">#fff</item>
            <item name="progress_text_size">20sp</item>
            <item name="progress_color">#C215AB30</item>
            <item name="radius_color">#FF734B58</item>
            <item name="progress">0</item>
            <item name="maxProgress">100</item>
        </style>
    

    自定义view

    package com.chuanye.shuiqiudemo1;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.os.Parcel;
    import android.os.Parcelable;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.view.View;
    
    import java.text.DecimalFormat;
    
    public class WaveProgressView extends View {
    
        private int radius = dp2px(55);//半径
        private int textColor;//进度字体颜色
        private int textSize;//进度字体大小
        private int progressColor;//进度颜色
        private int radiusColor;
        private Paint textPaint;
        private Paint circlePaint;
        private Paint pathPaint;
        private Bitmap bitmap;
        private Canvas bitmapCanvas;
        private int width = 10, height = 10;
        private int minPadding;
        private float progress;//当前进度
        private float maxProgress;//最大进度
        private Path path = new Path();
        private DecimalFormat df = new DecimalFormat("0.0");
    
    
        public WaveProgressView(Context context) {
            this(context, null);
        }
    
        public WaveProgressView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public WaveProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WaveProgressView, defStyleAttr, R.style.WaveProgressViewDefault);
            radius = (int) a.getDimension(R.styleable.WaveProgressView_radius, radius);//半径
            textColor = a.getColor(R.styleable.WaveProgressView_progress_text_color, 0);//进度字体颜色
            textSize = a.getDimensionPixelSize(R.styleable.WaveProgressView_progress_text_size, 0);//进度字体大小
            progressColor = a.getColor(R.styleable.WaveProgressView_progress_color, 0);//进度颜色
            radiusColor = a.getColor(R.styleable.WaveProgressView_radius_color, 0);//半径颜色
            progress = a.getFloat(R.styleable.WaveProgressView_progress, 0);//当前进度
            maxProgress = a.getFloat(R.styleable.WaveProgressView_maxProgress, 100);//最大进度
            a.recycle();//回收利用
    
            //初始化一些画笔  文本画笔
            textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            textPaint.setTextSize(textSize);
            textPaint.setColor(textColor);
            textPaint.setDither(true);
    
    
            //圆 画笔
            circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            circlePaint.setColor(radiusColor);
            circlePaint.setDither(true);
    
            //道路 进度画笔
            pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            pathPaint.setColor(progressColor);
            pathPaint.setDither(true);
            //设置转送模式
            pathPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //计算宽和高
            int exceptW = getPaddingLeft() + getPaddingRight() + 2 * radius;
            int exceptH = getPaddingTop() + getPaddingBottom() + 2 * radius;
            int width = resolveSize(exceptW, widthMeasureSpec);
            int height = resolveSize(exceptH, heightMeasureSpec);
            int min = Math.min(width, height);
    
            this.width = this.height = min;
    
            //计算半径,减去padding的最小值
            int minLR = Math.min(getPaddingLeft(), getPaddingRight());
            int minTB = Math.min(getPaddingTop(), getPaddingBottom());
            minPadding = Math.min(minLR, minTB);
            radius = (min - minPadding * 2) / 2;
    
            setMeasuredDimension(min, min);
        }
    
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (bitmap == null) {
                bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888);
                bitmapCanvas = new Canvas(bitmap);
            }
            bitmapCanvas.save();
            //移动坐标系   转化画布
            bitmapCanvas.translate(minPadding, minPadding);
            //绘制圆
            bitmapCanvas.drawCircle(radius, radius, radius, circlePaint);
    
            //绘制PATH
            //重置绘制路线
            path.reset();
            float percent = progress * 1.0f / maxProgress;
            float y = (1 - percent) * radius * 2;
            //移动到右上边
            path.moveTo(radius * 2, y);
            //移动到最右下方
            path.lineTo(radius * 2, radius * 2);
            //移动到最左下边
            path.lineTo(0, radius * 2);
            //移动到左上边
            // path.lineTo(0, y);
            //实现左右波动,根据progress来平移
            path.lineTo(-(1 - percent) * radius * 2, y);
            if (progress != 0.0f) {
                //根据直径计算绘制贝赛尔曲线的次数
                int count = radius * 4 / 60;
                //控制-控制点y的坐标
                float point = (1 - percent) * 15;
                for (int i = 0; i < count; i++) {
                    path.rQuadTo(15, -point, 30, 0);
                    path.rQuadTo(15, point, 30, 0);
                }
            }
            //闭合
            path.close();
            bitmapCanvas.drawPath(path, pathPaint);
    
            //绘制文字
            String text = progress + "%";
            float textW = textPaint.measureText(text);
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            float baseLine = radius - (fontMetrics.ascent + fontMetrics.descent) / 2;
            bitmapCanvas.drawText(text, radius - textW / 2, baseLine, textPaint);
    
            bitmapCanvas.restore();
    
            canvas.drawBitmap(bitmap, 0, 0, null);
        }
    
        public float getProgress() {
            return progress;
        }
    
        public void setProgress(float progress) {
            this.progress = Float.valueOf(df.format(progress));
            invalidate();
        }
    
        private int dp2px(int dp) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
        }
    
    
        private final static class SavedState extends BaseSavedState {
            float progress;
    
            public SavedState(Parcel source) {
                super(source);
            }
    
            public SavedState(Parcelable superState) {
                super(superState);
            }
    
            public static final Parcelable.Creator<SavedState> CREATOR
                    = new Parcelable.Creator<SavedState>() {
                public SavedState createFromParcel(Parcel in) {
                    return new SavedState(in);
                }
    
                public SavedState[] newArray(int size) {
                    return new SavedState[size];
                }
            };
        }
    
        @Override
        protected Parcelable onSaveInstanceState() {
            Parcelable superState = super.onSaveInstanceState();
            SavedState ss = new SavedState(superState);
            ss.progress = progress;
            return ss;
        }
    
        @Override
        protected void onRestoreInstanceState(Parcelable state) {
            SavedState ss = (SavedState) state;
            super.onRestoreInstanceState(ss.getSuperState());
            setProgress(ss.progress);
        }
    
    }
    

    布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:wpv="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center_horizontal">
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_main3"
            android:text="开启"
            android:onClick="start"
            tools:ignore="OnClick" />
    
    
        <com.chuanye.shuiqiudemo1.WaveProgressView
            android:id="@+id/wpv_0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            wpv:progress="15" />
    
        <com.chuanye.shuiqiudemo1.WaveProgressView
            android:id="@+id/wpv_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            wpv:maxProgress="80"
            wpv:progress_color="#dd65A6DA"
            wpv:progress_text_color="@color/colorAccent"
            wpv:progress_text_size="20sp"
            wpv:radius="60dp"
            wpv:radius_color="#AAffdd33" />
    
        <com.chuanye.shuiqiudemo1.WaveProgressView
            android:id="@+id/wpv_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            wpv:maxProgress="120"
            wpv:progress_color="#DC7E2040"
            wpv:progress_text_size="13sp"
            wpv:radius="70dp"
            wpv:radius_color="#7F6B1AB3" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_main32"
            android:text="设置值" />
    </LinearLayout>
    

    MainActivity 中

    package com.chuanye.shuiqiudemo1;
    
    import android.animation.ObjectAnimator;
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.animation.AccelerateInterpolator;
    import android.view.animation.BounceInterpolator;
    import android.view.animation.LinearInterpolator;
    import android.widget.Button;
    
    public class Main3Activity extends AppCompatActivity {
        //https://blog.csdn.net/ta893115871/article/details/52245815/
        //private WaveProgressView waveProgressView_0;
        private String TAG = "Main3Activity";
        //private WaveProgressView waveProgressView_1;
        //private WaveProgressView waveProgressView_2;
        private WaveProgressView waveProgressView_0, waveProgressView_1, waveProgressView_2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main3);
    
            Log.i(TAG,"onCreate...");
    
            waveProgressView_0 = (WaveProgressView) findViewById(R.id.wpv_0);
    
            waveProgressView_1 = (WaveProgressView) findViewById(R.id.wpv_1);
            waveProgressView_2 = (WaveProgressView) findViewById(R.id.wpv_2);
    
            
    
            Button btn_main32 = findViewById(R.id.btn_main32);
            btn_main32.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    waveProgressView_0.setProgress(85);
                }
            });
    
    
        }
    
    
        public void start(View view) {
            ObjectAnimator objectAnimator0 = ObjectAnimator.ofFloat(waveProgressView_0, "progress", 0f, 100f);
            objectAnimator0.setDuration(3300);
            objectAnimator0.setInterpolator(new LinearInterpolator());
            objectAnimator0.start();
    
            ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(waveProgressView_1, "progress", 0f, 80f);
            objectAnimator1.setDuration(3000);
            objectAnimator1.setInterpolator(new AccelerateInterpolator());
            objectAnimator1.start();
    
            ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(waveProgressView_2, "progress", 0f, 120f);
            objectAnimator2.setDuration(5000);
            objectAnimator2.setInterpolator(new BounceInterpolator());
            objectAnimator2.start();
        }
    }
    

    完成

  • 相关阅读:
    Flink1.9重大改进和新功能
    【2020】DBus,一个更能满足企业需求的大数据采集平台
    大数据运维:大数据平台+海量数据
    大数据运维尖刀班 | 集群_监控_CDH_Docker_K8S_两项目_腾讯云服务器
    离线数仓和实时数仓架构与设计
    【全集】IDEA入门到实战
    Mysql快速入门
    RabbitMQ安装
    消息队列MQ简介
    C#特性
  • 原文地址:https://www.cnblogs.com/changyiqiang/p/10875803.html
Copyright © 2011-2022 走看看