自定义View-第十七步:水波效果RadialGradient

前言

根据启舰大大 的博客所学习的自定义View。

一、RadialGradient详解

RadialGradient的意思是放射渐变,即它会向一个放射源一样,从一个点开始向外从一个颜色渐变成另一种颜色;

//两色渐变
RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
//多色渐变
RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)
  • (centerX ,centerY):渐变中心点坐标(x,y)
  • radius:渐变半径
  • centerColor:渐变的起始颜色,即渐变中心点的颜色,取值类型必须是八位的0xAARRGGBB色值!透明底Alpha值不能省略,不然不会显示出颜色。
  • edgeColor:渐变结束时的颜色,即渐变圆边缘的颜色,同样,取值类型必须是八位的0xAARRGGBB色值!
  • TileMode:与我们前面讲的各个Shader一样,用于指定当控件区域大于指定的渐变区域时,空白区域的颜色填充方式。

二、小试牛刀

        //多色渐变
        int[]   colors = new int[]{0xffff0000,0xff00ff00,0xff0000ff,0xffffff00};
        float[] stops  = new float[]{0f,0.4f,0.6f,1f};

        paint.setShader(new RadialGradient(100,100,50,colors,stops, Shader.TileMode.CLAMP));
        canvas.drawCircle(100,100,100,paint);

        //双色渐变
        paint.setShader(new RadialGradient(300,300,50,0xffff0000, 0xff0000ff,Shader.TileMode.MIRROR));
        canvas.drawCircle(300,300,150,paint);
效果图

ps:看着第二个镜像是不是有点晕呢?嘿嘿,我也晕了,其实是由红变蓝,再由蓝变红,再由红变蓝......这样子继续下去,白色的那条线就是每一圈渐变的边界,(⊙o⊙)…有点不清晰,大家可以自己画个大大的圆试试

三、水波纹效果

先看效果图吧

水波纹效果

源码如下:

public class MineView extends View {
    private Paint paint;
    float radius;
    ValueAnimator animator;
    int width; //控件的宽度
    int x, y; //当前触摸点的位置

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

    public MineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
       //在这可以获取控件宽度,不要在初始化的时候获取,那时候是获取不到的
        width = getMeasuredWidth();
        animator = ValueAnimator.ofInt(50, width);
        animator.setDuration(1000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                radius = (int) animation.getAnimatedValue();
                updateShader();
            }
        });

        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                radius = 0;
                updateShader();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setLayerType(LAYER_TYPE_SOFTWARE, null);//对单独的View在运行时阶段禁用硬件加速
        canvas.drawColor(Color.LTGRAY);
        canvas.drawCircle(x, y, radius, paint);
    }

    private void updateShader() {
        if (x > 0 && y > 0 && radius > 0) {
            //从零透明度逐渐变为绿色
            RadialGradient radialGradient = new RadialGradient(x, y, radius, 0x00FFFFFF, 0xFF00FF00, Shader.TileMode.CLAMP);
            paint.setShader(radialGradient);
        }
        postInvalidate();
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (x != event.getX() || y != event.getY()) {
            x = (int) event.getX();
            y = (int) event.getY();
            radius = 50;
            updateShader();
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return true;
            case MotionEvent.ACTION_UP:
                if (animator != null) {
                    if (animator.isRunning()) animator.cancel();
                    animator.start();
                }
                break;
        }
        return super.onTouchEvent(event);
    }
}

小知识

getMeasureWidth()方法在measure()过程结束后就可以获取到了,
而getWidth()方法要在layout()过程结束后才能获取到

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 系列文章之 Android中自定义View(一)系列文章之 Android中自定义View(二)系列文章之 And...
    YoungerDev阅读 2,201评论 0 4
  • 一、学习任务 英语 记背单词 新65 旧62 何凯文每日一句更新 线代一章节 二、日常生活 玩和吃,恋家
    狂野的孩儿也狂野阅读 170评论 0 0
  • 武志红的心理学7.20直播笔记 当我们在公共场所排队、挤公交、挤地铁时,当有人离我们很近时,我们会有一种不适感。在...
    被吹起来的猪阅读 419评论 2 0
  • 家附近的地方现在变成了工业园区。为了修厂,需要推出一大块平地,但在重庆这里要靠老天爷赐予一片平地,不是容易的事。所...
    zotin95阅读 352评论 0 1