You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现类似YouTube的Fragment拖拽效果(draggable panel已废弃)

YouTube-Style Floating Player (Replace Deprecated Draggable Panel)

Alright, let's solve this problem of building a YouTube-like floating player—where your entire Fragment minimizes, leaving just the player view active and visible over other Fragments or Activities—now that the draggable panel library is deprecated. Here are two robust, modern solutions you can implement:

Google's Jetpack WindowManager is the go-to replacement for legacy window management code. It handles cross-device compatibility (including foldables) and follows Android's latest best practices.

Step-by-Step Implementation:

  • Add Dependency:

    implementation "androidx.window:window:1.1.0"
    implementation "androidx.window:window-java:1.1.0" // For Java projects
    
  • Initialize WindowManager:
    In your Fragment, create an instance of WindowManager and define layout parameters for your floating player:

    private lateinit var windowManager: WindowManager
    private lateinit var floatingPlayerView: View
    private val params = WindowManager.LayoutParams().apply {
        type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else {
            WindowManager.LayoutParams.TYPE_PHONE
        }
        flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        width = WindowManager.LayoutParams.WRAP_CONTENT
        height = WindowManager.LayoutParams.WRAP_CONTENT
        gravity = Gravity.TOP or Gravity.START
        x = 100
        y = 100
    }
    
  • Inflate & Attach Floating Player:
    When the user taps to minimize the Fragment, inflate your player layout and add it to the window:

    floatingPlayerView = layoutInflater.inflate(R.layout.layout_floating_player, null)
    windowManager = requireContext().getSystemService(Context.WINDOW_SERVICE) as WindowManager
    windowManager.addView(floatingPlayerView, params)
    
    // Hide your Fragment's main content
    binding.mainFragmentContent.visibility = View.GONE
    
  • Handle Drag Functionality:
    Add touch listeners to let users drag the player around the screen:

    var initialX = 0
    var initialY = 0
    var initialTouchX = 0f
    var initialTouchY = 0f
    
    floatingPlayerView.setOnTouchListener { _, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                initialX = params.x
                initialY = params.y
                initialTouchX = event.rawX
                initialTouchY = event.rawY
                true
            }
            MotionEvent.ACTION_MOVE -> {
                params.x = initialX + (event.rawX - initialTouchX).toInt()
                params.y = initialY + (event.rawY - initialTouchY).toInt()
                windowManager.updateViewLayout(floatingPlayerView, params)
                true
            }
            else -> false
        }
    }
    
  • Clean Up & Restore:
    When restoring the Fragment, remove the floating view and show the main content again. Don't forget to clean up in onDestroyView() to avoid leaks:

    private fun restoreFragment() {
        if (::floatingPlayerView.isInitialized) {
            windowManager.removeView(floatingPlayerView)
        }
        binding.mainFragmentContent.visibility = View.VISIBLE
    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        if (::floatingPlayerView.isInitialized) {
            windowManager.removeView(floatingPlayerView)
        }
    }
    

2. Custom WindowManager Implementation (Full Control)

If you need more granular control over the floating window's behavior, you can build a custom solution using the system WindowManager directly. This gives you full access to all layout parameters and window flags.

Key Notes:

  • Permission: For Android 6.0+, request the SYSTEM_ALERT_WINDOW permission. Redirect users to app settings if denied:
    if (!Settings.canDrawOverlays(requireContext())) {
        val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:${requireContext().packageName}"))
        startActivityForResult(intent, OVERLAY_PERMISSION_REQUEST_CODE)
    }
    
  • Lifecycle Binding: Tie the floating view's lifecycle to your Fragment/Activity to prevent leaks. Use onPause()/onResume() to show/hide the player as needed.
  • Player State Sync: Keep the floating player's playback state (play/pause, progress) synced with your original Fragment's player. Use a ViewModel or singleton player manager for this.

Bonus: Picture-in-Picture (PiP) Mode

If you don't need full customization, Android's built-in PiP mode is a quick alternative. It lets your player stay visible over other apps, though layout control is limited:

  • Add android:supportsPictureInPicture="true" to your Activity in AndroidManifest.xml.
  • Call enterPictureInPictureMode() when you want to minimize the player.

内容的提问来源于stack exchange,提问作者Raja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:43:54