Android bullet screen frame dark flame make Basic use Method _android

Source: Internet
Author: User
Tags prepare tagname

Today I'm going to share the learning experience of the Android Bullet Screen Framework (danmakuflamemaster) by Bilibili Open source.

I am the entire framework in the form of model into the project, so more convenient to observe the source code. can also be injected in a way that depends.

dependencies { 
compile ' com.github.ctiao:danmakuflamemaster:0.5.3 ' 
}

Let me just put in a picture of the effect I'm going to make:

Page analysis

From the figure above, the entire UI is divided into three layers. The bottom is the video layer, the middle is the bomb screen layer, the top layer is the control layer. Now the mainstream video streaming software in the market are mostly such layered, different is a live class, there may be more than one layer of interaction, display attendance information, gift information and so on.
Since it is layered, I will directly use the Framelayout frame layout to achieve. Post my layout file:

<framelayout xmlns:android= "http://schemas.android.com/apk/res/android" 
android:layout_width= "Match_ Parent " 
android:layout_height=" match_parent "> 
<videoview 
android:id=" @+id/vv_video 
" Android:layout_width= "Match_parent" 
android:layout_height= "match_parent"/> 
< Master.flame.danmaku.ui.widget.DanmakuView 
android:id= "@+id/sv_danmaku" 
android:layout_width= "Match_ Parent " 
android:layout_height=" match_parent "/> 
<include android:id=" @+id/media_controller " 
android:layout_width= "match_parent" 
android:layout_height= "fill_parent" 
layout= "@layout/media_ Controller "/> 
</FrameLayout>

Layout of the control layer:

<framelayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "Match_parent" android:layout_height= "Match_parent" > <linearlayout android:gravity= "center_vertical" android:layout_width= "Match_parent" android:layout_height= "wrap_content" android:layout_gravity= "Bottom" "android:background=" #8acc22dd "> <button android:layout_weight=" 1 "android:id=" @+id/rotate "android:layout_width=" 0DP "Android:layout_heigh t= "Wrap_content" android:text= "@string/rotate"/> <button android:layout_width= "0DP" android:layout_weight= "1 "Android:id=" @+id/btn_hide "android:layout_height=" wrap_content "android:text=" @string/hide_danmaku "/> < Button android:id= "@+id/btn_show" android:layout_width= "0DP" android:layout_weight= "1" android:layout_height= "wrap _content "android:text=" @string/show_danmaku "/> <button android:id=" @+id/btn_pause "android:layout_width=" 0DP "android:layout_weight=" 1 "android:layout_height=" Wrap_cOntent "android:text=" @string/pause_danmaku "/> <button android:id=" @+id/btn_resume "android:layout_width=" 
0DP "android:layout_weight=" 1 "android:layout_height=" wrap_content "android:text=" @string/resume_danmaku "/> <button android:id= "@+id/btn_send" android:layout_width= "0DP" android:layout_weight= "1" android:layout_height= " Wrap_content "android:text=" @string/send_danmaku/> <button android:id= "@+id/btn_send_image_text" Android: Layout_width= "0DP" android:layout_weight= "1" android:layout_height= "wrap_content" android:text= "@string/send_ Danmaku_image_text "/> <button android:id=" @+id/btn_send_danmakus "android:layout_width=" 0DP "Android:layout_ 
weight= "1" android:layout_height= "wrap_content" android:text= "@string/send_danmakus"/> </LinearLayout> </FrameLayout>

Finish writing the layout, first write an initialization method:

Sets the maximum number of rows hashmap<integer,integer> Maxlinespair = new hashmap<> (); Maxlinespair.put (basedanmaku.type_scroll_rl,5)//scroll screen maximum display 5 line//set whether to prohibit overlapping hashmap<integer, boolean> 
Overlappingenablepair = new hashmap<> (); 
Overlappingenablepair.put (BASEDANMAKU.TYPE_SCROLL_RL, true); 
Overlappingenablepair.put (Basedanmaku.type_fix_top, true); Mdanmakucontext = Danmakucontext.create ()//initialization context Mdanmakucontext.setdanmakustyle (Idisplayer.danmaku_style_ 
stroken,3)//Set the type of mdanmakucontext.setduplicatemergingenabled (false),//Set whether to merge repeated barrage 
Mdanmakucontext.setscrollspeedfactor (1.2f); Set the rolling speed of the projectile screen mdanmakucontext.setscaletextsize (1.2f);//Set the size of the bounce screen font Mdanmakucontext.setcachestuffer (New Spannedcachestuffer (), mcachestufferadapter);//Set Cache draw Filler 
Use Spannedcachestuffer mdanmakucontext.setmaximumlines (Maxlinespair) for graphics and text mix;//Set maximum number of rows Mdanmakucontext.preventoverlapping (Overlappingenablepair); Set whether to prohibit overlapping mparser = Createparser (This.getresources (). Openrawresource (r.raw.comments))//Loading barrage resource file Mdvdanmaku. Prepare (Mparser, mdanmakucontext); 
Mdvdanmaku.showfps (TRUE); Mdvdanmaku.enabledanmakudrawingcache (TRUE);

Then paste the implementation of the drawing filler, mainly to achieve the image and text flow together the effect

Private Spannablestringbuilder createspannable (drawable drawable) { 
String text = "Bitmap"; 
Spannablestringbuilder Spannablestringbuilder = new Spannablestringbuilder (text); 
Imagespan span = new Imagespan (drawable); 
Spannablestringbuilder.setspan (span, 0, text.length (), spannable.span_inclusive_exclusive); 
Spannablestringbuilder.append ("Graphic mixed Row"); 
Spannablestringbuilder.setspan (New Backgroundcolorspan ("#8A2233B1")), 0, Spannablestringbuilder.length (), spannable.span_inclusive_inclusive); 
return spannablestringbuilder; 
}

Under the Basedanmaku class, the basic motion forms of the projectile screen are defined: TYPE_SCROLL_RL, TYPE_SCROLL_LR, Type_fix_top, Type_fix_bottom and type_special. That is, from right to left out, left to right out (reverse barrage), top of the screen, the bottom of the barrage and high-level barrage. (in addition to the script barrage)
When initializing, it is necessary to pass in a specific Danmukucontext context to initialize some settings through the context. Bomb screen resources are stored in the XML file, the approximate format is as follows:
.

<i> 
<chatserver>chat.bilibili.com</chatserver> 
<chatid>2962351</chatid> 
<mission>0</mission> 
<maxlimit>1500</maxlimit> 
<source>k-v</ source> 
<d p= "145.91299438477,1,25,16777215,1422201001,0,d6673695,757075520" > I've never seen anyone so brazen </d > 
</i>

Header information does not require much attention to see the specific meaning of the p corresponding parameter under D label:

The first one: the time when the curtain appears

Second: The type of the projectile screen (1, from right to left; 6, from left to right; 5, top barrage; 4, bottom barrage; 7, advanced barrage; 8, script bullet screen)

Third: Font size

Fourth one: color

Fifth: Time stamp

Sixth: Bomb screen pool ID

Seventh: User hash value

Eighth: Bomb Screen ID

The following is a detailed analysis of the bomb screen code

/** 
* 
@param stream 
* @return 
/Private Basedanmakuparser Createparser from the barrage file (InputStream Stream) { 
if (stream = = null) {return 
new Basedanmakuparser () { 
@Override 
protected Danmakus Parse () {
   return new Danmakus (); 
} 
Iloader loader = danmakuloaderfactory.create (Danmakuloaderfactory.tag_bili);//Create a Bilidanmakuloader instance to load the bullet screen stream file 
try { 
loader.load (stream); 
} catch (Illegaldataexception e) { 
e.printstacktrace (); 
} 
Basedanmakuparser parser = new Bilidanmukuparser ()//Bomb screen parser 
idatasource<?> DataSource = Loader.getdatasource (); 
Parser.load (DataSource); 
return parser; 
}

Specific solution:

String tagName = localname.length ()!= 0? Localname:qname; 
TagName = Tagname.tolowercase (Locale.getdefault ()). Trim (); 
if (Tagname.equals ("D")) { 
String pvalue = Attributes.getvalue ("P"); 
Parse p value to Danmaku 
string[] values = Pvalue.split (","); 
if (Values.length > 0) { 
long time = (long) (Float.parsefloat (values[0)) * 1000); 
Rseint (Values[1]); Barrage type 
Float textsize = float.parsefloat (values[2]);//font size 
int color = integer.parseint (values[3)) | 0xff0000 00; Color 
item = MContext.mDanmakuFactory.createDanmaku (type, mcontext); 
if (item!= null) { 
item.settime (time); 
Item.textsize = Textsize * (mdispdensity-0.6f); 
Item.textcolor = color; 
Item.textshadowcolor = Color <= color.black? Color.WHITE:Color.BLACK 
}} 
} 

When the bomb screen resource is loaded, the Mdvdanmuku prepare () method is invoked to execute the preparation. The prepared method in the Drawhandler.callback () callback is invoked when the preparation is complete. Then in this prepared method formally let the barrage start. The order of invocation is as follows:

Mdvdanmaku.prepare (Mparser, mdanmakucontext);//Incoming parsing complete barrage and context

Then execute the Prepare () method under Danmukuview

private void Prepare () { 
if (handler = = null) 
handler = new Drawhandler (Getlooper (Mdrawingthreadtype), this, Mdan makuvisible);//Create a handler 
}

Through this handler to achieve interprocess communication.

Handler.setconfig (config);

Handler.setparser (parser);

Handler.setcallback (Mcallback);

Handler.prepare ();-"will let handler send a message to carry out the real preparation

There is a callback in the Drawhandler

Public interface Callback {public 
void prepared (); 
public void Updatetimer (Danmakutimer timer); 
public void Danmakushown (Basedanmaku danmaku); 
public void drawingfinished (); 
}

The Real preparation

Mtimebase = Systemclock.uptimemillis (); 
if (Mparser = null | |!mdanmakuview.isviewready ()) {//not ready, delay 0.1 seconds before executing 
sendemptymessagedelayed (PREPARE); 
} else { 
Prepare (new Runnable () { 
@Override public 
void Run () { 
pausedposition = 0; 
Mready = true; 
if (mcallback!= null) { 
mcallback.prepared ();}}} 
); 

The above is the start call flow of the view of the bomb screen.

So, how do you add a pinball screen to pinch? Yuan Fang, what do you think? (tm How do I know what I think) look below

private void Adddanmaku (Boolean islive) { 
Basedanmaku Danmaku = MDanmakuContext.mDanmakuFactory.createDanmaku ( BASEDANMAKU.TYPE_SCROLL_RL);//Add a right-to-left scrolling barrage 
if (Danmaku = null | | | mdvdanmaku = NULL) {return 
; 
} 
Danmaku.text = "This is a barrage" + system.nanotime (); 
danmaku.padding = 5; 
danmaku.priority = 0; May be filtered by a variety of filters and hide the display set to 1, it will be shown to be suitable for the sending of the screen 
danmaku.islive = islive; 
Danmaku.settime (Mdvdanmaku.getcurrenttime () + 1200); 
Danmaku.textsize = 25f * (Mparser.getdisplayer (). Getdensity ()-0.6f); 
Danmaku.textcolor = color.red;//default set to red font 
danmaku.textshadowcolor = color.white; 
Danmaku.bordercolor = color.green;//in order to distinguish other shells and their hair, and then give their own shells with a border 
Mdvdanmaku.adddanmaku (Danmaku); 
}

The above is a small set up to introduce the Android frame of the framework of the Dark flame, I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.