[Android advanced] interpretation of every day's beautiful floating lyrics (mini lyrics)

Source: Internet
Author: User
Tags drawtext gety

 

I believe many of my friends have used this music player on Android phones. I wonder if you have noticed that every day there is a special effect on Mini lyrics.

 

What is the effect? The lyrics are always displayed and can be dragged. Type QQ music, the lyrics displayed on the computer.

 

Next, let's take a look at the effect.

 

 

The lyrics are on all interfaces.

 

Next we will dissect this effect. I think there are three main difficulties:

1. The lyrics are suspended on all pages.

2. You can drag the lyrics.

3. playback effect of the lyrics (color coverage)

 

For the first point, the first thought of is windowmanager, which may be used by many people. It is generally used to obtain the screen width and height, so this time we will use this class to bring our lyrics to the top forever.

 

By viewing the API, we can see that in the windowmanager. layoutparams class, there are several attributes that can be set to the top of the view.

 

Type_system_overlay

 

Window Type: System overlay windows, which need to be displayed on top of everything else.

Type_system_alert

Window Type: System window, such as low power alert.

Type_phone

These windows are normally placed above all applications, but behind the status bar.

 


Let's test the following code to make a view overwrite all views.

Windowmanager WM = (windowmanager) getapplicationcontext (). getsystemservice (window_service); <br/> windowmanager. layoutparams Params = new windowmanager. layoutparams (); <br/> Params. type = windowmanager. layoutparams. type_system_overlay; </P> <p> Params. width = windowmanager. layoutparams. wrap_content; <br/> Params. height = windowmanager. layoutparams. wrap_content; </P> <p> textview TV = new textview (this); <br/> WM. addview (TV, Params );


 

 

It is worth noting that windowmanager is also obtained through getsystemservice, but getapplicationcontext must be obtained first, otherwise it will be invalid.

 

 

Direct windowmanager WM = (windowmanager) getsystemservice (window_service); this is invalid !!

 

 

 

Also, do not forget to add permissions in manifest. xml:

 

<Uses-Permission Android: Name = "android. Permission. system_alert_window"/>

Now, we can stick the lyrics forever. But don't be proud. Now, the result is that textview is at the top level, and then you will find that nothing can be done on the page, anything under textview, you cannot even click it.

 

 

To solve this problem, we must add the flags parameter to make the current view lose focus, so that the subsequent page gets focus. The Code is as follows:

Params. Flags = layoutparams. flag_not_touch_modal | layoutparams. flag_not_focusable;

Add this sentence.

 

 

 

 

 

Well, what we need to deal with below is to make the lyrics move. What should we do?

 

 

We know that to move a view object on a page, you only need to implement its ontouchevent event.

 

 

 

 

The second step is to move the lyrics!

 

 

First, we define a textview class: mytextview, which inherits from textview and implements the ontouchevent method. Let's take a look at the Code:

 

@ Override <br/> Public Boolean ontouchevent (motionevent event) {<br/> // coordinates of the touch point relative to the upper left corner of the screen <br/> X = event. getrawx (); <br/> Y = event. getrawy ()-tool_bar_high; <br/> log. D (TAG, "------ X:" + x + "------ Y:" + Y); </P> <p> switch (event. getaction () {<br/> case motionevent. action_down: <br/> startx = event. getx (); <br/> starty = event. gety (); <br/> break; <br/> case motionevent. action_move: <br/> updateposition (); <br/> break; <br/> case motionevent. action_up: <br/> updateposition (); <br/> startx = starty = 0; <br/> break; <br/>}</P> <p> return true; <br/>}< br/> // update the floating window position parameter <br/> private void updateposition () {<br/> // current position of the view <br/> Params. X = (INT) (X-startx); <br/> Params. y = (INT) (Y-starty); <br/> WM. updateviewlayout (this, Params); <br/>} 

 

 

Getrawx and getrawy are used to obtain the distance between the touch point and the upper left corner of the screen. Getx and Gety are used to obtain the distance between the touch point and the top left corner of textview.

The two are the coordinates in the upper left corner of the view.

 

In addition, you must specify the X and Y coordinates of the view when displaying the view. Otherwise, the view will be misplaced when dragging.

Windowmanager WM = (windowmanager) getapplicationcontext (). getsystemservice (window_service); <br/> windowmanager. layoutparams Params = mytextview. params; </P> <p> Params. type = windowmanager. layoutparams. type_system_alert | windowmanager. layoutparams. type_system_overlay; <br/> Params. flags = layoutparams. flag_not_touch_modal | layoutparams. flag_not_focusable; </P> <p> Params. width = windowmanager. layoutparams. fill_parent; <br/> Params. height = windowmanager. layoutparams. wrap_content; <br/> Params. alpha = 80; </P> <p> Params. gravity = gravity. left | gravity. top; <br/> // set the initial values of x and y in the upper left corner of the screen. <br/> Params. X = 0; <br/> Params. y = 0; </P> <p> TV = new mytextview (topframe. this); <br/> WM. addview (TV, Params ); 

 

The following three statements are critical:

Params. gravity = gravity. left | gravity. top; <br/> // set the initial values of x and y in the upper left corner of the screen. <br/> Params. X = 0; <br/> Params. y = 0; 

 

Now, you can move the view.

 

 

 

The following is the third step: Play the lyrics.

In this example, there is only one loop, and the actual music player needs to be more complex. We need to calculate the coverage speed of the lyrics based on the length and interval of the opera, and then overwrite the lyrics based on the speed, present to the user.

 

To achieve the effect of playing the lyrics, you need to use the paint brush and shader. Another problem is the UI refresh.

 

Let's take a look at the Code:

@ Override <br/> protected void ondraw (canvas) {<br/> // todo auto-generated method stub <br/> super. ondraw (canvas); <br/> float1 + = 0.001f; <br/> float2 + = 0.001f; </P> <p> If (float2> 1.0) {<br/> float1 = 0.0f; <br/> float2 = 0.01f; <br/>}< br/> This. settext (""); <br/> float Len = This. gettextsize () * text. length (); <br/> shader = new lineargradient (0, 0, Len, 0, <br/> New int [] {color. yellow, color. red}, new float [] {float1, float2}, <br/> tilemode. clamp); <br/> paint P = new paint (); <br/> P. setshader (shader); <br/> // The following statement controls the lyrics <br/> P. settextsize (20f); <br/> P. settypeface (typeface. default_bold); <br/> // pay attention to the X and Y coordinates here, especially the Y coordinates. <br/> canvas. drawtext (text, 0, 20, p); </P> <p>} 

Now, send the following message:

 

 

 

 

The code of the entire project is attached: (one class is two classes and one layout file)

 

Androidmanifest. xml

<? XML version = "1.0" encoding = "UTF-8"?> <Br/> <manifest xmlns: Android = "http://schemas.android.com/apk/res/android" <br/> package = "com. yfz "<br/> Android: versioncode =" 1 "<br/> Android: versionname =" 1.0 "> <br/> <application Android: icon = "@ drawable/icon" Android: Label = "@ string/app_name"> <br/> <activity Android: Name = ". topframe "<br/> Android: Label =" @ string/app_name "> <br/> <intent-filter> <br/> <action Android: Name =" android. intent. action. main "/> <br/> <category Android: Name =" android. intent. category. launcher "/> <br/> </intent-filter> <br/> </activity> <br/> </Application> </P> <p> <uses- permission Android: name = "android. permission. system_alert_window "/> <br/> <uses-SDK Android: minsdkversion =" 8 "> </uses-SDK> <br/> </manifest> 

 

Main. xml

<? XML version = "1.0" encoding = "UTF-8"?> <Br/> <linearlayout xmlns: Android = "http://schemas.android.com/apk/res/android" <br/> Android: Orientation = "vertical" <br/> Android: layout_width = "fill_parent" <br/> Android: layout_height = "fill_parent" <br/> <button <br/> Android: id = "@ + ID/BT" <br/> Android: text = "Click here to try" <br/> Android: layout_width = "wrap_content" <br/> Android: layout_height = "wrap_content" <br/> Android: layout_gravity = "center" <br/> </linearlayout> <br/> 

 

Topframe. Java

Package COM. yfz; <br/> Import COM. yfz. view. mytextview; <br/> Import android. app. activity; <br/> Import android. graphics. rect; <br/> Import android. OS. bundle; <br/> Import android. view. gravity; <br/> Import android. view. view; <br/> Import android. view. windowmanager; <br/> Import android. view. view. onclicklistener; <br/> Import android. view. windowmanager. layoutparams; <br/> Import android. widget. button; <br/> Pu BLIC class topframe extends activity {<br/>/** called when the activity is first created. */<br/> @ override <br/> Public void oncreate (bundle savedinstancestate) {<br/> super. oncreate (savedinstancestate); <br/> setcontentview (R. layout. main); <br/> button = (button) findviewbyid (R. id. BT); </P> <p> button. setonclicklistener (onclick); <br/>}</P> <p> private mytextview TV = NULL; </P> <p> onclicklistener Onclick = new onclicklistener () {</P> <p> @ override <br/> Public void onclick (view v) {<br/> If (TV! = NULL & TV. isshown () {<br/> windowmanager WM = (windowmanager) getapplicationcontext (). getsystemservice (topframe. this. window_service); <br/> WM. removeview (TV); <br/>}< br/> show (); </P> <p >}< br/> }; </P> <p> private void show () {<br/> rect frame = new rect (); <br/> getwindow (). getdecorview (). getwindowvisibledisplayframe (FRAME); <br/> mytextview. tool_bar_high = frame. top; </P> <p> windowmanager WM = (windowmanager) getapplicationcontext (). getsystemservice (window_service); <br/> windowmanager. layoutparams Params = mytextview. params; </P> <p> Params. type = windowmanager. layoutparams. type_system_alert | windowmanager. layoutparams. type_system_overlay; <br/> Params. flags = layoutparams. flag_not_touch_modal | layoutparams. flag_not_focusable; </P> <p> Params. width = windowmanager. layoutparams. fill_parent; <br/> Params. height = windowmanager. layoutparams. wrap_content; <br/> Params. alpha = 80; </P> <p> Params. gravity = gravity. left | gravity. top; <br/> // set the initial values of x and y in the upper left corner of the screen. <br/> Params. X = 0; <br/> Params. y = 0; </P> <p> TV = new mytextview (topframe. this); <br/> WM. addview (TV, Params); <br/>}< br/> @ override <br/> protected void ondestroy () {<br/> super. ondestroy (); <br/>}< br/>} 

 

Mytextview. Java

Package COM. yfz. view; <br/> Import android. content. context; <br/> Import android. graphics. canvas; <br/> Import android. graphics. color; <br/> Import android. graphics. lineargradient; <br/> Import android. graphics. paint; <br/> Import android. graphics. rect; <br/> Import android. graphics. shader; <br/> Import android. graphics. typeface; <br/> Import android. graphics. shader. tilemode; <br/> Import android. OS. handler; <br/> Import android. OS. message; <br/> Import android. util. log; <br/> Import android. view. motionevent; <br/> Import android. view. view; <br/> Import android. view. windowmanager; <br/> Import android. widget. textview; <br/> Import android. widget. toast; <br/> public class mytextview extends textview {<br/> private final string tag = mytextview. class. getsimplename (); </P> <p> Public static int tool_bar_high = 0; <br/> Public static windowmanager. layoutparams Params = new windowmanager. layoutparams (); <br/> private float startx; <br/> private float starty; <br/> private float X; <br/> private float y; </P> <p> private string text; </P> <p> windowmanager WM = (windowmanager) getcontext (). getapplicationcontext (). getsystemservice (getcontext (). window_service); </P> <p> Public mytextview (context) {<br/> super (context); <br/> text = "only good mothers in the world, A fucking child is like a treasure "; <br/> This. setbackgroundcolor (color. argb (90,150,150,150); <br/> // The following statement does not control the lyrics, but only controls the background size. If not set, when the paint font is large, it will be blocked <br/> This. settextsize (20f); <br/> handler = new handler (); <br/> handler. post (update); <br/>}< br/> @ override <br/> Public Boolean ontouchevent (motionevent event) {<br/> // coordinates of the touch point relative to the upper left corner of the screen <br/> X = event. getrawx (); <br/> Y = event. getrawy ()-tool_bar_high; <br/> log. D (TAG, "------ X:" + x + "------ Y:" + Y); </P> <p> switch (event. getaction () {<br/> case motionevent. action_down: <br/> startx = event. getx (); <br/> starty = event. gety (); <br/> break; <br/> case motionevent. action_move: <br/> updateposition (); <br/> break; <br/> case motionevent. action_up: <br/> updateposition (); <br/> startx = starty = 0; <br/> break; <br/>}</P> <p> return true; <br/>}</P> <p> @ override <br/> protected void ondraw (canvas) {<br/> // todo auto-generated method stub <br/> super. ondraw (canvas); <br/> float1 + = 0.001f; <br/> float2 + = 0.001f; </P> <p> If (float2> 1.0) {<br/> float1 = 0.0f; <br/> float2 = 0.01f; <br/>}< br/> This. settext (""); <br/> float Len = This. gettextsize () * text. length (); <br/> shader = new lineargradient (0, 0, Len, 0, <br/> New int [] {color. yellow, color. red}, new float [] {float1, float2}, <br/> tilemode. clamp); <br/> paint P = new paint (); <br/> P. setshader (shader); <br/> // The following statement controls the lyrics <br/> P. settextsize (20f); <br/> P. settypeface (typeface. default_bold); <br/> // pay attention to the X and Y coordinates here, especially the Y coordinates. <br/> canvas. drawtext (text, 0, 20, p); </P> <p >}</P> <p> private runnable update = new runnable () {<br/> Public void run () {<br/> mytextview. this. update (); <br/> handler. postdelayed (Update, 3); <br/>}< br/>}; </P> <p> private void Update () {<br/> postinvalidate (); <br/>}</P> <p> private float float1 = 0.0f; <br/> private float float2 = 0.01f; </P> <p> private handler; <br/> // update the floating window position parameter <br/> private void updateposition () {<br/> // view current position <br/> Params. X = (INT) (X-startx); <br/> Params. y = (INT) (Y-starty); <br/> WM. updateviewlayout (this, Params); <br/>}< br/>} 

 

Okay, so much.

 

If it is useful to you, please leave a message to support it.


In addition, please indicate the source reprint: http://blog.csdn.net/feng88724/archive/2011/04/25/6362710.aspx

Source code: http://download.csdn.net/source/3231657

Related Article

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.