Android自定义圆形的波浪百分比进度

先上效果图

 

自定义代码如下:

package com.langteng.courtesy.customview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

//作者:        冯浩  on 2019/1/23 09:36
//                          _ooOoo_
//                         o8888888o                            
//                         88" . "88                             
//                         (| ^_^ |)                              
//                         O\  =  /O                              
//                      ____/`---'\____                          
//                    .'  \\|     |//  `.                         
//                   /  \\|||  :  |||//  \                        
//                  /  _||||| -:- |||||-  \                       
//                  |   | \\\  -  /// |   |                       
//                  | \_|  ''\---/''  |   |                      
//                  \  .-\__  `-`  ___/-. /                      
//                ___`. .'  /--.--\  `. . ___                     
//              ."" '<  `.___\_<|>_/___.'  >'"".                  
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                
//      ========`-.____`-.___\_____/___.-`____.-'========        
//                           `=---='                              
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        
//         佛祖保佑       永无BUG     永不修改                    
//                      程序员之歌    作者:冯浩(字:德明)       
//         十年生死两茫茫 ,写程序,到天亮。                      
//             千行代码 ,Bug何处藏 ?                            
//         纵使上线又怎样 ,朝令改 ,夕断肠。                     
//                                                                
//         领导每天新想法 ,日日改 ,夜夜忙。                     
//             相顾无言 ,唯有泪千行。                            
//         每晚灯火阑珊处 ,夜难寐 ,加班狂。 
// ************************************************************************************************
public class WaveProgressView extends View {

    private static final float DEFAULT_AMPLITUDE_RATIO = 0.05f;
    private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
    private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
    private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;

    public static final int DEFAULT_BEHIND_WAVE_COLOR = Color.parseColor("#28FFFFFF");
    public static final int DEFAULT_FRONT_WAVE_COLOR = Color.parseColor("#3CFFFFFF");
    public static final ShapeType DEFAULT_WAVE_SHAPE = ShapeType.CIRCLE;
    private boolean showBehindLine = true;

    public enum ShapeType {
        CIRCLE,
        SQUARE
    }

    // if true, the shader will display the wave
    private boolean mShowWave;

    // shader containing repeated waves
    private BitmapShader mWaveShader;
    // shader matrix
    private Matrix mShaderMatrix;
    // paint to draw wave
    private Paint mViewPaint;
    // paint to draw border
    private Paint mBorderPaint;//边界画笔
    // paint to draw backgroup
    private Paint mBgPaint; //背景画笔

    private float mDefaultAmplitude;
    private float mDefaultWaterLevel;
    private float mDefaultWaveLength;
    private double mDefaultAngularFrequency;

    private float mAmplitudeRatio = DEFAULT_AMPLITUDE_RATIO;
    private float mWaveLengthRatio = DEFAULT_WAVE_LENGTH_RATIO;
    private float mWaterLevelRatio = DEFAULT_WATER_LEVEL_RATIO;
    private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;

    private int mBehindWaveColor = DEFAULT_BEHIND_WAVE_COLOR;
    private int mFrontWaveColor = DEFAULT_FRONT_WAVE_COLOR;
    private ShapeType mShapeType = DEFAULT_WAVE_SHAPE;

    public WaveProgressView(Context context) {
        super(context);
        init();
    }

    public WaveProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WaveProgressView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        mShaderMatrix = new Matrix();
        mViewPaint = new Paint();
        mViewPaint.setAntiAlias(true);
        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        /**默认背景色---淡黄色*/
        mBgPaint.setColor(0xff282828);
    }

    public float getWaveShiftRatio() {
        return mWaveShiftRatio;
    }

    /**
     * Shift the wave horizontally according to <code>waveShiftRatio</code>.
     *
     * @param waveShiftRatio Should be 0 ~ 1. Default to be 0.
     *                       <br/>Result of waveShiftRatio multiples width of WaveView is the length to shift.
     */
    public void setWaveShiftRatio(float waveShiftRatio) {
        if (mWaveShiftRatio != waveShiftRatio) {
            mWaveShiftRatio = waveShiftRatio;
            invalidate();
        }
    }

    public float getWaterLevelRatio() {
        return mWaterLevelRatio;
    }

    /**
     * Set water level according to <code>waterLevelRatio</code>.
     *
     * @param waterLevelRatio Should be 0 ~ 1. Default to be 0.5.
     *                        <br/>Ratio of water level to WaveView height.
     */
    public void setWaterLevelRatio(float waterLevelRatio) {
        if (mWaterLevelRatio != waterLevelRatio) {
            mWaterLevelRatio = waterLevelRatio;
            invalidate();
        }
    }

    public float getAmplitudeRatio() {
        return mAmplitudeRatio;
    }

    /**
     * Set vertical size of wave according to <code>amplitudeRatio</code>
     *
     * @param amplitudeRatio Default to be 0.05. Result of amplitudeRatio + waterLevelRatio should be less than 1.
     *                       <br/>Ratio of amplitude to height of WaveView.
     */
    public void setAmplitudeRatio(float amplitudeRatio) {
        if (mAmplitudeRatio != amplitudeRatio) {
            mAmplitudeRatio = amplitudeRatio;
            invalidate();
        }
    }

    public float getWaveLengthRatio() {
        return mWaveLengthRatio;
    }

    /**
     * Set horizontal size of wave according to <code>waveLengthRatio</code>
     *
     * @param waveLengthRatio Default to be 1.
     *                        <br/>Ratio of wave length to width of WaveView.
     */
    public void setWaveLengthRatio(float waveLengthRatio) {
        mWaveLengthRatio = waveLengthRatio;
    }

    public boolean isShowWave() {
        return mShowWave;
    }

    public void setShowWave(boolean showWave) {
        mShowWave = showWave;
    }

    public void setBorder(int width, int color) {
        if (mBorderPaint == null) {
            mBorderPaint = new Paint();
            mBorderPaint.setAntiAlias(true);
            mBorderPaint.setStyle(Paint.Style.STROKE);
        }
        mBorderPaint.setColor(color);
        mBorderPaint.setStrokeWidth(width);

        invalidate();
    }

    public void setWaveColor(int behindWaveColor, int frontWaveColor) {
        mBehindWaveColor = behindWaveColor;
        mFrontWaveColor = frontWaveColor;

        if (getWidth() > 0 && getHeight() > 0) {
            // need to recreate shader when color changed
            mWaveShader = null;
            createShader();
            invalidate();
        }
    }

    public void setShapeType(ShapeType shapeType) {
        mShapeType = shapeType;
        invalidate();
    }

    public void setShowBehindLine(boolean showBehindLine){
        this.showBehindLine = showBehindLine;
        invalidate();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        createShader();
    }

    /**
     * Create the shader with default waves which repeat horizontally, and clamp vertically
     */
    private void createShader() {
        mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth();
        mDefaultAmplitude = getHeight() * DEFAULT_AMPLITUDE_RATIO;
        mDefaultWaterLevel = getHeight() * DEFAULT_WATER_LEVEL_RATIO;
        mDefaultWaveLength = getWidth();

        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        Paint wavePaint = new Paint();
        wavePaint.setStrokeWidth(2);
        wavePaint.setAntiAlias(true);

        // Draw default waves into the bitmap
        // y=Asin(ωx+φ)+h
        final int endX = getWidth() + 1;
        final int endY = getHeight() + 1;

        float[] waveY = new float[endX];

        wavePaint.setColor(mBehindWaveColor);
        for (int beginX = 0; beginX < endX; beginX++) {
            double wx = beginX * mDefaultAngularFrequency;
            float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx));
            if(showBehindLine){
                canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);
            }
            waveY[beginX] = beginY;
        }

        wavePaint.setColor(mFrontWaveColor);
        final int wave2Shift = (int) (mDefaultWaveLength / 4);
        for (int beginX = 0; beginX < endX; beginX++) {
            canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
        }

        // use the bitamp to create the shader
        mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        mViewPaint.setShader(mWaveShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // modify paint shader according to mShowWave state
        if (mShowWave && mWaveShader != null) {
            // first call after mShowWave, assign it to our paint
            if (mViewPaint.getShader() == null) {
                mViewPaint.setShader(mWaveShader);
            }

            // sacle shader according to mWaveLengthRatio and mAmplitudeRatio
            // this decides the size(mWaveLengthRatio for width, mAmplitudeRatio for height) of waves
            mShaderMatrix.setScale(
                    mWaveLengthRatio / DEFAULT_WAVE_LENGTH_RATIO,
                    mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO,
                    0,
                    mDefaultWaterLevel);
            // translate shader according to mWaveShiftRatio and mWaterLevelRatio
            // this decides the start position(mWaveShiftRatio for x, mWaterLevelRatio for y) of waves
            mShaderMatrix.postTranslate(
                    mWaveShiftRatio * getWidth(),
                    (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());

            // assign matrix to invalidate the shader
            mWaveShader.setLocalMatrix(mShaderMatrix);

            float borderWidth = mBorderPaint == null ? 0f : mBorderPaint.getStrokeWidth();
            switch (mShapeType) {
                case CIRCLE:
                    if (borderWidth > 0) {
                        canvas.drawCircle(getWidth() / 2f, getHeight() / 2f,
                                (getWidth() - borderWidth) / 2f - 1f, mBorderPaint);
                    }
                    float radius = getWidth() / 2f - borderWidth;
                    canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mBgPaint);
                    canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mViewPaint);
                    break;
                case SQUARE:
                    if (borderWidth > 0) {
                        canvas.drawRect(
                                borderWidth / 2f,
                                borderWidth / 2f,
                                getWidth() - borderWidth / 2f - 0.5f,
                                getHeight() - borderWidth / 2f - 0.5f,
                                mBorderPaint);
                    }
                    canvas.drawRect(borderWidth, borderWidth, getWidth() - borderWidth,
                            getHeight() - borderWidth, mViewPaint);
                    break;
            }
        } else {
            mViewPaint.setShader(null);
        }
    }

}

//布局中代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/x162"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/x30">

    <RelativeLayout
        android:id="@+id/coiner"
        android:layout_width="@dimen/x162"
        android:layout_height="@dimen/x162">

        <com.langteng.courtesy.customview.WaveProgressView
            android:id="@+id/progress"
            android:layout_width="@dimen/x162"
            android:layout_height="@dimen/x162" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/first_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4"
                android:textColor="#FFFFFFFF"
                android:textSize="@dimen/x54" />

            <TextView
                android:id="@+id/second_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=".35"
                android:textColor="#FFFFFFFF"
                android:textSize="@dimen/x36" />

        </LinearLayout>


    </RelativeLayout>


    <TextView
        android:gravity="center"
        android:id="@+id/job_tv"
        android:layout_width="@dimen/x162"
        android:layout_height="wrap_content"
        android:layout_below="@id/coiner"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/y30"
        android:ellipsize="end"
        android:maxLines="2"
        android:text="哈设计师"
        android:textColor="#FFFFFFFF"
        android:textSize="@dimen/x40" />
</RelativeLayout>

//界面中动态改变数值以及颜色

  WaveProgressView mWaveProgressView = (WaveProgressView) helper.getView(R.id.progress);
    mWaveProgressView.setShapeType(WaveProgressView.ShapeType.CIRCLE);

    /**绘制边界线的宽及颜色,不需要的可以注销,此处默认宽4,白色*/
    mWaveProgressView.setBorder(4, 0xffffffff);
    /**是否显示双线*/
    mWaveProgressView.setShowBehindLine(false);
    mWaveHelper = new WaveHelper(mWaveProgressView);
    // mWaveProgressView.setWaterLevelRatio(0.1F);
    mWaveProgressView.setWaterLevelRatio(Float.parseFloat(item.getProportion()) / 100f);
    mWaveHelper.start();

    if (helper.getPosition() > getArgb().size()) {

        mWaveProgressView.setWaveColor(
                Color.parseColor("#fff7bfc0"),//波浪线上(淡紫色)setShowBehindLine为true时显示,false不显示
                getArgb().get(helper.getPosition() - getArgb().size()));//波浪线下(橘黄色)

    } else {

        mWaveProgressView.setWaveColor(
                Color.parseColor("#fff7bfc0"),//波浪线上(淡紫色)setShowBehindLine为true时显示,false不显示
                getArgb().get(helper.getPosition()));//波浪线下(橘黄色)

    }


}

private List<Integer> getArgb() {
    List<Integer> argbs = new ArrayList<>();
    argbs.add(Color.argb(255, 253, 177, 49));
    argbs.add(Color.argb(255, 126, 185, 255));
    argbs.add(Color.argb(255, 80, 227, 194));
    argbs.add(Color.argb(255, 255, 94, 98));
    argbs.add(Color.argb(255, 157, 221, 85));
    argbs.add(Color.argb(255, 198, 158, 255));
    return argbs;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值