ANDROID-漂浮背景效果

效果图:

GIF动图效果不是很好,实际效果很是平滑very smooth,并且添加不一样的图形能够组成各类效果,目前已经用在咱们项目的注册界面~java

这里写图片描述

原理:

实现原理很简单,每个悬浮的“小物体”就是一个自定义View,这些小的自定义View都盛放在一个自定义的ViewGroup中。而后全部的视图都放在这个ViewGroup之上,这样就至关于作一个可动的背景。android

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

详解:

FloatObject

悬浮的物体,继承自View,须要重写onDraw方法,主要做用就是来画出本身,并进行随机曲线运动github

任何须要画出的对象都须要继承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); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

随机曲线:

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

我以前想过使用布朗运动,可是在网上找了很久也没找到一个好用的算法数据结构

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

控制运动的代码以下:ide

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); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

关于赛贝尔曲线运动的算法都是复用以前写的一篇文章ANDROID模拟火花粒子的滑动喷射效果,若是你们有兴趣能够看看。post

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); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

绘制:

@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(); // 控制帧数 } };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

开始和结束:

public void startFloat() { for (FloatObject floatObject : floats) { floatObject.setStatus(FloatObject.START); } } public void endFloat() { for (FloatObject floatObject : floats) { floatObject.setStatus(FloatObject.END); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

使用

使用时很是简单,在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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在代码中进行以下调用:

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));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

好比在添加文字“漂浮物”时:floatBackground.addFloatView(new FloatText( 0.3f, 0.6f, “E”))
接收的三个参数分别为出生位置在屏幕宽的百分比,长的百分比,和显示的文字。

Github

相关文章
相关标签/搜索