天天看點

Android自定義View,實作Progress(水波紋動畫)

Android自定義View,實作Progress(水波紋動畫)

代碼貼出來,友善自己回顧和大家借鑒

下載下傳Demo位址:自定義 Progress(水波紋動畫)

實作方法:

xml檔案`

<com.example.jiaojiao.waveprogressdemo.DynamicWave
                android:id="@+id/dw_progress"
                android:background="#ffffff"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_margin="5dp"
                android:layout_centerInParent="true" />`   
           

自定義View

/**
 * 簡介:波浪進度條
 */
public class DynamicWave extends View {


    // 圓
    private Paint paint;
    //    private int roundWidth = 10;
    //    private int roundHeight = 10;
    private int roundWidth = ;
    private int roundHeight = ;
    private Paint paint2;

    // 波紋顔色
    private static int WAVE_PAINT_COLOR;// = 0x880000aa;
    // y = Asin(wx+b)+h
    private float STRETCH_FACTOR_A=;
    private static final int OFFSET_Y = ;
    // 第一條水波移動速度
    private static final int TRANSLATE_X_SPEED_ONE = ;
    // 第二條水波移動速度
    private static final int TRANSLATE_X_SPEED_TWO = ;
    private float mCycleFactorW;

    private int mTotalWidth, mTotalHeight;
    private float[] mYPositions;
    private float[] mResetOneYPositions;
    private float[] mResetTwoYPositions;
    private int mXOffsetSpeedOne;
    private int mXOffsetSpeedTwo;
    private int mXOneOffset;
    private int mXTwoOffset;

    private Paint mWavePaint;
    private Paint mWavePaint2;
    private Paint mWavePaint3;
    private DrawFilter mDrawFilter;

    private float currentY=;
    private float lastY=;
    private Bitmap bitmaps;

    public DynamicWave(Context context, AttributeSet attrs) {
        super(context, attrs);

        // 圓
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundAngleImageView);
            assert a != null;
            roundWidth = a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundWidth, roundWidth);
            roundHeight = a.getDimensionPixelSize(R.styleable.RoundAngleImageView_roundHeight, roundHeight);
        } else {
            float density = context.getResources().getDisplayMetrics().density;
            roundWidth = (int) (roundWidth * density);
            roundHeight = (int) (roundHeight * density);
        }

        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setAntiAlias(true);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

        paint2 = new Paint();
        paint2.setXfermode(null);

        STRETCH_FACTOR_A=f*getResources().getDisplayMetrics().density;

        // 将dp轉化為px,用于控制不同分辨率上移動速度基本一緻
        mXOffsetSpeedOne = (int) (TRANSLATE_X_SPEED_ONE*getResources().getDisplayMetrics().density);//UIUtils.dipToPx(context, TRANSLATE_X_SPEED_ONE);
        mXOffsetSpeedTwo = (int) (TRANSLATE_X_SPEED_TWO*getResources().getDisplayMetrics().density);//UIUtils.dipToPx(context, TRANSLATE_X_SPEED_TWO);
        WAVE_PAINT_COLOR=context.getResources().getColor(R.color.orange);

        // 初始繪制波紋的畫筆
        mWavePaint = new Paint();
        // 去除畫筆鋸齒
        mWavePaint.setAntiAlias(true);
        // 設定風格為實線
        mWavePaint.setStyle(Paint.Style.FILL);
        // 設定畫筆顔色
        mWavePaint.setColor(WAVE_PAINT_COLOR);
        mDrawFilter = new PaintFlagsDrawFilter(, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);

        // 第二條波紋
        mWavePaint2=new Paint();
        // 去除畫筆鋸齒
        mWavePaint2.setAntiAlias(true);
        // 設定風格為實線
        mWavePaint2.setStyle(Paint.Style.FILL);
        // 設定畫筆顔色
        mWavePaint2.setColor(context.getResources().getColor(R.color.dynamic_wave_orange));
    }

    @SuppressWarnings("NullableProblems")
    @Override
    public void draw(Canvas canvas) {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas2 = new Canvas(bitmap);
        super.draw(canvas2);
        canvas.drawBitmap(toRoundCorner(bitmap, ), , , paint2);
    }

    // 目前進度
    public void setProgress(float current){
        if (-==current){
            currentY=-;
        }else {
            currentY=current-STRETCH_FACTOR_A;
        }
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 從canvas層面去除繪制時鋸齒
        canvas.setDrawFilter(mDrawFilter);
        if (<=currentY){
            float js=currentY/*getHeight();
            if(<=js){
                lastY=js;
            }else {
                lastY=;
            }
        }else {
            lastY=;
            currentY=-;
        }
        resetPositonY();
        for (int i = ; i < mTotalWidth; i++) {

            // 減400隻是為了控制波紋繪制的y的在螢幕的位置,大家可以改成一個變量,然後動态改變這個變量,進而形成波紋上升下降效果
            // 繪制第一條水波紋
            canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - lastY, i,
                    mTotalHeight,
                    mWavePaint2);

            // 繪制第二條水波紋
            canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - lastY, i,
                    mTotalHeight,
                    mWavePaint);
        }

        // 改變兩條波紋的移動點
        mXOneOffset += mXOffsetSpeedOne;
        mXTwoOffset += mXOffsetSpeedTwo;

        // 如果已經移動到結尾處,則重頭記錄
        if (mXOneOffset >= mTotalWidth) {
            mXOneOffset = ;
        }
        if (mXTwoOffset > mTotalWidth) {
            mXTwoOffset = ;
        }

        // 引發view重繪,一般可以考慮延遲20-30ms重繪,空出時間片
        //postInvalidate();
        if (-!=currentY){
            postInvalidateDelayed();
        }
    }

    private void resetPositonY() {
        // mXOneOffset代表目前第一條水波紋要移動的距離
        int yOneInterval = mYPositions.length - mXOneOffset;
        // 使用System.arraycopy方式重新填充第一條波紋的資料
        System.arraycopy(mYPositions, mXOneOffset, mResetOneYPositions, , yOneInterval);
        System.arraycopy(mYPositions, , mResetOneYPositions, yOneInterval, mXOneOffset);

        int yTwoInterval = mYPositions.length - mXTwoOffset;
        System.arraycopy(mYPositions, mXTwoOffset, mResetTwoYPositions, ,
                yTwoInterval);
        System.arraycopy(mYPositions, , mResetTwoYPositions, yTwoInterval, mXTwoOffset);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 記錄下view的寬高
        mTotalWidth = w;
        mTotalHeight = h;
        // 用于儲存原始波紋的y值
        mYPositions = new float[mTotalWidth];
        // 用于儲存波紋一的y值
        mResetOneYPositions = new float[mTotalWidth];
        // 用于儲存波紋二的y值
        mResetTwoYPositions = new float[mTotalWidth];

        // 将周期定為view總寬度
        mCycleFactorW = (float) ( * Math.PI / mTotalWidth);

        // 根據view總寬度得出所有對應的y值
        for (int i = ; i < mTotalWidth; i++) {
            mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y);
        }
    }


    // 圓
    public static Bitmap toRoundCorner(Bitmap bitmap, float ratio) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(, , bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(, , , );
        canvas.drawRoundRect(rectF, bitmap.getWidth() / ratio,
                bitmap.getHeight() / ratio, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;

    }
    private void drawLiftUp(Canvas canvas) {
        Path path = new Path();
        path.moveTo(, roundHeight);
        path.lineTo(, );
        path.lineTo(roundWidth, );
        path.arcTo(new RectF(
                        ,
                        ,
                        roundWidth * ,
                        roundHeight * ),
                -,
                -);
        path.close();
        canvas.drawPath(path, paint);
    }

    private void drawLiftDown(Canvas canvas) {
        Path path = new Path();
        path.moveTo(, getHeight() - roundHeight);
        path.lineTo(, getHeight());
        path.lineTo(roundWidth, getHeight());
        path.arcTo(new RectF(
                        ,
                        getHeight() - roundHeight * ,
                        roundWidth * ,
                        getHeight()),
                ,
                );
        path.close();
        canvas.drawPath(path, paint);
    }

    private void drawRightDown(Canvas canvas) {
        Path path = new Path();
        path.moveTo(getWidth() - roundWidth, getHeight());
        path.lineTo(getWidth(), getHeight());
        path.lineTo(getWidth(), getHeight() - roundHeight);
        path.arcTo(new RectF(
                getWidth() - roundWidth * ,
                getHeight() - roundHeight * ,
                getWidth(),
                getHeight()), , );
        path.close();
        canvas.drawPath(path, paint);
    }

    private void drawRightUp(Canvas canvas) {
        Path path = new Path();
        path.moveTo(getWidth(), roundHeight);
        path.lineTo(getWidth(), );
        path.lineTo(getWidth() - roundWidth, );
        path.arcTo(new RectF(
                        getWidth() - roundWidth * ,
                        ,
                        getWidth(),
                        roundHeight * ),
                -,
                );
        path.close();
        canvas.drawPath(path, paint);
    }
}
           

Activity

private DynamicWave dw_progress;
    private TextView tv_at_present;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        dw_progress = (DynamicWave) findViewById(R.id.dw_progress);
        tv_at_present = (TextView) findViewById(R.id.tv_at_present);
        tv_at_present.setText("30%");
        dw_progress.setProgress();
    }