当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义View实现水波纹引导动画

Android自定义View实现水波纹引导动画

2019年07月24日  | 移动技术网IT编程  | 我要评论

王成山,河南省人社厅,保尔呕心沥血写小说

一、实现效果图

关于贝塞尔曲线

二、实现代码

1.自定义view

package com.czhappy.showintroduce.view;

import android.content.context;
import android.graphics.bitmap;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.path;
import android.util.attributeset;
import android.view.view;
import android.widget.relativelayout;

/**
 * description: 水波纹动画引导view
 * user: chenzheng
 * date: 2017/1/14 0014
 * time: 18:01
 */
public class rippleintroview extends relativelayout implements runnable {

 private int mmaxradius = 70;
 private int minterval = 20;
 private int count = 0;

 private bitmap mcachebitmap;
 private paint mripplepaint;
 private paint mcirclepaint;
 private path marcpath;

 public rippleintroview(context context) {
  this(context, null);
 }

 public rippleintroview(context context, attributeset attrs) {
  this(context, attrs, 0);
 }

 public rippleintroview(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  init();
 }

 private void init() {
  mripplepaint = new paint();
  mripplepaint.setantialias(true);
  mripplepaint.setstyle(paint.style.stroke);
  mripplepaint.setcolor(color.white);
  mripplepaint.setstrokewidth(2.f);

  mcirclepaint = new paint();
  mcirclepaint.setantialias(true);
  mcirclepaint.setstyle(paint.style.fill);
  mcirclepaint.setcolor(color.white);

  marcpath = new path();
 }

 /**
  * view大小变化时系统调用
  * @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);
  if (mcachebitmap != null) {
   mcachebitmap.recycle();
   mcachebitmap = null;
  }
 }

 @override
 protected void ondraw(canvas canvas) {
  //获取加号图片view
  view mpluschild = getchildat(0);
  //获取提示图片view
  view mrefschild = getchildat(1);
  if (mpluschild == null || mrefschild == null) return;

  //获取加号图片大小
  final int pw = mpluschild.getwidth();
  final int ph = mpluschild.getheight();

  //获取提示图片大小
  final int fw = mrefschild.getwidth();
  final int fh = mrefschild.getheight();

  if (pw == 0 || ph == 0) return;

  //加号图片中心点坐标
  final float px = mpluschild.getx() + pw / 2;
  final float py = mpluschild.gety() + ph / 2;
  //提示图片左上角坐标
  final float fx = mrefschild.getx();
  final float fy = mrefschild.gety();

  final int rw = pw / 2;
  final int rh = ph / 2;

  if (mcachebitmap == null) {
   mcachebitmap = bitmap.createbitmap(getwidth(), getheight(), bitmap.config.argb_8888);
   canvas cv = new canvas(mcachebitmap);
   super.ondraw(cv);

   //清空所有已经画过的path至原始状态
   marcpath.reset();

   //起始轮廓点移至x,y坐标点,即加号图片正下方再往下20位置
   marcpath.moveto(px, py + rh + minterval);
   //设置二次贝塞尔,实现平滑曲线,前两个参数为操作点坐标,后两个参数为结束点坐标
   marcpath.quadto(px, fy - minterval, fx + fw * 0.618f, fy - minterval);
   //0~255,数值越小越透明
   mripplepaint.setalpha(255);
   cv.drawpath(marcpath, mripplepaint);
   //绘制半径为6的实心圆点
   cv.drawcircle(px, py + rh + minterval, 6, mcirclepaint);
  }

  //绘制背景图片
  canvas.drawbitmap(mcachebitmap, 0, 0, mcirclepaint);

  //保存画布当前的状态
  int save = canvas.save();
  for (int step = count; step <= mmaxradius; step += minterval) {
   //step越大越靠外就越透明
   mripplepaint.setalpha(255 * (mmaxradius - step) / mmaxradius);
   canvas.drawcircle(px, py, (float) (rw + step), mripplepaint);
  }
  //恢复canvas的状态
  canvas.restoretocount(save);
  //延迟80毫秒后开始运行
  postdelayed(this, 80);
 }

 @override
 public void run() {
  //把run对象的引用从队列里拿出来,这样,他就不会执行了,但 run 没有销毁
  removecallbacks(this);
  count += 2;
  count %= minterval;
  invalidate();//重绘
 }

 /**
  * 销毁view时调用,收尾工作
  */
 @override
 protected void ondetachedfromwindow() {
  super.ondetachedfromwindow();
  if (mcachebitmap != null) {
   mcachebitmap.recycle();
   mcachebitmap = null;
  }
 }
}

2.mainactivity.java

package com.czhappy.showintroduce.activity;

import android.os.bundle;
import android.support.v7.app.appcompatactivity;
import android.view.view;
import android.view.viewgroup;

import com.czhappy.showintroduce.r;

public class mainactivity extends appcompatactivity {

 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);

  view view = findviewbyid(r.id.layout_ripple);
  view.setonclicklistener(new view.onclicklistener() {
   @override
   public void onclick(view v) {
    ((viewgroup) v.getparent()).removeview(v);
   }
  });
 }
}

3.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<framelayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <textview
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="hello world!" />

 <com.czhappy.showintroduce.view.rippleintroview
  android:id="@+id/layout_ripple"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:clickable="true"
  android:fitssystemwindows="true"
  android:background="#aa000000">

  <imageview
   android:id="@+id/iv_plus"
   android:layout_margintop="36dp"
   android:src="@mipmap/ic_add"
   android:layout_alignparentright="true"
   android:layout_marginright="6dp"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

  <imageview
   android:src="@mipmap/tips_subscribe"
   android:id="@+id/tv_title"
   android:layout_below="@id/iv_plus"
   android:layout_margintop="50dp"
   android:layout_alignparentright="true"
   android:layout_marginright="40dp"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

 </com.czhappy.showintroduce.view.rippleintroview>

</framelayout>

三、源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网