Exoplayer 视频在滚动时从 BottomsheetDialogFragment 流出 ==

问题描述 投票:0回答:1

在 BottomsheetDialogFragment 中加载包含 exoplayer 磁贴的现有片段时,Exoplayer 视频在滚动时会超出 BottomsheetDialogFragment 的范围。

尝试了很多改变样式、行为、嵌套滚动视图等的解决方案,但没有解决问题。

(https://i.stack.imgur.com/BJH5a.png)

ReelBottomSheetDialogFragment.class

import android.app.Dialog
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.WindowManager
import androidx.databinding.DataBindingUtil
import com.caratlane.android.Fragments.ListingPageFragment
import com.caratlane.android.R
import com.caratlane.android.Utils.Constants
import com.caratlane.android.Utils.Constants.ReelsKey.PDP_ORIGIN_KEY
import com.caratlane.android.Utils.Constants.ReelsKey.PRODUCT_SKU
import com.caratlane.android.Utils.Methods
import com.caratlane.android.activity.CLBaseToolbarActivity
import com.caratlane.android.activity.MainActivity
import com.caratlane.android.activity.ShoppingCartActivity
import com.caratlane.android.databinding.LayoutProductDetailBottomSheetBinding
import com.caratlane.android.mvvm.home.view.HomeFragment
import com.caratlane.android.mvvm.listing.view.ListingFragment
import com.caratlane.android.mvvm.loginFeature.model.apimodel.NavigationSource
import com.caratlane.android.mvvm.loginFeature.view.fragments.LoginLandingFragment
import com.caratlane.android.mvvm.reels.view.ReelsFragment
import com.caratlane.android.mvvm.reviewsratings.view.BaseProductDetailFragment
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment


class ReelBottomSheetDialogFragment : BottomSheetDialogFragment(),
    LoginLandingFragment.LogInCallback{
    var binding: LayoutProductDetailBottomSheetBinding? = null
    var onReelsBottomSheetStatusChange: OnBottomSheetStatusChange? = null
    var onPdpBottomSheetStatusChange: OnBottomSheetStatusChange? = null
    private var logInReelListener: LoginLandingFragment.LogInCallback? = null
    var sku: String? = null
    var reelClickedListner : ReelClickedListener? =null

    override fun getTheme(): Int {
        return R.style.AppBottomSheetDialogTheme
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        (activity as CLBaseToolbarActivity?)?.hideToolBar()
        (activity as CLBaseToolbarActivity?)?.hideBackToolbar()
        return if (arguments?.getBoolean(ReelsFragment.OPEN_PDP, false) == true) {
            sku = arguments?.getString(PRODUCT_SKU)
            addProductDetailFragment()
            //BottomSheetDialog(requireContext(), theme)
            openFullExpandedBottomSheet()
        } else {
            openLoginFragment()
            openFullExpandedBottomSheet()

        }
    }

    private fun openFullExpandedBottomSheet(): BottomSheetDialog {
        val dialog = BottomSheetDialog(requireContext(), theme)
        dialog.setOnShowListener {
            val bottomSheetDialog = it as BottomSheetDialog
            val parentLayout =
                bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
            parentLayout?.let { it ->
                val behaviour = BottomSheetBehavior.from(it)
                //setupFullHeight(it)
                behaviour.state = BottomSheetBehavior.STATE_COLLAPSED
                behaviour.addBottomSheetCallback(object :
                    BottomSheetBehavior.BottomSheetCallback() {
                    override fun onStateChanged(bottomSheet: View, newState: Int) {
                    /*    if (newState == BottomSheetBehavior.STATE_EXPANDED) {
                            // Bottom sheet is expanded, change status bar color
                            //changeStatusBarColor(getResources().getColor(R.color.black))
                            setStatusBarColor(getResources().getColor(R.color.black))
                        } else {
                            // Revert to default status bar color when bottom sheet is closed
                            //changeStatusBarColor(resources.getColor(R.color.white))
                            setStatusBarColor(getResources().getColor(R.color.black))

                        }*/

                    }

                    override fun onSlide(bottomSheet: View, slideOffset: Float) {
                        //updateStatusBarColor(R.color.black)
                        //changeStatusBarColor(R.color.black)

                    }
                })
            }
        }
        return dialog
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(
            LayoutInflater.from(context),
            R.layout.layout_product_detail_bottom_sheet,
            container,
            false
        )
        return binding?.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                view.viewTreeObserver.removeOnGlobalLayoutListener(this)
                dialog?.setOnShowListener {
                }
            }
        })
    }

    private fun setupFullHeight(bottomSheet: View) {
        val layoutParams = bottomSheet.layoutParams
        layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
        bottomSheet.layoutParams = layoutParams
    }

    private fun addProductDetailFragment() {
        val productDetailFragment = BaseProductDetailFragment()
        arguments?.putBoolean("isToolbarVisible", false)
        arguments?.putString(PDP_ORIGIN_KEY, arguments?.getString(PDP_ORIGIN_KEY))
        arguments?.putString(
            Constants.ReelsKey.IS_FROM,
            Constants.ReelsKey.REELS_PAGE
        )
        productDetailFragment.arguments = arguments
        productDetailFragment.takeCallback(object : BaseProductDetailFragment.ViewClick{
            override fun onAnyViewClicked() {
                Log.d("bottomsheetdialogfragment","in on click")
                dialog?.dismiss()
            }

            override fun onReelClicked(videoId: Long) {
                Log.d("bottomsheetdialogfragment","reel video id "+videoId.toString())
                reelClickedListner?.onReelClickedFromPdTray(videoId)
            }
        })
        val fragmentManager = childFragmentManager.beginTransaction()
        fragmentManager.replace(R.id.product_detail_container, productDetailFragment, productDetailFragment.tag)
        fragmentManager.commit()
    }

    override fun onResume() {
        super.onResume()
        if (sku != null) {
            onPdpBottomSheetStatusChange?.onPDBottomSheetOpened(sku)
            onReelsBottomSheetStatusChange?.onPDBottomSheetOpened(sku)
        }
    }

    fun setPdpBottomSheetOpenListener(listener: OnBottomSheetStatusChange) {
        onPdpBottomSheetStatusChange = listener
    }

    fun setReelsBottomSheetStatusChangeListener(listener: OnBottomSheetStatusChange){
        onReelsBottomSheetStatusChange = listener
    }

    private fun openLoginFragment() {
        if (!Methods.isActivityAlive(activity)) return
        val loginLandingFragment: LoginLandingFragment = if (activity is MainActivity) {
            (activity as MainActivity).signInSignUpFragment
        } else {
            (activity as ShoppingCartActivity).signInSignUpFragment
        }
        val arguments = Bundle()
        arguments.putSerializable(
            Constants.BUNDLE_EXTRAS.SOURCE_NAV,
            NavigationSource.ReelsPage
        )
        loginLandingFragment.arguments = arguments
        loginLandingFragment.setLoginListener(this)
        childFragmentManager.beginTransaction()
            .add(R.id.product_detail_container, loginLandingFragment, loginLandingFragment.tag)
            .commitAllowingStateLoss()
    }

    fun setLoginListener(listener : LoginLandingFragment.LogInCallback){
        logInReelListener = listener
    }


    override fun onLoginSuccess() {
        logInReelListener?.onLoginSuccess()
        dismiss()
    }

    override fun onLoginBackPressed() {
        dialog?.dismiss()
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        if (sku != null) {
            onPdpBottomSheetStatusChange?.onPDBottomSheetClose(sku)
            onReelsBottomSheetStatusChange?.onPDBottomSheetClose(sku)
        }
        //logInReelListener?.onLoginBottomSheetDismiss()
    }

    fun setReelClickedListener(listener  : ReelClickedListener){
        reelClickedListner = listener
    }

    interface OnBottomSheetStatusChange {
        fun onPDBottomSheetOpened(sku: String?)
        fun onPDBottomSheetClose(sku: String?)
    }

    interface ReelClickedListener{
        fun onReelClickedFromPdTray(videoId : Long)
    }
}

样式.xml

  <!--    Rounded corner BottomSheet-->
    <style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowSoftInputMode">adjustResize|stateAlwaysVisible</item>
        <item name="bottomSheetStyle">@style/AppModalStyle</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>

layout_product_detail_bottom_sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">


    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:id="@+id/cl_product_detail"
        android:layout_height="match_parent"
        android:layout_width="match_parent">

        <androidx.appcompat.widget.LinearLayoutCompat
            android:id="@+id/ll_product_detail_header"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/dp_10"
                android:layout_marginStart="@dimen/dp_10"
                android:layout_marginBottom="@dimen/dp_10"
                android:gravity="center">

                <LinearLayout
                    android:layout_width="@dimen/_32dp"
                    android:layout_height="@dimen/dp_4"
                    android:layout_gravity="center_horizontal"
                    android:background="@drawable/shape_purple_round_corner"
                    android:gravity="center_horizontal"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent">

                </LinearLayout>


            </androidx.constraintlayout.widget.ConstraintLayout>


            <androidx.appcompat.widget.LinearLayoutCompat
                android:id="@+id/product_detail_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </androidx.appcompat.widget.LinearLayoutCompat>
        </androidx.appcompat.widget.LinearLayoutCompat>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</layout>
android kotlin exoplayer
1个回答
0
投票

ExoPlayer 渲染到提供给它的任何 Surface 中。

您可以通过在您使用的 PlayerView 实例上设置 app:surface_type="texture_view" 来解决此问题。在合成方面,TextureView 比 SurfaceView 更像“普通”视图,因此不太容易出现此类问题。也有一些缺点。

阅读TextureView 的优点和缺点

https://exoplayer.dev/ui-components.html#choosing-a-surface-type

© www.soinside.com 2019 - 2024. All rights reserved.