Android实现自定义的弹幕效果
一、效果图
先来看看效果图吧~~
二、实现原理方案
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 list<view> mchildlist; 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<childcount;i++){ view view = getchildat(i); relativelayout.layoutparams lp = (layoutparams) view.getlayoutparams(); if(lp.leftmargin <= 0){ if(mdirection == xcdirection.form_left_to_right){ view.layout(-view.getmeasuredwidth(), lp.topmargin, 0,lp.topmargin + view.getmeasuredheight()); }else{ view.layout(mscreenwidth,lp.topmargin,mscreenwidth+view.getmeasuredwidth(), lp.topmargin+view.getmeasuredheight()); } }else{ continue; } } }
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 list<view> mviewlist; 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的时候能有所帮助。如果有疑问可以留言交流。