本文实例讲述了Android编程实现简易弹幕效果。分享给大家供大家参考,具体如下:
首先上效果图,类似于360检测到骚扰电话页面:
布局很简单,上面是一个RelativeLayout,下面一个Button.
功能:
(1)弹幕生成后自动从右侧往左侧滚动(TranslateAnimation),弹幕消失后立刻被移除。
(2)弹幕位置随机出现,并且不重复(防止文字重叠)。
(3)字体大小在一定范围内随机改变,字体颜色也可以设置。
(4)自定义先减速,后加速的Interpolator,弹幕加速进入、减速停留、然后加速出去。
1.Activity代码:
public class MainActivity extends ActionBarActivity {
private MyHandler handler;
//弹幕内容
private TanmuBean tanmuBean;
//放置弹幕内容的父组件
private RelativeLayout containerVG;
//父组件的高度
private int validHeightSpace;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
containerVG = (RelativeLayout) findViewById(R.id.tanmu_container);
tanmuBean = new TanmuBean();
tanmuBean.setItems(new String[]{"测试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神可以帮帮我啊?", "I need your help.",
"测试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神可以帮帮我啊?", "I need your help.",
"测试一下", "弹幕这东西真不好做啊", "总是出现各种问题~~", "也不知道都是为什么?麻烦!", "哪位大神可以帮帮我啊?", "I need your help."});
handler = new MyHandler(this);
//开始弹幕
View startTanmuView = findViewById(R.id.startTanmu);
startTanmuView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (containerVG.getChildCount() > 0) {
return;
}
existMarginValues.clear();
new Thread(new CreateTanmuThread()).start();
}
});
}
//每2s自动添加一条弹幕
private class CreateTanmuThread implements Runnable {
@Override
public void run() {
int N = tanmuBean.getItems().length;
for (int i = 0; i < N; i++) {
handler.obtainMessage(1, i, 0).sendToTarget();
SystemClock.sleep(2000);
}
}
}
//需要在主线城中添加组件
private static class MyHandler extends Handler {
private WeakReference<MainActivity> ref;
MyHandler(MainActivity ac) {
ref = new WeakReference<>(ac);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
MainActivity ac = ref.get();
if (ac != null && ac.tanmuBean != null) {
int index = msg.arg1;
String content = ac.tanmuBean.getItems()[index];
float textSize = (float) (ac.tanmuBean.getMinTextSize() * (1 + Math.random() * ac.tanmuBean.getRange()));
int textColor = ac.tanmuBean.getColor();
ac.showTanmu(content, textSize, textColor);
}
}
}
}
private void showTanmu(String content, float textSize, int textColor) {
final TextView textView = new TextView(this);
textView.setTextSize(textSize);
textView.setText(content);
// textView.setSingleLine();
textView.setTextColor(textColor);
int leftMargin = containerVG.getRight() - containerVG.getLeft() - containerVG.getPaddingLeft();
//计算本条弹幕的topMargin(随机值,但是与屏幕中已有的不重复)
int verticalMargin = getRandomTopMargin();
textView.setTag(verticalMargin);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.topMargin = verticalMargin;
textView.setLayoutParams(params);
Animation anim = AnimationHelper.createTranslateAnim(this, leftMargin, -ScreenUtils.getScreenW(this));
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//移除该组件
containerVG.removeView(textView);
//移除占位
int verticalMargin = (int) textView.getTag();
existMarginValues.remove(verticalMargin);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
textView.startAnimation(anim);
containerVG.addView(textView);
}
//记录当前仍在显示状态的弹幕的位置(避免重复)
private Set<Integer> existMarginValues = new HashSet<>();
private int linesCount;
private int getRandomTopMargin() {
//计算用于弹幕显示的空间高度
if (validHeightSpace == 0) {
validHeightSpace = containerVG.getBottom() - containerVG.getTop()
- containerVG.getPaddingTop() - containerVG.getPaddingBottom();
}
//计算可用的行数
if (linesCount == 0) {
linesCount = validHeightSpace / ScreenUtils.dp2px(this, tanmuBean.getMinTextSize() * (1 + tanmuBean.getRange()));
if (linesCount == 0) {
throw new RuntimeException("Not enough space to show text.");
}
}
//检查重叠
while (true) {
int randomIndex = (int) (Math.random() * linesCount);
int marginValue = randomIndex * (validHeightSpace / linesCount);
if (!existMarginValues.contains(marginValue)) {
existMarginValues.add(marginValue);
return marginValue;
}
}
}
}
2.平移动画生成工具:
public class AnimationHelper {
public static Animation createTranslateAnim(Context context, int fromX, int toX) {
TranslateAnimation tlAnim = new TranslateAnimation(fromX, toX, 0, 0);
//自动计算时间
long duration = (long) (Math.abs(toX - fromX) * 1.0f / ScreenUtils.getScreenW(context) * 4000);
tlAnim.setDuration(duration);
tlAnim.setInterpolator(new DecelerateAccelerateInterpolator());
tlAnim.setFillAfter(true);
return tlAnim;
}
}
ScreenUtils是用来获取屏幕宽高、dp与px之间互转的工具类。
3.自定义的Interpolator,其实只有一行代码
public class DecelerateAccelerateInterpolator implements Interpolator {
//input从0~1,返回值也从0~1.返回值的曲线表征速度加减趋势
@Override
public float getInterpolation(float input) {
return (float) (Math.tan((input * 2 - 1) / 4 * Math.PI)) / 2.0f + 0.5f;
}
}
4.TanmuBean是一个实体类
public class TanmuBean {
private String[] items;
private int color;
private int minTextSize;
private float range;
public TanmuBean() {
//init default value
color = Color.parseColor("#eeeeee");
minTextSize = 16;
range = 0.5f;
}
public String[] getItems() {
return items;
}
public void setItems(String[] items) {
this.items = items;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getMinTextSize() {
return minTextSize;
}
public void setMinTextSize(int minTextSize) {
this.minTextSize = minTextSize;
}
public float getRange() {
return range;
}
public void setRange(float range) {
this.range = range;
}
}
完整实例代码点击此处本站下载。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android视图View技巧总结》、《Android开发动画技巧汇总》、《Android编程之activity操作技巧总结》、《Android布局layout技巧总结》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。
您可能感兴趣的文章:Android自定义View实现弹幕效果Android双重SurfaceView实现弹幕效果Android实现视频弹幕功能Android自制精彩弹幕效果Android EasyBarrage实现轻量级弹幕效果很棒的Android弹幕效果实例Android 实现仿网络直播弹幕功能详解及实例Android实现炫酷的网络直播弹幕功能Android弹幕框架 黑暗火焰使基本使用方法Android仿斗鱼直播的弹幕效果Android实现自定义的弹幕效果实例解析如何在Android应用中实现弹幕动画效果Android简单实现弹幕效果