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

Android漂浮背景效果的制作方法

程序员文章站 2023-12-19 17:42:34
gif动图效果不是很好,实际效果非常平滑very smooth,而且添加不同的图形可以组成各种效果,目前已经用在我们项目的注册界面~ 原理: 实现原理很简单,每一个...

gif动图效果不是很好,实际效果非常平滑very smooth,而且添加不同的图形可以组成各种效果,目前已经用在我们项目的注册界面~

Android漂浮背景效果的制作方法

原理:

实现原理很简单,每一个悬浮的“小物体”就是一个自定义view,这些小的自定义view都盛放在一个自定义的viewgroup中。然后所有的视图都放在这个viewgroup之上,这样就相当于做一个可动的背景。

下面结合代码详细介绍下:

详解:

floatobject

悬浮的物体,继承自view,需要重写ondraw方法,主要作用就是来画出自己,并进行随机曲线运动。

任何需要画出的对象都需要继承floatobject,并重写提供的drawfloatobject方法,在此方法中可以通过设置画笔和画布画出任意图形。比如下面是画出一行文字:

public class floattext extends floatobject {
 string text;

 public floattext(float posx, float posy, string text) {
 super(posx, posy);
 this.text = text;
 setalpha(88);
 setcolor(color.white);
 }

 @override
 public void drawfloatobject(canvas canvas, float x, float y, paint paint) {
 paint.settextsize(65);
 canvas.drawtext(text, x, y, paint);
 }
}

随机曲线:

其实最复杂的部分就是让漂浮的物体做随机无规则的曲线运动,并且每个漂浮物的速度不同,这样整个漂浮动画才更加自然。

我之前想过使用布朗运动,但是在网上找了好久也没找到一个好用的算法。

最后只能还是使用3点赛贝尔曲线,使漂浮物沿着一条赛贝尔曲线运动,达到终点时,再随机产生一条新的曲线,这样就可以实现随机曲线运动了。

控制运动的代码如下:

public void drawfloatitem(canvas canvas) {

 switch (status) {
  case start:
  // fade in
  if (isfade() && alpha <= alpha_limit) {
   paint.setalpha(alpha);
   alpha += alpha_per_frame;
  } else {
   setstatus(move);
  }
  break;
  case move:
  // 更新赛贝尔曲线点
  if (mcurdistance == 0) {
   start = new pointf(x, y);
   end = getrandompoint((int)start.x, (int)start.y, (int) distance);// 取值范围distance
   c1 = getrandompoint((int)start.x, (int)start.y, random.nextint(width / 2)); // 取值范围width/2
   c2 = getrandompoint(end.x, end.y, random.nextint(width / 2));// 取值范围width/2
  }

  // 计算塞贝儿曲线的当前点
  pointf bezierpoint = calculatebezierpoint(mcurdistance / distance, start, c1, c2, end);
  x = bezierpoint.x;
  y = bezierpoint.y;

  // 更新当前路径
  mcurdistance += move_per_frame;

  // 一段画完后重置
  if (mcurdistance >= distance) {
   mcurdistance = 0;
  }
  break;
  case end:
  // fade out
  if (isfade() && alpha > 0) {
   paint.setalpha(alpha);
   alpha -= alpha_per_frame;
  } else {
   setstatus(finish);
  }
  break;
 }

 if (status != finish) {
  log.e("drawfloatobject", x+", "+y);
  drawfloatobject(canvas, x ,y, paint);
 }
 }

关于赛贝尔曲线运动的算法都是复用之前写的一篇文章android模拟火花粒子的滑动喷射效果,如果大家有兴趣可以看看。

floatbackground

floatbackground继承自framelayout,里面有一个用于存放floatobject的集合。
floatbackground的主要作用就是绘制所有的“漂浮物”,以及维护其生命周期:

初始化:

 private void initfloatobject(int width, int height) {
 for (floatobject floatobject : floats) {
  int x = (int) (floatobject.posx * width);
  int y = (int) (floatobject.posy * height);
  floatobject.init(x, y, width, height);
 }
 }

绘制:

 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 for (floatobject floatobject : floats) {
  floatobject.drawfloatitem(canvas);
 }
 // 隔一段时间重绘一次, 动画效果
 gethandler().postdelayed(runnable, delay);

 }

 // 重绘线程
 private runnable runnable = new runnable() {
 @override
 public void run() {
  invalidate();
  // 控制帧数
 }
 };

开始和结束:

 public void startfloat() {
 for (floatobject floatobject : floats) {
  floatobject.setstatus(floatobject.start);
 }
 }

 public void endfloat() {
 for (floatobject floatobject : floats) {
  floatobject.setstatus(floatobject.end);
 }
 }

使用

使用时非常简单,在layout文件中将floatbackground设置为最底层的视图(其实就是当作一个背景):

 <com.dean.library.floatbackground
 android:id="@+id/float_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <linearlayout
  android:layout_gravity="center"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">

  <button
  android:id="@+id/start"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:text="start" />

  <button
  android:id="@+id/end"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:text="end" />
 </linearlayout>
 </com.dean.library.floatbackground>

在代码中进行如下调用:

final floatbackground floatbackground = (floatbackground) this.findviewbyid(r.id.float_view);

 button start = (button) this.findviewbyid(r.id.start);
 start.setonclicklistener(new view.onclicklistener() {
  @override
  public void onclick(view v) {
  floatbackground.startfloat();
  }
 });

 button end = (button) this.findviewbyid(r.id.end);
 end.setonclicklistener(new view.onclicklistener() {
  @override
  public void onclick(view v) {
  floatbackground.endfloat();
  }
 });

 floatbackground.addfloatview(new floatrect(0.2f, 0.3f, 30, 40));
 floatbackground.addfloatview(new floatbitmap( this, 0.2f, 0.3f, r.drawable.gr_ptn_03));
 floatbackground.addfloatview(new floatcircle( 0.8f, 0.8f));
 floatbackground.addfloatview(new floattext( 0.3f, 0.6f, "e"));
 floatbackground.addfloatview(new floatring( 0.6f, 0.2f, 15 ,20));

浮物”时:floatbackground.addfloatview(new floattext( 0.3f, 0.6f, “e”))
接收的三个参数分别为出生位置在屏幕宽的百分比,长的百分比,和显示的文字。

github

https://github.com/a396901990/floatbackground

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

上一篇:

下一篇: