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