Android編程實(shí)現(xiàn)簡(jiǎn)易彈幕效果示例【附demo源碼下載】
本文實(shí)例講述了Android編程實(shí)現(xiàn)簡(jiǎn)易彈幕效果。分享給大家供大家參考,具體如下:
首先上效果圖,類似于360檢測(cè)到騷擾電話頁(yè)面:

布局很簡(jiǎn)單,上面是一個(gè)RelativeLayout,下面一個(gè)Button.
功能:
(1)彈幕生成后自動(dòng)從右側(cè)往左側(cè)滾動(dòng)(TranslateAnimation),彈幕消失后立刻被移除。
(2)彈幕位置隨機(jī)出現(xiàn),并且不重復(fù)(防止文字重疊)。
(3)字體大小在一定范圍內(nèi)隨機(jī)改變,字體顏色也可以設(shè)置。
(4)自定義先減速,后加速的Interpolator,彈幕加速進(jìn)入、減速停留、然后加速出去。
1.Activity代碼:
/**
* 簡(jiǎn)易彈幕效果實(shí)現(xiàn)
* Created by admin on 15-6-4.
*/
public class MainActivity extends ActionBarActivity {
private MyHandler handler;
//彈幕內(nèi)容
private TanmuBean tanmuBean;
//放置彈幕內(nèi)容的父組件
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[]{"測(cè)試一下", "彈幕這東西真不好做啊", "總是出現(xiàn)各種問(wèn)題~~", "也不知道都是為什么?麻煩!", "哪位大神可以幫幫我啊?", "I need your help.",
"測(cè)試一下", "彈幕這東西真不好做啊", "總是出現(xiàn)各種問(wèn)題~~", "也不知道都是為什么?麻煩!", "哪位大神可以幫幫我?。?, "I need your help.",
"測(cè)試一下", "彈幕這東西真不好做啊", "總是出現(xiàn)各種問(wèn)題~~", "也不知道都是為什么?麻煩!", "哪位大神可以幫幫我啊?", "I need your help."});
handler = new MyHandler(this);
//開(kāi)始彈幕
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自動(dòng)添加一條彈幕
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();
//計(jì)算本條彈幕的topMargin(隨機(jī)值,但是與屏幕中已有的不重復(fù))
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);
}
//記錄當(dāng)前仍在顯示狀態(tài)的彈幕的位置(避免重復(fù))
private Set<Integer> existMarginValues = new HashSet<>();
private int linesCount;
private int getRandomTopMargin() {
//計(jì)算用于彈幕顯示的空間高度
if (validHeightSpace == 0) {
validHeightSpace = containerVG.getBottom() - containerVG.getTop()
- containerVG.getPaddingTop() - containerVG.getPaddingBottom();
}
//計(jì)算可用的行數(shù)
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.平移動(dòng)畫(huà)生成工具:
public class AnimationHelper {
/**
* 創(chuàng)建平移動(dòng)畫(huà)
*/
public static Animation createTranslateAnim(Context context, int fromX, int toX) {
TranslateAnimation tlAnim = new TranslateAnimation(fromX, toX, 0, 0);
//自動(dòng)計(jì)算時(shí)間
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是用來(lái)獲取屏幕寬高、dp與px之間互轉(zhuǎn)的工具類。
3.自定義的Interpolator,其實(shí)只有一行代碼
public class DecelerateAccelerateInterpolator implements Interpolator {
//input從0~1,返回值也從0~1.返回值的曲線表征速度加減趨勢(shì)
@Override
public float getInterpolation(float input) {
return (float) (Math.tan((input * 2 - 1) / 4 * Math.PI)) / 2.0f + 0.5f;
}
}
4.TanmuBean是一個(gè)實(shí)體類
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;
}
/**
* min textSize, in dp.
*/
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;
}
}
完整實(shí)例代碼點(diǎn)擊此處本站下載。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android視圖View技巧總結(jié)》、《Android開(kāi)發(fā)動(dòng)畫(huà)技巧匯總》、《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android布局layout技巧總結(jié)》、《Android開(kāi)發(fā)入門(mén)與進(jìn)階教程》、《Android資源操作技巧匯總》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android自定義View實(shí)現(xiàn)彈幕效果
- Android雙重SurfaceView實(shí)現(xiàn)彈幕效果
- Android實(shí)現(xiàn)視頻彈幕功能
- Android自制精彩彈幕效果
- Android EasyBarrage實(shí)現(xiàn)輕量級(jí)彈幕效果
- 很棒的Android彈幕效果實(shí)例
- Android 實(shí)現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解及實(shí)例
- Android實(shí)現(xiàn)炫酷的網(wǎng)絡(luò)直播彈幕功能
- Android彈幕框架 黑暗火焰使基本使用方法
- Android仿斗魚(yú)直播的彈幕效果
- Android實(shí)現(xiàn)自定義的彈幕效果
- 實(shí)例解析如何在Android應(yīng)用中實(shí)現(xiàn)彈幕動(dòng)畫(huà)效果
- Android簡(jiǎn)單實(shí)現(xiàn)彈幕效果
相關(guān)文章
Android 媒體開(kāi)發(fā)之MediaPlayer狀態(tài)機(jī)接口方法實(shí)例解析
這篇文章主要介紹了Android 媒體開(kāi)發(fā)之MediaPlayer狀態(tài)機(jī)接口方法實(shí)例解析,需要的朋友可以參考下2017-08-08
Android開(kāi)發(fā)實(shí)現(xiàn)可拖動(dòng)排序的ListView功能【附源碼下載】
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)可拖動(dòng)排序的ListView功能,結(jié)合實(shí)例形式分析了Android列表拖動(dòng)排序原理與相關(guān)操作技巧,并附帶完整源碼供讀者下載參考,需要的朋友可以參考下2017-11-11
Android實(shí)現(xiàn)創(chuàng)意LoadingView動(dòng)畫(huà)效果
這篇文章主要介紹了Android實(shí)現(xiàn)創(chuàng)意LoadingView動(dòng)畫(huà)效果的相關(guān)資料,需要的朋友可以參考下2016-02-02
AndroidHttpClient詳解及調(diào)用示例
本文給大家介紹AndroidHttpClient結(jié)構(gòu)、使用方式及調(diào)用示例詳解,需要的朋友可以參考下2015-10-10
淺談Android ASM自動(dòng)埋點(diǎn)方案實(shí)踐
本篇文章主要介紹了淺談Android ASM自動(dòng)埋點(diǎn)方案實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android程序開(kāi)發(fā)ListView+Json+異步網(wǎng)絡(luò)圖片加載+滾動(dòng)翻頁(yè)的例子(圖片能緩存,圖片不錯(cuò)亂)
這篇文章主要介紹了Android程序開(kāi)發(fā)ListView+Json+異步網(wǎng)絡(luò)圖片加載+滾動(dòng)翻頁(yè)的例子(圖片能緩存,圖片不錯(cuò)亂) 的相關(guān)資料,需要的朋友可以參考下2016-01-01
Android Socket實(shí)現(xiàn)多個(gè)客戶端聊天布局
這篇文章主要為大家詳細(xì)介紹了Android Socket實(shí)現(xiàn)多個(gè)客戶端聊天布局,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
實(shí)例講解Android中ContentProvider組件的使用方法
這篇文章主要介紹了Android中ContentProvider組件的使用方法,包括ContentProvider使用單元測(cè)試的步驟,需要的朋友可以參考下2016-04-04

