Android Barrage frame Dark flames make

Source: Internet
Author: User
Tags tagname

The words of the wind, the language set the universe. Hello, I am wanjiang.

Today I will share the learning experience from Bilibili Open source Android bullet frame (danmakuflamemaster).

I have introduced the whole framework into the project in the form of model, so it is more convenient to observe the source code. can also be injected in a way that relies on it.

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

Let's just put what I'm going to do:


Page analysis

From the point of view, 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 is mostly layered, different from the live class, there may be another layer of interaction, showing check-in information, gift information and so on.

Since it is layered, I will directly use the Framelayout frame layout to achieve. To 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:layo Ut_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_height= "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=" W Rap_content "android:text=" @string/pause_danmaku "/> <button android:id=" @+id/btn_resum E "android:layout_width=" 0DP "android:layout_weight=" 1 "android:layout_height=" Wrap_conte            NT "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 "Andro Id:layout_width= "0DP" android:layout_weight= "1" android:layout_height= "Wrap_content" Android oid:text= "@string/send_danmakus"/> </LinearLayout></FrameLayout>

After writing the layout, first write an initialization method:

        Set maximum number of rows hashmap<integer,integer> Maxlinespair = new hashmap<> (); Maxlinespair.put (basedanmaku.type_scroll_rl,5);//The maximum display of the rolling barrage 5 lines//Set whether to prohibit overlapping hashmap<integer, boolean> Overl        Appingenablepair = new hashmap<> ();        Overlappingenablepair.put (BASEDANMAKU.TYPE_SCROLL_RL, true);        Overlappingenablepair.put (Basedanmaku.type_fix_top, true); Mdanmakucontext = Danmakucontext.create ();//Initialize Context Mdanmakucontext.setdanmakustyle (Idisplayer.danmaku_style_ stroken,3)///Set the barrage type mdanmakucontext.setduplicatemergingenabled (false);//Set whether to merge duplicate barrage Mdanmakucontext.setscroll Speedfactor (1.2f);//Set the bounce Speed Mdanmakucontext.setscaletextsize (1.2f);//Set the bullet screen font size Mdanmakucontext.setcachestuff ER (new Spannedcachestuffer (), mcachestufferadapter);//Set Cache draw filler graphics mix using Spannedcachestuffer Mdanmakucontext.setmaxim Umlines (Maxlinespair);//Set maximum number of rows mdanmakucontext.preventoverlapping (Overlappingenablepair);       Set whether to prohibit overlapping Mparser = Createparser (This.getresources (). Openrawresource (r.raw.comments));//Load Barrage resource file Mdvdanmaku.prepare (mParser        , Mdanmakucontext);        Mdvdanmaku.showfps (TRUE); Mdvdanmaku.enabledanmakudrawingcache (TRUE);


And then paste the implementation of the drawing filler, the main implementation of the picture and text together to arrange 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");        Spannablestringbuilder.setspan (New Backgroundcolorspan (Color.parsecolor ("#8A2233B1")), 0, Spannablestringbuilder.length (), spannable.span_inclusive_inclusive);        return spannablestringbuilder;    }

Under this class of Basedanmaku, the basic motion forms of the projectile are defined: TYPE_SCROLL_RL,TYPE_SCROLL_LR,type_fix_top,Type_fix_bottom and type_special. That is, from the right into the left, left into the right (reverse barrage), the top of the barrage, the bottom of the barrage and high-level bomb screen. (in addition to the script barrage)

At initialization time, you need to pass in a unique pop-up context Danmukucontext, which initializes some settings through the context. The barrage resource is stored under an XML file in the following format:

.

<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 such a brazen man </d ></i>
Header information does not need much attention, to see the D-tag p corresponding parameters of the specific meaning:

The first one: the time the barrage appears

Second: The type of projectile (1, from right to left, 6, from left to right, 5, the top of the barrage, 4, the bottom of the bomb screen; 7, the High-level bomb screen; 8, the script barrage ')

The third one: Font size

Fourth one: color

Fifth one: Timestamp

Sixth: The pool ID of the barrage

Seventh one: User hash value

Eighth one: the Bullet screen ID

The following is the specific parsing code of the projectile screen


    /**     * Lift the barrage from the barrage file *     @param stream     * @return *     *    /private Basedanmakuparser Createparser (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 barrage 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);//Occurrence int type = Integer.parseint (values[1]); Barrage type Float textSize = float.parsefloat (values[2]); Font size int color = Integer.parseint (values[3]) | 0xff000000;                    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; }                }            }
After the barrage resource has been loaded, call Mdvdanmuku's prepare () method to perform the preparation. The prepared method in the Drawhandler.callback () callback is called when the preparation is complete. Then formally let the barrage start in this prepared method. The invocation order is as follows:

Mdvdanmaku.prepare (Mparser, mdanmakucontext);//The barrage and context of incoming parsing completion

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 do 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 barrage view.
So, how do you add a barrage? Yuan Fang, what do you think? (tm How do I know what I think) look underneath
    private void Adddanmaku (Boolean islive) {        Basedanmaku Danmaku = MDanmakuContext.mDanmakuFactory.createDanmaku ( BASEDANMAKU.TYPE_SCROLL_RL)///Add a right-to-left scroll bullet        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 hidden display  set to 1, it will be shown  for the local send the barrage        danmaku.islive = islive;        Danmaku.settime (Mdvdanmaku.getcurrenttime () + +);        Danmaku.textsize = 25f * (Mparser.getdisplayer (). Getdensity ()-0.6f);        Danmaku.textcolor = color.red;//default is set to red font        danmaku.textshadowcolor = color.white;        Danmaku.bordercolor = color.green;//in order to distinguish the other barrage with their own bomb screen, and then give their own bomb screen plus border        Mdvdanmaku.adddanmaku (Danmaku);    }

Above, isThe Dark FlamesBasic use method.

Android Barrage frame Dark flames make

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.