临文乍了了,彻卷兀若无。这篇文章主要讲述ANDROID-漂浮背景效果相关的知识,希望能为你提供帮助。
转载请注明本文出自大苞米的博客(
http://blog.csdn.net/a396901990)
,
谢谢支持!
效果图:
GIF动图效果不是很好,
实际效果非常平滑very smooth,
而且添加不同的图形可以组成各种效果,
目前已经用在我们项目的注册界面~
文章图片
原理:
实现原理很简单, 每一个悬浮的“小物体”就是一个自定义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
【ANDROID-漂浮背景效果】https://github.com/a396901990/FloatBackground
推荐阅读
- Android Gradle插件(plugin)版本(version)与GradleSDK Build Tools版本关系
- React Native在Android平台运行gif的解决方法
- 直播技术总结ijkplayer的编译到Android平台并测试解码库
- PHP SplDoublyLinkedList offsetUnset()函数用法示例
- 文件管理器的作用是什么()
- find_elements_by_link_text()驱动程序方法– Selenium Python
- GOCC18(2020年Google在线编码挑战赛-新毕业生(印度))
- 算法题(查找多数元素|S3(位魔术))
- 8051和AVR之间有哪些区别()