Small floating window is still a common demand in live broadcast projects. Open other interfaces in the live broadcast room or return to the desktop to continue to play live broadcast content. The following is my implementation scheme.

rendering

Implementation approach

If your project is an in-app hover window, you can also get a DecorView and add a View to it, so you don’t have to get permissions

The floating window permission is obtained

Add permissions to manifest

<! - a suspended window permissions - > < USES - permission android: name = "android. Permission. SYSTEM_ALERT_WINDOW" / >Copy the code

Set the type of Window to Windows. If the type has changed since version 8.0, check if it has changed

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
    layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
}
Copy the code

Authority to judge

The levitating window needs to be opened manually by the user, and there needs to be a guide for the user

if (! Settings.candrawoverlays (this)) {// determine whether permissions are available val intent = intent (settings.action_manage_overlay_permission) // Data = uri.parse ("package:$packageName") // Open the system's approval interface to the user. StartActivityForResult (Intent, intent) REQ_CODE_1000) } @RequiresApi(Build.VERSION_CODES.M) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, Data) if (requestCode == REQ_CODE_1000) {if (settings.candrawoverlays (this)) {Copy the code

Handle sliding and inertial sliding

We use the updateViewLayout() method of The WindowManager to change the position of the Window based on the distance of the slide, but we need to calculate whether the distance of the slide is beyond the sliding boundary, so we can’t let our floating Window go outside the screen

The inertial slip is the template code, which is handed over to the onFling() method of GestureDetector, and then calculated with the OverScroller

One more thing to note is that our hover window not only handles the sliding time but also the click event. When the user clicks on the window, it will return to the live page. When onTouchEvent is handed over to GestureDetector for processing, the click event will not work. The setOnClickListener setting doesn’t work anymore, so you need to manually adjust this callback

override fun onSingleTapConfirmed(e: MotionEvent?) : Boolean {// Trigger onClick() callback performClick() return true}Copy the code

Packaging ideas

The floating window has some variable parts and invariable parts. The variable part is the style of the floating window and the specific operation of playing, while the invariable part is the operation of sliding. Therefore, separate the two parts and connect them with the adapter mode, in which users can customize the layout and implement their own business logic. Since only one FloatWindow is available globally at a time, a singleton class FloatWindow is used to manage the addition and removal of views.

// create a FloatView setAdapter val FloatView = FloatView(this).apply {setAdapter(SimpleAdapter())} // set the View to Window Floatwindow.getinstance (this).bindView(floatView) // Remove Window floatWindow.getInstance (this).removeView()Copy the code

The source address

Making the address

rendering