欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android自定义波浪加载动画的实现代码

程序员文章站 2023-10-29 12:47:40
本文实例为大家分享了android自定义波浪加载动画的具体代码,供大家参考,具体内容如下 效果图 1.自定义控件 waveview package com...

本文实例为大家分享了android自定义波浪加载动画的具体代码,供大家参考,具体内容如下

效果图

android自定义波浪加载动画的实现代码

1.自定义控件 waveview

package com.example.wh.myapplication;
 
 
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.path;
import android.support.annotation.nullable;
import android.support.v4.content.contextcompat;
import android.util.attributeset;
import android.view.view;
 
import java.text.decimalformat;
public class waveview extends view {
 
 /**
 * 默认波浪1长度
 */
 private final int wave_length1 = 600;
 
 /**
 * 默认波浪1高度
 */
 private final int wave_height1 = 30;
 
 /**
 * 波浪1高度
 */
 private int mwaveheight1 = wave_height1;
 
 /**
 * 波浪1长度
 */
 private int mwavelenght1 = wave_length1;
 
 /**
 * 默认波浪1颜色
 */
 private final int wave_color1 = color.parsecolor("#0000ff");
 
 /**
 * 默认边框颜色
 */
 private final int border_color = color.parsecolor("#800000ff");
 
 /**
 * 默认文字颜色
 */
 private final int default_text_color = color.parsecolor("#ff0000");
 /**
 * 默认文字大小
 */
 private final int default_text_size = 30;
 
 /**
 * 文字颜色
 */
 private int mtextcolor = default_text_color;
 /**
 * 文字大小
 */
 private int mtextsize = default_text_size;
 
 /**
 * 波浪1颜色
 */
 private int mwavecolor1 = wave_color1;
 
 /**
 * 默认每一次重绘时波峰1的移动的距离,实现移动效果
 */
 private final int wave_offset1 = 8;
 
 /**
 * 每一次重绘时波峰1的移动的距离,实现移动效果
 */
 private int moffset1 = wave_offset1;
 
 /**
 * 默认边框宽度
 */
 private final int border_width = 2;
 
 /**
 * 边框颜色
 */
 private int mbordercolor = border_color;
 
 /**
 * 边框宽度
 */
 private int mborderwidth = border_width;
 
 /**
 * 绘制的高度,百分比。0表示内有高度,1表示全部高度
 */
 private float mprecent = 0.5f;
 
 /**
 * 形状枚举,暂时只支持矩形和圆形,可扩展
 */
 public enum showshape {
 rect
 }
 
 /**
 * 形状默认矩形
 */
 private showshape mshape = showshape.rect;
 
 /**
 * 默认两次重绘之间间隔的时间,5毫秒
 */
 private final int default_time = 5;
 
 /**
 * 两次重绘之间间隔的时间,毫秒。
 */
 private int mtime = default_time;
 
 /**
 * 设置两次重绘之间的间隔时间,毫秒
 *
 * @param time
 * @return
 */
 public waveview settime(int time) {
 this.mtime = time;
 return this;
 }
 
 /**
 * 波浪1画笔
 */
 private paint mwavepaint1;
 
 /**
 * 边框画笔
 */
 private paint mborderpaint;
 /**
 * 文字画笔
 */
 private paint mtextpaint;
 
 /**
 * 波浪1路径
 */
 private path mwavepath1;
 
 /**
 * 定义数字格式转行类
 */
 private decimalformat mformat;
 
 /**
 * 控件的宽度
 */
 private int mwidth;
 /**
 * 控件的高度
 */
 private int mheight;
 
 /**
 * 水位上升时不断变化的 y 坐标
 */
 private float mchangey;
 
 /**
 * 水位最终的高度,通过控件的高度和百分比计算出来
 */
 private float mfinaly;
 
 /**
 * 波峰的个数
 */
 private int mwavecount = 8;
 
 /**
 * 重置标记,开始为重置状态
 */
 private boolean isreset = true;
 
 
 /**
 * 当前百分比
 */
 private float mcurrentprecent = 0.0f;
 
 /**
 * 重绘值波峰移动距离的和
 */
 private int mmovesum1;
 
 /**
 * 能够绘制标记位,开始不能绘制
 */
 private boolean invalidateflag = false;
 
 /**
 * 百分比改变监听
 */
 private precentchangelistener mprecentchangelistener;
 
 
 /**
 * 百分比改变监听接口
 */
 public interface precentchangelistener {
 /**
  * 百分比发生改变时调用的方法
  *
  * @param precent 当前的百分比,格式 0.00 范围 [0.00 , 1.00]
  */
 void precentchange(double precent);
 }
 
 
 public waveview(context context) {
 this(context, null);
 }
 
 public waveview(context context, @nullable attributeset attrs) {
 this(context, attrs, 0);
 }
 
 public waveview(context context, @nullable attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);
 
 initattrs(context, attrs); // 获取布局文件中dingy9i的属性
 init();
 }
 
 //获取布局中的初始属性
 private void initattrs(context context, attributeset attrs) {
 typedarray typedarray = context.obtainstyledattributes(attrs, r.styleable.waveview);
 mwavelenght1 = typedarray.getinteger(r.styleable.waveview_wave1length, wave_length1);
 mwaveheight1 = typedarray.getinteger(r.styleable.waveview_wave1height, wave_height1);
 mwavecolor1 = typedarray.getcolor(r.styleable.waveview_wave1color, wave_color1);
 moffset1 = typedarray.getinteger(r.styleable.waveview_wave1offset, wave_offset1);
 
 mborderwidth = typedarray.getdimensionpixelsize(r.styleable.waveview_borderwidth, border_width);
 mbordercolor = typedarray.getcolor(r.styleable.waveview_bordercolor, border_color);
 
 mtime = typedarray.getinteger(r.styleable.waveview_intervaltime, default_time);
 mprecent = typedarray.getfloat(r.styleable.waveview_precent, 0.5f);
 /**
  * 绘制的高度,百分比。0表示内有高度,1表示全部高度
  */
 int shapevalue = typedarray.getinteger(r.styleable.waveview_showshape, 0);
 
 mshape = showshape.rect;
 typedarray.recycle();
 }
 
 private void init() {
 mwavepaint1 = new paint(paint.anti_alias_flag);
 mborderpaint = new paint(paint.anti_alias_flag);
 mtextpaint = new paint(paint.anti_alias_flag);
 
 mwavepath1 = new path();
 
 mwavepaint1.setcolor(mwavecolor1);
 mwavepaint1.setstyle(paint.style.fill);
 
 mborderpaint.setcolor(mbordercolor);
 mborderpaint.setstrokewidth(mborderwidth);
 mborderpaint.setstyle(paint.style.stroke);
 
 
 mtextpaint.setcolor(mtextcolor);
 mtextpaint.settextsize(mtextsize);
 
 // 定义数字显示个格式
 mformat = new decimalformat("###,###,##0.00");
 }
 
 @override
 protected void onsizechanged(int w, int h, int oldw, int oldh) {
 super.onsizechanged(w, h, oldw, oldh);
 mwidth = w;
 mheight = h;
 
 mchangey = mheight;
 // 计算波峰个数,为了实现移动效果,保证至少绘制两个波峰
 mfinaly = (1 - mprecent) * mheight; // 计算水位最终高度
 }
 
 @override
 protected void ondraw(canvas canvas) {
 mwavepath1.reset();
 
 
 if (mborderwidth > 0) {
  // 边框大于0,表示需要绘制边框
  if(mshape == showshape.rect) {
  canvas.drawrect(0, 0, mwidth, mheight, mborderpaint);
  }
 }
 
 mwavepath1.moveto(-mwavelenght1, mchangey);
 
 if (!isreset) { // 判断重置标记
  // 利用贝塞尔曲线绘制波浪
  for (int i = 0; i < mwavecount; i++) {
  // 绘制波浪1的曲线
  mwavepath1.quadto((-mwavelenght1 * 3 / 4) + (i * mwavelenght1) + mmovesum1, mchangey + mwaveheight1, (-mwavelenght1 / 2) + (i * mwavelenght1) + mmovesum1, mchangey);
  mwavepath1.quadto((-mwavelenght1 * 1 / 4) + (i * mwavelenght1) + mmovesum1, mchangey - mwaveheight1, (i * mwavelenght1) + mmovesum1, mchangey);
 
  }
 
  // 不断改变高度,实现逐渐水位逐渐上涨效果
  mchangey -= 1;
  if (mchangey < mfinaly) mchangey = mfinaly;
 
  // 波峰1往右移动,波峰2往左移动
  mmovesum1 += moffset1;
  if (mmovesum1 >= mwavelenght1) mmovesum1 = 0;
 
  // 填充矩形,让上涨之后的水位下面填充颜色
  mwavepath1.lineto(mwidth, mheight);
  mwavepath1.lineto(0, mheight);
  mwavepath1.close();
 
  canvas.drawpath(mwavepath1, mwavepaint1);
 } else {
  // 是重置
  canvas.drawcolor(color.transparent);
 }
 
 // 计算当前的百分比
 mcurrentprecent = 1 - mchangey / mheight;
 // 格式化数字格式
 string format1 = mformat.format(mcurrentprecent);
 // 绘制文字,将百分比绘制到界面。此处用的是 "50%" 的形式,可以根据需求改变格式
 double parsedouble = double.parsedouble(format1);
 canvas.drawtext((int) (parsedouble * 100) + " %", (mwidth - mtextpaint.measuretext(format1)) / 2, mheight / 5, mtextpaint);
 // 监听对象不为null并且没有达到设置高度时,调用监听方法
 if (mprecentchangelistener != null && mchangey != mfinaly) {
  mprecentchangelistener.precentchange(parsedouble);
 }
 
 //高度到达设置高度
 if (mchangey == mfinaly){
  canvas.drawcolor(contextcompat.getcolor(getcontext(), r.color.bowencolor));
 }
 
 // 判断绘制标记
 if (invalidateflag) postinvalidatedelayed(mtime);
 }
 
 /**
 * 设置边框宽度
 *
 * @param borderwidth
 * @return
 */
 public waveview setborderwidth(int borderwidth) {
 this.mborderwidth = borderwidth;
 return this;
 }
 
 /**
 * 设置波浪1颜色
 *
 * @param wavecolor1
 * @return
 */
 public waveview setwavecolor1(int wavecolor1) {
 this.mwavecolor1 = wavecolor1;
 return this;
 }
 
 /**
 * 设置边框颜色
 *
 * @param bordercolor
 * @return
 */
 public waveview setbordercolor(int bordercolor) {
 this.mbordercolor = bordercolor;
 return this;
 }
 
 /**
 * 设置文字颜色
 *
 * @param textcolor
 * @return
 */
 public waveview settextcolor(int textcolor) {
 this.mtextcolor = textcolor;
 return this;
 }
 
 /**
 * 设置百分比
 *
 * @param precent
 * @return
 */
 public waveview setprecent(float precent) {
 this.mprecent = precent;
 return this;
 }
 
 
 /**
 * 设置文字大小
 *
 * @param textsize
 * @return
 */
 public waveview settextsize(int textsize) {
 this.mtextsize = textsize;
 return this;
 }
 
 
 /**
 * 设置当前显示形状
 *
 * @param shape
 * @return
 */
 public waveview setshape(showshape shape) {
 this.mshape = shape;
 return this;
 }
 
 /**
 * 开始
 */
 public void start() {
 invalidateflag = true;
 isreset = false;
 postinvalidatedelayed(mtime);
 }
 
 /**
 * 暂停
 */
 public void stop() {
 invalidateflag = false;
 isreset = false;
 }
 
 /**
 * 重置
 */
 public void reset() {
 invalidateflag = false;
 isreset = true;
 mchangey = mheight;
 postinvalidate();
 }
}

2.attrs

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <!--自定义水波纹效果属性-->
 <declare-styleable name="waveview">
 <!--波浪1的长度、高度、颜色和每次重绘的偏移量-->
 <attr name="wave1length" format="integer" />
 <attr name="wave1height" format="integer" />
 <attr name="wave1color" format="color" />
 <attr name="wave1offset" format="integer" />
 
 <!--边框的宽度和颜色-->
 <attr name="borderwidth" format="dimension" />
 <attr name="bordercolor" format="color" />
 <!--文字的大小和颜色-->
 <attr name="textcolor" format="color" />
 <attr name="textsize" format="dimension" />
 <!--水位高度的百分比-->
 <attr name="precent" format="float" />
 <!--两次重绘的间隔时间-->
 <attr name="intervaltime" format="integer" />
 <!--控件的显示形状,rect矩形、circle圆形-->
 <attr name="showshape" format="enum">
  <enum name="rect" value="0" />
  <enum name="circle" value="1" />
 </attr>
 </declare-styleable>
</resources>

3.布局

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context="com.example.wh.myapplication.mainactivity">
 
 <com.example.wh.myapplication.waveview
 android:id="@+id/waveview1"
 android:layout_width="200dp"
 android:layout_height="200dp" />
 
 <linearlayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_margintop="30dp"
 android:orientation="horizontal">
 
 <button
  android:id="@+id/bt_start"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_weight="1"
  android:text="开始"/>
 
 <button
  android:id="@+id/bt_stop"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_weight="1"
  android:text="暂停"/>
 
 <button
  android:id="@+id/bt_reset"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_weight="1"
  android:text="重置"/>
 </linearlayout>
</linearlayout>

4.mainactivity

package com.example.wh.myapplication;
 
import android.graphics.color;
import android.support.v7.app.appcompatactivity;
import android.os.bundle;
import android.view.view;
import android.widget.button;
 
public class mainactivity extends appcompatactivity {
 
 private waveview waveview1;
 private button btstart;
 private button btstop;
 private button btreset;
 
 @override
 protected void oncreate(bundle savedinstancestate) {
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);
 
 waveview1 = (waveview) findviewbyid(r.id.waveview1);
 
 btstart = (button) findviewbyid(r.id.bt_start);
 btstop = (button) findviewbyid(r.id.bt_stop);
 btreset = (button) findviewbyid(r.id.bt_reset);
 
 // 代码设置相关属性
 waveview1.setborderwidth(2)
  .setwavecolor1(color.red)
  .setbordercolor(color.green)
  .settextcolor(color.blue)
  .setshape(waveview.showshape.rect)
  .settextsize(36)
  .setprecent(1f)//设置水波纹的百分比
  .settime(2);
 
 btstart.setonclicklistener(new view.onclicklistener() {
  @override
  public void onclick(view v) {
  waveview1.start();
  }
 });
 
 btstop.setonclicklistener(new view.onclicklistener() {
  @override
  public void onclick(view v) {
  waveview1.stop();
  }
 });
 
 btreset.setonclicklistener(new view.onclicklistener() {
  @override
  public void onclick(view v) {
  waveview1.reset();
  }
 });
 }
}

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