实现水波效果

一·效果图:



根据 y = A*sin(wx + b) + h;来画出我们的波纹

基本思路:

1.将view的一个宽度作为一个周期,或者一个周期的整数倍,这样便于计算和编程。

2.用数组保存每一个x值对应的y值,这里的x其实就是横向的像素值,都为整数。

3.然后通过这些数组画线,是纵向划线,然后就行

4.让两条波的速度有一个差值,已形成层次感



package com.liaoli.xfermode.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DrawFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by liaoli on 2016/3/5.
 */
public class DynamicWaveView extends View {


    /**
     * 一个正常周期的y     */
    private float[] mYPositions;

    /**
     * 第一条波纹的y     */
    private float[] mlineOneYPositions;

    /**
     * 第二条波纹的y     */
    private float[] mLineTwoYPositions;


    /**
     * 第一条波纹移动的速度
     */
    private int DEFUALT_TRANSLATE_X_SPEED_ONE = 70;
    /**
     *
     *第二条波纹移动的速度
     */
    private int DEFUALT_TRANSLATE_X_SPEED_two = 50;


    /**
     * 转换成像素的速度
     */
    private int mXOffSpeedOne, mXOffSpeedTwo;


    /**
     * 移动的距离
     */
    private int mXOneOffset, mXTwoOffset;

    private Paint mPaint;
    private DrawFilter mDrawFilter;

    private int waveColor = 0x880000aa;


    private int STRETCH_FACTOR_A = 20;

    private int OFFSET_Y = 100;

    private float mCycleFactorW;
    private int mTotalW;
    private int mTotalH;

    public DynamicWaveView(Context context) {
        this(context, null);
    }

    public DynamicWaveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DynamicWaveView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


        /**
         * 转换成像素是的在不同的手机上面的移动速度都是一样的
         */
        mXOffSpeedOne = UiUtils.dipToPx(context,DEFUALT_TRANSLATE_X_SPEED_ONE);

        mXOffSpeedTwo = UiUtils.dipToPx(context,DEFUALT_TRANSLATE_X_SPEED_two);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPaint.setStyle(Paint.Style.FILL);

        mPaint.setColor(waveColor);

        mDrawFilter = new PaintFlagsDrawFilter(0,Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG);


    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        
        canvas.setDrawFilter(mDrawFilter);
        
        resetPositionY();

        /**
         * 画两条波纹。是通过划线的方式来实现的
         * 之所以要画线,是要实现装满水的效果
         */
        for(int i = 0 ; i < mTotalW; i++){

            canvas.drawLine(i,mlineOneYPositions[i],i,mTotalH,mPaint);

            canvas.drawLine(i,mLineTwoYPositions[i],i,mTotalH,mPaint);
        }


        /**
         * 两条波纹的移动距离
         */
        mXOneOffset += mXOffSpeedOne;
        mXTwoOffset += mXOffSpeedTwo;


        /**
         * 如果移动距离,超过view的宽度时,相当于进入下一个周期,回复初始值
         */
        if (mXOneOffset > mTotalW) {
            mXOneOffset = 0;
        }


        /**
         * 如果移动距离,超过view的宽度时,相当于进入下一个周期,回复初始值
         */
        if (mXTwoOffset > mTotalW) {
            mXTwoOffset = 0;
        }

        /**
         * 重新绘制
         */
        postInvalidate();

    }


    /**
     * 根据波移动的距离,来改变波的对应点的值,这里是纯数学知识
     *看不明白的画一下图,马上就明白了
     */
    private void resetPositionY() {

        int lineOneInterval = mYPositions.length - mXOneOffset;

        System.arraycopy(mYPositions,mXOneOffset,mlineOneYPositions,0,lineOneInterval);
        System.arraycopy(mYPositions,0,mlineOneYPositions,lineOneInterval,mXOneOffset);



        int lineTwoInterval = mYPositions.length - mXTwoOffset;

        System.arraycopy(mYPositions,mXTwoOffset,mLineTwoYPositions,0,lineTwoInterval);
        System.arraycopy(mYPositions,0,mLineTwoYPositions,lineTwoInterval,mXTwoOffset);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


    }

    /**
     * 此方法调用在onMeasure之后,onDraw之前。
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mTotalW  = w;
        mTotalH = h;
        mYPositions = new float[w];

        mlineOneYPositions = new float[w];
        mLineTwoYPositions = new float[w];

        /**
         * 周期
         */
        mCycleFactorW = (float) (2*Math.PI /w);


        /**
         * 通过正玄函数来算一个周期的Y值,并保存在一个数组中
         */
        for(int i = 0 ; i < w; i++){

            mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW *i) + OFFSET_Y);
        }

    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值