1.布局文件:activity_main.xml

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context="com.skg.danmudemo.MainActivity">

android:id="@+id/danmu"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:orientation="horizontal">

android:id="@+id/text"

android:layout_width="0dp"

android:layout_height="50dp"

android:layout_weight="1"/>

android:id="@+id/btn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="发送"/>

2.主类: MainActivity

/**

* @author ClamLaw

* @time 2016/11/26

* @desc MainActivity

*/

public class MainActivity extends AppCompatActivity {

private EditText mText;

private List mList = new ArrayList<>();

private DanMuView mDanMuView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initView();//初始化

initData();

}

private void initData() {

String[] array = getResources().getStringArray(R.array.danmuList);//先获取部分数据

for (int i = 0; i < array.length; i++) {

mList.add(array[i]);

}

mDanMuView.setData(mList);//向弹幕框添加数据

mDanMuView.startDanmu();//开始弹幕

}

//初始化

private void initView() {

mText = (EditText) findViewById(R.id.text);

mDanMuView = (DanMuView) findViewById(R.id.danmu);

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {//发送按钮

@Override

public void onClick(View v) {

//发送评论

String str = mText.getText().toString();

mDanMuView.insertDanmu(str);

}

});

}

}

3.自定义弹幕显示框控件: DanMuView

/**

* @author ClamLaw

* @time 2016/11/26 19:01

* @desc 自定义弹幕的view

*/

public class DanMuView extends RelativeLayout {

private Context mContext;

private View view;

private RelativeLayout mContainerVG;

private List mList;

//父组件的高度

private int validHeightSpace;

private Set existMarginValues = new HashSet<>();

private int lastMarginValue;

ExecutorService executorService = Executors.newFixedThreadPool(1);//线程池

Handler mHandler = new Handler(){

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

switch (msg.what){

case 1:

int index = msg.arg1;

String data = mList.get(index);

showDanmu(data);

break;

}

}

};

public DanMuView(Context context) {

super(context);

}

public DanMuView(Context context, AttributeSet attrs) {

super(context, attrs);

this.mContext = context;

view = LayoutInflater.from(context).inflate(R.layout.danmu_view, null, false);

mContainerVG = (RelativeLayout) view.findViewById(R.id.danmu);

mContainerVG.setBackgroundDrawable(null);

addView(view);

}

/**

* 添加数据到弹幕中

*

* @param list

*/

public void setData(List list) {

this.mList = list;

}

/**

* 用户发送评论弹幕

*

* @param data

*/

public void insertDanmu(String data) {

showDanmu(data);//显示弹幕

mList.add(data);//将弹幕信息添加到集合的第一位

startDanmu();//开始弹幕

}

/**

* 开始弹幕

*/

public void startDanmu() {

existMarginValues.clear();

executorService.execute(new Runnable() {

@Override

public void run() {

for (int i =0 ;i

int size = mList.size();

if (size==0){

break;

}

mHandler.obtainMessage(1,i%size,0).sendToTarget();

SystemClock.sleep(1000);

}

}

});

}

/**

* 显示弹幕

*/

public void showDanmu(String data) {

View view = LayoutInflater.from(mContext).inflate(R.layout.item_danmu, null, false);

final RelativeLayout danmu_container = (RelativeLayout) view.findViewById(R.id.danmu_container);

TextView danmu_text = (TextView) view.findViewById(R.id.danmu_text);

ImageView danmu_img = (ImageView)view.findViewById(R.id.danmu_img);

String str = clipLongTextByChineseCount(data, 12);//评论内容长度限制

danmu_img.setImageResource(R.drawable.deta_shoucz);

danmu_text.setText(str);//设置弹幕

danmu_container.setBackgroundResource(R.drawable.textview_bg);//设置背景

int leftMargin = mContainerVG.getRight() - mContainerVG.getLeft() - mContainerVG.getPaddingLeft();

//计算本条弹幕的topMargin(随机值,但是与屏幕中已有的不重复)

int verticalMargin = getRandomTopMargin();

LayoutParams params = new LayoutParams(

LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

params.addRule(RelativeLayout.ALIGN_PARENT_TOP);//设置节点属性,上边缘

params.topMargin = verticalMargin;

danmu_container.setLayoutParams(params);

//动画

Animation anim = new AnimationHelper().createTranslateAnim(mContext, leftMargin, -getScreenWidth((Activity) mContext));

//动画监听

anim.setAnimationListener(new Animation.AnimationListener() {

@Override

public void onAnimationStart(Animation animation) {

}

@Override

public void onAnimationEnd(Animation animation) {

//动画结束时移除控件

mContainerVG.removeView(danmu_container);

}

@Override

public void onAnimationRepeat(Animation animation) {

}

});

danmu_container.startAnimation(anim);//开始动画

mContainerVG.addView(danmu_container);

}

private int getRandomTopMargin() {

if (validHeightSpace == 0) {

validHeightSpace = mContainerVG.getBottom() - mContainerVG.getTop()

- mContainerVG.getPaddingBottom() - mContainerVG.getTop();

}

if (existMarginValues.size() == 3) {

existMarginValues.clear();

while (true) {

int randomIndex = (int) (Math.random() * 5);

int marginValue = randomIndex * (validHeightSpace / 5);

if (lastMarginValue != marginValue) {

existMarginValues.add(marginValue);

return marginValue;

}

}

} else {

//检查重叠

while (true) {

int randomIndex = (int) (Math.random() * 5);

int marginValue = randomIndex * (validHeightSpace / 5);

if (!existMarginValues.contains(marginValue)) {

existMarginValues.add(marginValue);

if (existMarginValues.size() == 3) {

lastMarginValue = marginValue;

}

return marginValue;

}

}

}

}

/**

* 获取屏幕的宽度

* @param context

* @return

*/

private int getScreenWidth(Context context) {

WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

return manager.getDefaultDisplay().getWidth();

}

/**

* 评论的长度限制

* @param str

* @param count

* @return

*/

public static String clipLongTextByChineseCount(String str, int count) {

if (str != null) {

final String encoding = "GBK";

try {

byte[] b = str.getBytes(encoding);

if (b.length >= (count + 1) * 2) {

int end = count * 2;

String result = new String(b, 0, end, encoding);

if (str.indexOf(result) == -1) {

return new String(b, 0, end - 1, encoding) + "...";

}

return result + "...";

}

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

return str;

}

//动画

public class AnimationHelper{

public AnimationHelper() {

}

//fromX 开始的位置 ,toX结束的位置

public Animation createTranslateAnim(Context context, int fromX, int toX){

TranslateAnimation translateAnimation = new TranslateAnimation(fromX, toX, 0, 0);

int width = getScreenWidth((Activity)context);//获取屏幕的宽度

//自动计算时间

long duration = (long) (Math.abs(toX - fromX) * 1.0f / width * 6000);

translateAnimation.setDuration(duration);//动画时间

// translateAnimation.setInterpolator(new DecelerateAccelerateInterpolator());//动画速率

translateAnimation.setFillAfter(true);//终止时停留最后一帧

return translateAnimation;

}

}

public class DecelerateAccelerateInterpolator implements Interpolator {

@Override

public float getInterpolation(float input) {

return (float) (Math.tan((input * 2 - 1) / 4 * Math.PI)) / 2.0f + 0.5f;

}

}

}

4.弹幕容器布局:danmu_view.xml

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/danmu"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

5.弹幕子控件布局:item_danmu.xml

android:id="@+id/danmu_container"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/danmu_img"

android:layout_width="25dp"

android:layout_height="25dp"

android:layout_marginLeft="1px"

android:layout_marginTop="1px"/>

android:id="@+id/danmu_text"

android:textColor="@android:color/white"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:singleLine="true"

android:layout_marginLeft="25dp"

android:text="123123"

android:textSize="20dp"/>

本Demo的源码下载链接:DanMuDemo.

android 弹幕礼物,Android的简易弹幕相关推荐

  1. android动画实例源码,Android编程实现简易弹幕效果示例【附demo源码下载】

    本文实例讲述了Android编程实现简易弹幕效果.分享给大家供大家参考,具体如下: 首先上效果图,类似于360检测到骚扰电话页面: 布局很简单,上面是一个RelativeLayout,下面一个Butt ...

  2. Android集成bilibili播放器以及弹幕

    考虑到开发直播和视频播放的必要性,网上了解到b站开源播放器(https://github.com/bilibili/ijkplayer)好用,集成下试试. 运行后发现b站原生的只能播放没有其他选项,考 ...

  3. android 图文弹幕重叠,Android双重SurfaceView实现弹幕效果

    本文实例为大家分享了Android双重SurfaceView实现弹幕效果的具体代码,供大家参考,具体内容如下 页面布局 首先是XML的layout布局,这里的总的父布局是一个FrameLayout用于 ...

  4. android-实现一个简单的视频弹幕,Android已死

    android:id="@+id/edit_text" android:layout_width="0dp" android:layout_height=&qu ...

  5. android+弹幕实现,Android弹幕实现:基于B站弹幕开源系统(1)

     Android弹幕实现:基于B站弹幕开源系统(1) 如今的视频播放,流行在视频上飘弹幕.这里面做的相对比较成熟.稳定.使用量较多的弹幕系统,当推B站的弹幕系统,B站的弹幕系统已经作为开源项目在g ...

  6. obs弹幕助手android版,OBS Studio 使用全屏弹幕教程

    亲爱的葫芦丝们,大家好! (•̀ᴗ•́)و ̑̑ 今天给大家介绍 -- OBS Studio 使用全屏弹幕教程,让萌新们远离困扰,小白们远离烦恼~ 闲话不多说,小编我开始讲解: (。・ω・)ノ゙ 首先 ...

  7. android 弹幕动画,Android自制精彩弹幕效果

    好久没有写过文章,最近发现直播特别的火,很多app都集成了直播的功能,发现有些直播是带有弹幕的,效果还不错,今天心血来潮,特地写了篇制作弹幕的文章. 今天要实现的效果如下: 1.弹幕垂直方向固定 2. ...

  8. android动画送礼物,Android仿直播类app赠送礼物功能

    直播界面 实现的是播放本地的视频文件: /** * 直播界面,用于对接直播功能 */ public class LiveFrag extends Fragment { private ImageVie ...

  9. android计算器弹窗,android实现简易计算器

    本文实例为大家分享了android实现简易计算器展示的具体代码,供大家参考,具体内容如下 效果图: 一.如图,首先布局计算器主页显示 activity_main.xml xmlns:tools=&qu ...

  10. android动画送礼物,Android开发仿映客送礼物效果

    这里写链接内容仿映客送小礼物的特效,顺便复习一下属性动画,话不多说先看效果图. 需求分析 可以看到整个动画有几部分组成,那我们就把每个部分拆分出来各个击破. 1.要显示那些内容以及内容间的位置关系? ...

最新文章

  1. Linux命令:tar命令批量解压方法总结
  2. 什么是ownership?
  3. 教程视图Android教程(十三)-- Activity间的切换
  4. 6 大技巧帮助初学者快速掌握 JavaScript!
  5. vsftp不同帐号的目录和权限
  6. ansible软件模块参数
  7. .net core mvc中使用ef
  8. 统筹高效利用时间——《小强升职记(升级版):时间管理故事书》读后感
  9. 定时网页截图php,浏览器实现网页定时自动截图
  10. 洛谷P1725 琪露诺(单调队列优化dp)
  11. Anroid 7.0 Direct Boot研究
  12. 使用注册表编辑win10鼠标右键菜单,详细解释(右键文件夹、文件以及右键空白区域下三种情况)
  13. 氧分呗:新时代定义科技的美好 自主创新踏上新征程
  14. 乌镇 · 第四节世界互联网大会 · 马云
  15. python dingding --- 钉钉机器人API
  16. JAVA学习笔记 15 - 函数式接口、Lambda表达式和方法引用
  17. 解决Windows d3dx9_30.dll找不到问题
  18. python语言数值操作符_python数据类型和运算符
  19. 【原创】火星寻路程序
  20. 基于SSM+JSP+MYSQL+H-UI 实现的火锅店点餐系统

热门文章

  1. Julia: Array元素过滤、元素替代、元素删除等酸爽操作
  2. “阿里云核心竞争力”峰会首日中奖小伙伴名单公布!机械键盘等豪礼下午继续放出!...
  3. 机器学习笔记(二十三):算法精准率、召回率
  4. 申通上云?技术详解! | 凌云时刻
  5. 在安全防火墙内通过 WebHook 触发构建
  6. Linux基金会宣布行业进一步支持Akraino Edge Stack
  7. 【房价预测】基于matlab遗传算法优化BP神经网络房价预测【含Matlab源码 592期】
  8. 【语音编码】基于matlab ADPCM编解码【含Matlab源码 553期】
  9. 【路径规划】基于matlab蚁群和粒子群算法双机器人协调路径规划【含Matlab源码 045期】
  10. 端到端车道线检测_弱监督对象检测-端到端培训管道