Floating small windows and packaging in Android live broadcast

Floating small windows are still relatively common requirements in live broadcast projects. Open other interfaces in the live room or exit to the desktop to continue playing live content. The following is my implementation plan.

Effect picture

Realization ideas

In fact, it is easy to think through WindowManagerthe addView()implementation, but requires the user's consent permissions floating window, if your project is a floating window within the application, you can go to get DecorViewto it to add a Viewso will not have to obtain the permission

Floating window permission acquisition

manifestAdd permissions

<!--    悬浮窗权限-->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

To Windowset up some typetype, where there is a change after the 8.0 version of the type to be a judge here

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
}

Judgment of authority

The floating window needs to be opened manually by the user, and here needs to be a guide for the user

if (!Settings.canDrawOverlays(this)) { // 判断是否有权限
    val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
    // packageName 是应用的包名
    intent.data = Uri.parse("package:$packageName")
    // 直接打开系统的同意界面给用户操作
    startActivityForResult(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)) {
            // 用户同意了就可以进行其它操作了
        }
    }
}

Handling sliding and inertial sliding

The slide is treated by WindowManagerthe updateViewLayout()method according to the distance slide change Windowof position, but the process to calculate whether the slide before sliding distance can slide over the border, can not let go of the floating window outside the screen go

Inertial sliding is the template code, hand it over to GestureDetectorthe onFling()method, and then OverScrollercalculate the current sliding value

One more thing to note, our floating window not only handles the sliding time but also the click event. When the user clicks on the window, it also returns to the live page . The click event will not work when the front is onTouchEventhanded over GestureDetectorto handle it. , That is, the setOnClickListenersetting has no effect, here you have to manually adjust this callback

override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
  // 触发 onClick() 回调
    performClick()
    return true
}

Packaging ideas

The floating window has some variable parts and unchanging parts. The variable is the style of the floating window and the specific playback operation. The unchanging is the sliding operation, so the two parts are separated and the two parts are connected using the adapter mode. In the adapter, users can customize the layout and implement their own business logic. Since the floating window has a global effect, there can only be one at a time, so a singleton class is used FloatWindowto manage the addition and deletion of View.

// 创建 FloatView 设置 Adapter
val floatView = FloatView(this).apply {
    setAdapter(SimpleAdapter())
}
// 把 View 设置给 Window
FloatWindow.getInstance(this).bindView(floatView)
// 移除 Window
FloatWindow.getInstance(this).removeView()

Source address

github address

Effect picture

Guess you like

Origin blog.csdn.net/u012165769/article/details/114459903