Android 中的浮动视频视图

Floating Video View in Android

我想做的是:

我有一个带有滚动视图且顶部有视频的片段。我想要实现的是让视频在我滚动时浮动。

与此 link 类似的行为:https://www.independentarabia.com/jsonfeed/api/v2/node/34291

我查看了画中画模式,但没有成功

谁能告诉我如何实现这种行为?

万一有人想做这样的事情: 我参考了jw播放器库:

scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { v, _, scrollY, _, oldScrollY ->
            x = 0
            if (scrollY > 200) {
                if (!mPlayerContainer.isMovable) {
                    movable = false
                    x = 2
                } else {
                    x = 0
                    val momentView = v.getChildAt(v.childCount - 1)

                val diff = (momentView.bottom - (scroll.height + scroll
                    .scrollY))

                if (diff < 50) {
                    val layoutParamsNew =
                        RelativeLayout.LayoutParams(mPlayerContainer.width, mPlayerContainer.height)
                    layoutParamsNew.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
                    layoutParamsNew.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
                    val displayMetrics = resources.displayMetrics
                    layoutParamsNew.setMargins(
                        0,
                        0,
                        (displayMetrics.density * 16).roundToInt(),
                        (displayMetrics.density * 16).roundToInt()
                    )
                    mPlayerContainer.layoutParams = layoutParamsNew
                } else {
                    val layoutParamsNew =
                        RelativeLayout.LayoutParams(mPlayerContainer.width, mPlayerContainer.height)
                    layoutParamsNew.addRule(RelativeLayout.CENTER_VERTICAL)
                    layoutParamsNew.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
                    val displayMetrics = resources.displayMetrics
                    layoutParamsNew.setMargins(
                        0,
                        0,
                        (displayMetrics.density * 16).roundToInt(),
                        (displayMetrics.density * 16).roundToInt()
                    )
                    mPlayerContainer.layoutParams = layoutParamsNew
                }
            }
        } else if (scrollY < 200 && mPlayerContainer.isMovable) {
            movable = true
            x = 1
        }
        if (x != 0) {
            toggleMovablePlayer()
        }
    })
 private fun toggleMovablePlayer() {
    if (!movable) {
        // Set the player container to movable, in order to intercept touch events.
        mPlayerContainer.isMovable = true

        // Disable fullscreen rotation handling on the JW Player.
        mPlayerView!!.setFullscreen(mPlayerView!!.fullscreen, false)

        // Disable controls.
        mPlayerView!!.controls = false
        if (mPlayerState != PlayerState.PLAYING && mPlayerState != PlayerState.BUFFERING) {
            // Start playback in case the user hasn't done this yet, since we don't want to have
            // a movable player that does not play anything...
            mPlayerView!!.play()
        }

        // Scale the player.
        mInitialLayoutParams = mPlayerContainer.layoutParams
        val newWidth = (mPlayerContainer.width / SCALING_FACTOR)
        val newHeight = (mPlayerContainer.height / SCALING_FACTOR)
        val layoutParams = RelativeLayout.LayoutParams(newWidth.toInt(), newHeight.toInt())

        // Position the player in the right bottom corner.
        mPlayerContainer.layoutParams = getInitialMovablePlayerLayoutParams(layoutParams)

        // Set an onTouchListener on the player which handles MotionEvents.
        mPlayerContainer.setOnTouchListener(View.OnTouchListener { v, event ->
            if (v.id == R.id.player_container) {
                val layoutParams = v.layoutParams as RelativeLayout.LayoutParams
                when (event.action) {
                    MotionEvent.ACTION_DOWN ->
                        // Notify the MovablePlayerLayout that we started consuming
                        // events in order to receive ACTION_MOVE events.
                        return@OnTouchListener true
                    MotionEvent.ACTION_MOVE -> {
                        var topMargin = event.rawY.toInt() - v.height
                        var leftMargin = event.rawX.toInt() - v.width / 2

                        // Make sure that the view can not go "out of bounds"
                        if (topMargin < 0) {
                            // Out of bounds: TOP
                            topMargin = 0
                        }
                        if (topMargin > mContentContainer.height - mPlayerContainer.height) {
                            // Out of bounds: BOTTOM
                            topMargin = mContentContainer.height - mPlayerContainer.height
                        }
                        if (leftMargin < 0) {
                            // Out of bounds: LEFT
                            leftMargin = 0
                        }
                        if (leftMargin > mContentContainer.width - mPlayerContainer.width) {
                            // Out of bounds: RIGHT
                            leftMargin = mContentContainer.width - mPlayerContainer.width
                        }

                        layoutParams.topMargin = topMargin
                        layoutParams.leftMargin = leftMargin

                        // Make sure the align rules have been removed.
                        layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
                        layoutParams.removeRule(RelativeLayout.CENTER_VERTICAL)
                        layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT)
                        layoutParams.rightMargin = 0
                        layoutParams.bottomMargin = 0
                        // Set the new layout parameters
                        v.layoutParams = layoutParams
                        return@OnTouchListener true
                    }
                }
            }
            false
        })
    } else {
        // Disable the movable property of the MovableViewLayout.
        mPlayerContainer.isMovable = false
        // Restore the initial layout parameters.
        mPlayerContainer.layoutParams = mInitialLayoutParams
        // Remove the onTouchListener.
        mPlayerContainer.setOnTouchListener(null)
        // Re-enable the controls.
        mPlayerView!!.controls = true
        // Re-enable fullscreen rotation handling, and go to fullscreen if we're in landscape mode.
        mPlayerView!!.setFullscreen(
            resources.configuration.orientation === Configuration.ORIENTATION_LANDSCAPE,
            true
        )
    }
}
  private fun setInitialLayoutParams() {
    val displayMetrics = resources.displayMetrics
    if (resources.configuration.orientation === Configuration.ORIENTATION_PORTRAIT) {
        /*mPlayerContainer.layoutParams = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, displayMetrics.widthPixels / 16 * 9
        ) // 16:9*/
        mPlayerContainer.layoutParams = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                200f,
                resources.displayMetrics
            ).toInt()
        )
    } else {
        // We need to use height to calculate a 16:9 ratio since we're in landscape mode.
        mPlayerContainer.layoutParams = RelativeLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, displayMetrics.heightPixels / 16 * 9
        ) // 16:9
        // Toggle fullscreen, since we're in landscape mode.
        mPlayerView!!.setFullscreen(true, true)
    }
}

/**
 * Positions the movable player to the right bottom corner.
 *
 * @param layoutParams
 * @return
 */
private fun getInitialMovablePlayerLayoutParams(layoutParams: RelativeLayout.LayoutParams): RelativeLayout.LayoutParams {
    layoutParams.addRule(RelativeLayout.CENTER_VERTICAL)
    layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
    val displayMetrics = resources.displayMetrics
    layoutParams.setMargins(0, 0, Math.round(displayMetrics.density * 16), Math.round(displayMetrics.density * 16))
    return layoutParams
}