一、效果图

先来看看效果图吧~~

二、实现原理方案

1、自定义ViewGroup-XCDanmuView,继承RelativeLayout来实现,当然也可以继承其他三大布局类哈

2、初始化若干个TextView(弹幕的item View,这里以TextView为例,当然也可以其他了~),然后通过addView添加到自定义View中

3、通过addView添加到XCDanmuView中,位置在坐标,为了实现 从屏幕外移动进来的效果

我们还需要修改添加进来TextView的位置,以从右向左移动方向来说,addView后必须将该TextView的位置设置到右边的屏幕外

这样我们采用的方法,是在onLayout()方法中对childView进行layout重新布局设置位置

4、随机冲左侧或右侧出来弹幕itemView,移动采用属性动画来实现平移,从屏幕的一端移动到另一端,当动画结束后,就将

该child从XCDanmuView中remove掉。并重新new一个弹幕itemView,并addView到XCDanmuView中,并开始动画移动

5、本自定义弹幕View支持从左到右和从右到左两个方向,支持自定义设置屏幕弹幕最多显示个数。

三、自定义弹幕效果XCDanmuView的具体实现

1、初始化需要用到的数据变量

private int mWidth;

private int mScreenWidth;

private ListmChildList;

private boolean mIsWorking = false;

private Context mContext;

private int mMaxShowNum = 15;

private int mRowNum = 4;

private int[] mSpeeds = {

3000,4000,5000,6000

};

private int mDelayDuration = 500;

private int[] mBgResIds = {

R.drawable.bg_danmu0,

R.drawable.bg_danmu1,

R.drawable.bg_danmu2,

R.drawable.bg_danmu3

};

private int[] mRowPos = {

150,140,160,150

};

private Random mRandom;

private String[] mStrContents;

public static enum XCDirection{

FROM_RIGHT_TO_LEFT,

FORM_LEFT_TO_RIGHT

}

public enum XCAction{

SHOW,HIDE

}

private XCDirection mDirection = XCDirection.FROM_RIGHT_TO_LEFT;

private void init() {

mScreenWidth = getScreenWidth();

mChildList = new ArrayList<>();

mRandom = new Random();

}

2、初始化若干个弹幕item view

public void initDanmuItemViews(String[] strContents){

mStrContents = strContents;

for(int i = 0; i < mMaxShowNum; i ++){

int index = mRandom.nextInt(100) % strContents.length;

createDanmuView(i,strContents[index],false);

}

}

3、创建弹幕item view 并addView到XCDanmuView中

public void createDanmuView(int index,String content,boolean reset){

final TextView textView = new TextView(mContext);

textView.setTextColor(Color.WHITE);

int r = mRandom.nextInt(100) % mRowNum;

textView.setBackgroundResource(mBgResIds[r]);

textView.setText(content +"_"+ (index+1));

RelativeLayout.LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,

RelativeLayout.LayoutParams.WRAP_CONTENT);

int row = mRandom.nextInt(100) % mRowNum;

while(row == lastRow){

row = mRandom.nextInt(100)% mRowNum;

}

int pos = mRandom.nextInt(100)% mRowNum;

lp.topMargin = row * mRowPos[pos];

lastRow = row;

textView.setLayoutParams(lp);

textView.setPadding(40, 2, 40, 2);

this.addView(textView);

if(reset){

mChildList.set(index,textView);

}else{

mChildList.add(index,textView);

}

textView.setClickable(true);

textView.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View view) {

Toast toast = Toast.makeText(mContext, textView.getText(), Toast.LENGTH_SHORT);

toast.setGravity(Gravity.TOP,0,50);

toast.show();

}

});

}

4、重新设置childView的初始位置到屏幕之外

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

super.onLayout(changed, l, t, r, b);

int childCount = this.getChildCount();

for(int i=0;i

5、弹幕item view的移动效果

private Handler mHandler = new Handler() {

@Override

public void handleMessage(final Message msg) {

super.handleMessage(msg);

final int pos = msg.what;

ViewPropertyAnimator animator;

if(mDirection == XCDirection.FROM_RIGHT_TO_LEFT){

animator = mChildList.get(msg.what).animate()

.translationXBy(-(mScreenWidth + mChildList.get(msg.what).getWidth()));

}else{

animator = mChildList.get(msg.what).animate()

.translationXBy(mScreenWidth + mChildList.get(msg.what).getWidth());

}

Random random = new Random(System.currentTimeMillis());

int index = random.nextInt(100) % mSpeeds.length;

animator.setDuration(mSpeeds[index]);

animator.setInterpolator(new LinearInterpolator());

animator.setListener(new Animator.AnimatorListener() {

@Override

public void onAnimationStart(Animator animator) {

}

@Override

public void onAnimationEnd(Animator animator) {

XCDanmuView.this.removeView(mChildList.get(pos));

int index = mRandom.nextInt(100) % mStrContents.length;

createDanmuView(pos, mStrContents[index], true);

mHandler.sendEmptyMessageDelayed(pos, mDelayDuration);

Log.v("czm", "size=" + mChildList.size());

}

@Override

public void onAnimationCancel(Animator animator) {

}

@Override

public void onAnimationRepeat(Animator animator) {

}

});

animator.start();

}

};

6、开启弹幕效果和关闭弹幕效果以及对于的动画效果

boolean isFirst = true;

public void start(){

switchAnimation(XCAction.SHOW);

if(isFirst){

for(int i =0;i< mChildList.size();i++){

mHandler.sendEmptyMessageDelayed(i,i * mDelayDuration);

}

isFirst = false;

}

mIsWorking = true;

}

public void hide(){

switchAnimation(XCAction.HIDE);

mIsWorking =false;

}

public void stop(){

this.setVisibility(View.GONE);

for(int i =0;i< mChildList.size();i++){

mChildList.get(i).clearAnimation();

mHandler.removeMessages(i);

}

mIsWorking =false;

}

private void switchAnimation(final XCAction action){

AlphaAnimation animation;

if(action == XCAction.HIDE){

animation = new AlphaAnimation(1.0f,0.0f);

animation.setDuration(400);

}else{

animation = new AlphaAnimation(0.0f,1.0f);

animation.setDuration(1000);

}

XCDanmuView.this.startAnimation(animation);

animation.setAnimationListener(new Animation.AnimationListener() {

@Override

public void onAnimationStart(Animation animation) {

}

@Override

public void onAnimationEnd(Animation animation) {

if(action == XCAction.HIDE){

XCDanmuView.this.setVisibility(View.GONE);

}else{

XCDanmuView.this.setVisibility(View.VISIBLE);

}

}

@Override

public void onAnimationRepeat(Animation animation) {

}

});

}

四、如何使用该自定义侧滑View控件

使用该自定义View非常简单,控件默认效果从右向左,如果需要修改方向为从左到右,只需设置下方向即可

public class MainActivity extends Activity {

private XCDanmuView mDanmuView;

private ListmViewList;

private String[] mStrItems = {

"搜狗","百度",

"腾讯","360",

"阿里巴巴","搜狐",

"网易","新浪",

"搜狗-上网从搜狗开始","百度一下,你就知道",

"必应搜索-有求必应","好搜-用好搜,特顺手",

"Android-谷歌","IOS-苹果",

"Windows-微软","Linux"

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initDanmuView();

initListener();

}

private void initListener() {

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

if (mDanmuView.isWorking()) {

mDanmuView.hide();

((Button) view).setText("开启弹幕");

} else {

mDanmuView.start();

((Button) view).setText("关闭弹幕");

}

}

});

}

private void initDanmuView() {

mDanmuView = (XCDanmuView)findViewById(R.id.danmu);

mDanmuView.initDanmuItemViews(mStrItems);

}

}

五、总结

以上就是在Android中实现自定义弹幕效果的全部内容个,希望本文的内容对大家开发Android的时候能有所帮助。如果有疑问可以留言交流。

android实现弹幕功能,Android实现自定义的弹幕效果相关推荐

  1. android的UDC功能,Android实现搜索历史功能

    本文实例为大家分享了Android实现搜索历史的具体代码,供大家参考,具体内容如下 SharedPreferences实现本地搜索历史功能,覆盖搜索重复的文本,可清空 1. 判断搜索内容是否含表情,不 ...

  2. android sharesdk分享功能,Android ShareSDK快速实现分享功能

    第一步 :获取ShareSDK 为了集成ShareSDK,您首先需要到ShareSDK官方网站注册并且创建应用,获得ShareSDK的Appkey,然后到SDK的下载页面下载SDK的压缩包,解压以后可 ...

  3. android相册幻灯片功能,Android实现幻灯片式图片浏览器

    我们来实现一个幻灯片式图片浏览器: 最下面一个画廊视图,选中画廊中的图片,会在上面的ImageSwitcher控件中显示大图. 效果图如图 实现方法: 在布局文件中添加图片切换控件ImageSwitc ...

  4. android放微信@功能,Android仿微信语音消息的录制和播放功能

    一.简述 效果: 实现功能: 长按Button时改变Button显示文字,弹出Dialog(动态更新音量),动态生成录音文件,开始录音: 监听手指动作,规定区域.录音状态下手指划出规定区域取消录音,删 ...

  5. android 本地提醒功能,android中的本地定时推送到通知栏

    一.使用系统定义的Notification 以下是使用示例代码: import android.app.Notification; import android.app.NotificationMan ...

  6. android 语音发送功能,Android仿微信、录制音频并发送功能

    MyRecorder(仿微信,录制音频并发送功能) ①布局实现(activity_main.xml)布局采用线性布局,上面使用的一个ListView,下面使用的是一个自定义的Button(会在下面进行 ...

  7. android app 退出功能,Android 应用技巧: 手把手教你 优雅实现 “一键退出 App”

    前言 在 Android开发中,会经常存在 "一键退出App" 的需求 但市面上流传着 太多不可用的"一键退出App"功能实现 本文将全面总结"一键退 ...

  8. android 微信评论功能,Android仿微信朋友圈点赞和评论功能

    最近在做朋友圈的项目,所以写一个Android仿朋友圈点赞和评论功能Demo,代码就是简单实现了一下功能,没有做优化,凑合看. 图文排列是用的RecyclerView实现的,弹窗效果是用的自定义的Po ...

  9. android播放mp3功能,Android Studio实现简单音乐播放功能的示例代码

    项目要求 基于Broadcast,BroadcastReceiver等与广播相关的知识实现简单的音乐播放功能,包括音乐的播放.暂停.切换.进度选择.音量调整. 设计效果 (进度条时间刷新功能还没有实现 ...

  10. android edittext清除功能,Android:带一键清除功能的EditText

    作为一个前端应用开发者,下面这样的场景可以说是屡见不鲜了? 20181218135459.png 当然了,本文所要讲的重点不是如何做一个登录页面,而是输入框后面的那个清除按钮.你可能会说了,这有什么好 ...

最新文章

  1. 安装Windows Vista
  2. tf2.0环境下“module ‘tensorflow‘ has no attribute ‘log‘”的解决办法
  3. Linux源代码软件安装,Linux软件安装:源代码与软件安装
  4. java comparable接口_Java面试题之Java集合篇三
  5. Silverlight4中用net.tcp双工方式进行通信
  6. pycharm中的console退出问题以及console和pycharm各自运行结果不一样的问题
  7. linuxpip安装python包_Windows+Linux安装Python包管理工具pip
  8. 【转】Windows Server 2012 R2 双网卡绑定
  9. LeetCode 759. 员工空闲时间(排序)
  10. 【51NOD】1006 最长公共子序列Lcs(动态规划)
  11. 结构与表现分离的思想
  12. android状态栏华为,状态栏设置华为版
  13. 默认主页被篡改为360导航如何解决!
  14. Struts2概述及与Struts1的对比
  15. 推荐一本 Bulma 的书《使用Bulma来创建用户界面》
  16. 洛谷 P1160 队列安排
  17. 两个人聪明人的空城——《司马懿之虎啸龙吟》
  18. Pandoc+TeXLive实现Markdown转PDF
  19. 什么是手机证书和签名干什么用的
  20. (转)逃脱者可获生机(中)

热门文章

  1. 最具有催眠功能的网站
  2. 与太阳神对话——j2se之旅
  3. 【历史上的今天】11 月 15 日:全球首款商用微处理器;微软进军游戏界;ICQ 诞生
  4. Neuromation新研究:利用卷积神经网络进行儿童骨龄评估
  5. 10岁男孩开灯睡觉骨龄发育慢4年上热搜,开灯睡觉都有什么危害?
  6. SPI 测试程序sja1105
  7. 微型计算机组装的目的,微机组装实训报告范文
  8. android4以下的音乐播放器,动静(音乐播放器)
  9. 安装了VCam后,VideoCapture 出问题,FileStorage fs(X.yml, FileStorage::READ)报错
  10. 冰封王座1.17版新英雄研究之地精炼金术士