自定义View详解(3)

大家教师节快乐啊,不知道勤学的Coder们有没有去尝试下绘制上篇文章中最后留下的进阶效果,不管怎样,还是一起动手写一遍吧!看看套路是否一致。


水波纹

 


首先来看图-水波纹中的效果,其具有以下特点:

  • 从内到外四层,内圆外环;

  • 从内到外四个色值;

  • 最内部圆局于View中心;

  • 圆和环同心;

看出以下几点,我们就可以开始按照套路画图了,老套路走起(在以后自定义View部分新建项目及类相关的描述不再赘述)。

声明画笔和宽高

1.声明画笔及宽高
如上分析,我们需要两个画笔,一个用于绘制内圆,一个用于绘制外环。

/**
   * 绘制最中心圆的Paint
   */
  private Paint mInnerCirclePaint;

  /**
   * 绘制外部圆环的Paint
   */
  private Paint mOutterRingPaint;

  /**
   * View宽度
   */
  private int mWidth;

  /**
   * View高度
   */
  private int mHeight;

  /**
   * 外环宽度
   */
  private int mOuttterRingWidth = 50;

2.初始化画笔并在构造函数内调用
由于外部为圆环,所以外部画笔样式设置为空心,内部圆画笔样式设置为实心,同时设置画笔宽度为外部圆环宽度。

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

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

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

  private void init() {
    mInnerCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mInnerCirclePaint.setColor(Color.BLUE);
    /** 内部画笔为实心 **/
    mInnerCirclePaint.setStyle(Style.FILL);

    mOutterRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mOutterRingPaint.setColor(Color.BLUE);
    /** 外部画笔为空心 **/
    mOutterRingPaint.setStyle(Style.STROKE);
    mOutterRingPaint.setStrokeWidth(mOuttterRingWidth);
  }

3.初始化宽高

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    if (w > 0 && h > 0){
      mWidth = w;
      mHeight = h;
    }
  }

计算Points

声明内圆半径,圆环宽度,计算各圆的半径,同心圆及圆环,圆心位于View中心。

 

如图-水波纹内部距离说明,外环所在圆依次为(radius为外环半径,mInnerRadius为内圆半径,mOutterRingWidth为环宽度):

一环:半径与内圆半径一致,radius = mInnerRadius+(mOutterRingWidth/2)1; 二环:半径等于内圆半径+圆环宽度,radius = mInnerRadius + (mOutterRingWidth/2)3;

依次类推,我们可以得到外部圆环半径公式:

radius = mInnerRadius + (mOutterRingWidth/2) * i;(i取1,3,5,7,9…)

如此我们就可以开始撸码了。

  /*  声明必要变量 */
  /**
   * 内圆半径
   */
  private int mInnerRadius = 50;

  /**
   * 存储计算所得的外环半径
   */
  private int[] mRadius = new int[4];
  /* 计算外环半径 */
  private void calculateRadius() {
    for (int i = 0; i < 4; i++) {
      mRadius[i] = mInnerRadius + (i * 2 + 1) * mOuttterRingWidth / 2;
    }
  }

获取画布绘制圆及圆环

重写onDraw函数获取canvas,并绘制圆环及内圆。

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    calculateRadius();
    canvas.drawCircle(mWidth / 2, mHeight / 2, mInnerRadius, mInnerCirclePaint);
    for (int i = 0; i < 4; i++) {
      /** 改变外环的颜色透明度 **/
      mOutterRingPaint.setAlpha(255 - (int) (255 * ((float) (i + 1) / 5)));
      canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius[i], mOutterRingPaint);
    }
  }

至于运行效果,大家自己动手试一下喽!


动起来的水波纹

虽然我们画出来了水波纹,但是和蔼的产品还是会批斗你的,他会说,你家水波纹静态的哦?这一秒钟心里是不是有一万只羊驼奔腾?哈哈!奔腾归奔腾,需求我们还是要实现下滴。

那么我们来观察下现实中的水波纹,不难发现与图-水波纹形成 相似的过程。

 

我们可以看出水波纹动态形成的本质是,外部圆环逐步扩张增加形成的。那么我们只需要动态控制外部圆环的绘制个数,就可以让它动起来了。

属性动画

说到控制外环个数动态增长,做过动画的朋友第一个直觉肯定就是属性动画喽,这样是值变化,所以我们使用ValueAnimator即可(关于属性动画,帧动画,View动画相关的细节,我们在后续文章中单独说明)。

1.声明动画相关的成员

  /**
   * 控制外环个数变化的属性动画对象
   */
  private ValueAnimator mValueAnimator;

  /**
   * 绘制的外环总个数
   */
  private int mOutterRingCount = 4;

2.初始化动画对象并开始

public void startAnimation(){
    //创建ValueAnimator对象,按照整型值从0变化到4
    mValueAnimator = ValueAnimator.ofInt(0,5);
    //设置动画重复类型,RESTART--重新开始,REVERSE--值反转
    mValueAnimator.setRepeatMode(ValueAnimator.RESTART);
    //设置动画重复次数,-1--不限制次数
    mValueAnimator.setRepeatCount(-1);
    mValueAnimator.setDuration(2000);
    mValueAnimator.addUpdateListener(new AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator valueAnimator) {
        mOutterRingCount = (int) valueAnimator.getAnimatedValue();
        postInvalidate();
      }
    });
    mValueAnimator.start();
  }

3.更新onDraw循环参数

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    calculateRadius();
    canvas.drawCircle(mWidth / 2, mHeight / 2, mInnerRadius, mInnerCirclePaint);
    for (int i = 0; i < mOutterRingCount; i++) {
      mOutterRingPaint.setAlpha(255 - (int) (255 * ((float) (i + 1) / 5)));
      canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius[i], mOutterRingPaint);
    }
  }

运行效果见gif,至此我们就完成了水波纹自定义View的开发,怎么样?是不是很有趣啊.

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值