频道栏目
首页 > 程序开发 > 移动开发 > 其他 > 正文
自定义view实现水波纹效果
2017-09-13 10:36:00      个评论    来源:HelloMagina的博客  
收藏   我要投稿

自定义view实现水波纹效果

自己实现了一遍,碰到的坑有2个:
1、记得调用mPath.reset(),否则每次的path内容会叠加在一起,就会充满整个view ,不再出现水波纹效果;
2、代码中的调用贝塞尔曲线的参数原理要弄明白:其实每次调用onDraw()方法时,调用了mPath.moveTo(x,y),关键需要弄懂这里的x的意思,我们必须保证每次moveTo(X,Y)的点是一个贝塞尔曲线的起点,把该动画想象是正弦波,我们希望每次moveTO()的点都应该是原点,这样才能完整得去确定我们即将绘制的贝塞尔曲线。所以这次的x= -dx。

package com.example.myapplication;


import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by liudong on 17-9-11.
 */

public class RippleView extends View {

    private int rippleY;
    private int waveLength;
    private Paint paint;


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

    void init() {
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);


    }

    public RippleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        rippleY = getTop() + getHeight() / 2;
        waveLength = getWidth() / 3;
        interval = this.getWidth() / 100;
        interval_y = getHeight() / 100;
    }

    public RippleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private Path mPath = new Path();

    private int dx;// 0 ->viewWidth

    private int y_pide = 0;
    private int y_total = 100;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.reset();
        int tempY = rippleY/2;
        mPath.moveTo(-dx, tempY);
        for (int i = -dx; i < getWidth(); i += waveLength) {
        //2次调用贝塞尔曲线
            mPath.rQuadTo(waveLength / 2, tempY, waveLength, 0);
            mPath.rQuadTo(waveLength / 2, -tempY, waveLength, 0);

        }
        mPath.lineTo(getRight(), getBottom());
        mPath.lineTo(0, getBottom());
        mPath.close();
        canvas.drawPath(mPath, paint);
    }

    private float dy;
    int interval;
    int interval_y;
    private int x;

    private boolean shouldincrete = true;
    private boolean shouldincrete_Y = true;

    public void startRippleAnimation() {
//        利用动画实现水波纹
        ValueAnimator animator = ValueAnimator.ofInt(getWidth(), 0);
        animator.setDuration(20000);
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(animation -> {
            int animatedValue = (int) animation.getAnimatedValue();
            float v = animation.getAnimatedFraction() * getHeight();
            dy = v;
            dx = animatedValue;
            invalidate();
        });
        animator.start();
//        利用子线程实现水波纹
        animationThread = new Thread(() -> {
            while (!isStop) {
                SystemClock.sleep(60);
                if (dx > getWidth()) {
                    shouldincrete = false;
                } else if (dx < 0) {
                    shouldincrete = true;
                }

                if (shouldincrete) {
                    dx += interval;
                } else {
                    dx -= interval;
                }

                if (y_pide > getHeight()) {
                    shouldincrete_Y = false;
                } else if (y_pide < 0) {
                    shouldincrete_Y = true;
                }

                if (shouldincrete_Y) {
                    y_pide += interval_y;
                } else {
                    y_pide -= interval_y;
                }
                postInvalidate();

            }
        });
        animationThread.start();
    }
    public boolean isStop = false;
    private Thread animationThread;
}

点击复制链接 与好友分享!回本站首页
上一篇:AndroidStudio代码规范——TextView规范
下一篇:关于ActionBarDrawerToggle的构造方法参数详解
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站