先看效果:

高级UI--有趣的水波纹


一,效果有两个,一个是波纹运动,另外一个就是头像运动(换成小船的图片更有趣哦)
二,实现步骤

1,使用贝塞尔曲线,确定path的路径。
2,绘制path路径,并且开启动画,使向右移动,达到水波纹效果。
3,确定头像的位置
4,绘制头像。

1,绘制波浪线,如图
高级UI--有趣的水波纹
2,填充区域,如图
高级UI--有趣的水波纹
3,Region和path相交,得到一个矩形区域
高级UI--有趣的水波纹
4,当这个矩形区域的左边和右边无限接近时,就可以把它看做一条直线,然后就可以得到中间线和path的相交点,这样就可以确定头像的位置了。
高级UI--有趣的水波纹



核心代码:

public WaveView(Context context, AttributeSet attrs) {
    super(context, attrs);
    //初始化自定义属性
    initAttrs(context, attrs);
    init();
}


private void init() {
    paint = new Paint();
    paint.setColor(getResources().getColor(R.color.colorPrimary));
    paint.setStyle(Paint.Style.FILL_AND_STROKE);  //填充

    path = new Path();


}

/**
 * 初始化自定义属性
 * @param context
 * @param attrs
 */
private void initAttrs(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
    waveView_boatBitmap = a.getResourceId(R.styleable.WaveView_boatBitmap, 0);
    rise = a.getBoolean(R.styleable.WaveView_rise, false);
    waveLength = (int) a.getDimension(R.styleable.WaveView_waveLength, 400);
    originY = (int) a.getDimension(R.styleable.WaveView_originY, 500);
    waveHeight = (int) a.getDimension(R.styleable.WaveView_waveHeight, 200);
    duration = (int) a.getDimension(R.styleable.WaveView_duration,2000);
    a.recycle();

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 2;
    if(waveView_boatBitmap > 0){
        mBitmap = BitmapFactory.decodeResource(getResources(),waveView_boatBitmap,options);
        mBitmap = getCircleBitmap(mBitmap);
    }else{
        mBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher,options);
    }

}

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

    //画水波纹曲线
    //定义曲线path
    setPathData();
    canvas.drawPath(path, paint);

    //绘制头像
    Rect bounds = region.getBounds();
    if(bounds.top > 0 || bounds.right > 0){
        if(bounds.top < originY){
            canvas.drawBitmap(mBitmap,bounds.right-mBitmap.getWidth()/2,bounds.top-mBitmap.getHeight(),paint);
        }else{
            canvas.drawBitmap(mBitmap,bounds.right-mBitmap.getWidth()/2,bounds.bottom-mBitmap.getHeight(),paint);
        }

    }else{
        float x = width/2 - mBitmap.getWidth()/2;
        canvas.drawBitmap(mBitmap,x,originY-mBitmap.getHeight(),paint);
    }
}

/**
 * 绘制曲线路径
 */
private void setPathData() {
    //贝塞尔曲线
    path.reset();;
    int halfWaveLength = waveLength / 2;
    //dx,使view不断右移,达到动起来效果
    path.moveTo(-waveLength+dx,originY);
    //需要多画一个波长,万一只剩一点点,否则就空白了一些
    for (int i = -waveLength; i < width+waveLength; i+= waveLength) {
        //画一个完整的波长,拆分成波峰和波谷
        //
        //rQuadTo 相对位置的,相对于中间的基准线
        path.rQuadTo(halfWaveLength/2, -waveHeight,halfWaveLength,0);
        path.rQuadTo(halfWaveLength/2, waveHeight,halfWaveLength,0);
    }
    //确定中间图片的位置
    //曲线和中间线的相交
    //区域范围
    float x = width / 2;
    region = new Region();
    //这样设置,矩形的左边和右边无限逼近,(也就差不多是一根直线了)
    Region clip = new Region((int)(x-0.1),0,(int)x,height);
    //用一个矩形区域去切割一个path路径,得到一个矩形区域
    region.setPath(path,clip);


    //补充封闭的线
    path.lineTo(width,height);
    path.lineTo(0,height);
    path.close();  //最后的关闭,会自动连接起来
}

/**
 * 开启动画
 */
public void startAnimation(){
    animator = ValueAnimator.ofFloat(0,1);
    //不断的执行
    animator.setRepeatCount(ValueAnimator.INFINITE);
    //使动画不卡顿,不用这个,会动一下,然后卡一下
    animator.setInterpolator(new LinearInterpolator());
    animator.setDuration(duration);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float fraction = (float) valueAnimator.getAnimatedValue();  //0-1
            dx = (int) (waveLength * fraction);
            postInvalidate();  //然后重新绘制,调用ondraw,使循环运动。
        }
    });

    animator.start();

}

/**
 * 得到圆形的图片
 * @param bitmap
 * @return
 */
public Bitmap getCircleBitmap(Bitmap bitmap){
    try {
        Bitmap circleBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(),Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(circleBitmap);
        final Paint paint = new Paint();
        final Rect rect = new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
        final RectF rectF = new RectF(new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()));
        float roundPx = 0.0f;
        //以较短的为准
        if(bitmap.getWidth() > bitmap.getHeight()){
            roundPx = bitmap.getHeight() / 2.0f;
        }else{
            roundPx = bitmap.getWidth() / 2.0f;
        }
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.WHITE);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        //图片和圆形相交的部分,取图片上相交的
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        final Rect src = new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
        canvas.drawBitmap(bitmap,src,rect,paint);
        return circleBitmap;
    }catch (Exception e){
        return bitmap;
    }

}

源码下载:http://download.csdn.net/download/shenbin1/10027671


相关文章:

  • 2022-12-23
  • 2022-01-15
  • 2021-12-03
  • 2018-12-08
  • 2022-01-26
  • 2021-11-19
  • 2021-09-11
  • 2021-08-24
猜你喜欢
  • 2019-11-21
  • 2022-12-23
  • 2021-08-04
  • 2021-09-15
  • 2021-12-14
  • 2022-01-19
  • 2022-12-23
相关资源
相似解决方案