Android 和 Exoplayer 中的视图绑定
Posted
技术标签:
【中文标题】Android 和 Exoplayer 中的视图绑定【英文标题】:Viewbinding within Android and Exoplayer 【发布时间】:2021-12-10 09:28:42 【问题描述】:我在我的一个 Fragment 中使用 android Exoplayer。 在 Exoplayer 中,我使用自定义控件布局“@layout/custom_player”作为控件。 我在布局中有不同的元素,例如我有一个按钮元素“optionBtn”,我想从我的 Kotlin 代码连接到 onclicklistener。不幸的是,视图绑定并不顺利。
这是 XML Exoplayer
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerVIew"
app:resize_mode="fill"
android:animateLayoutChanges="true"
app:controller_layout_id="@layout/custom_player"
android:layout_
android:layout_
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
这是 kotlin 代码
...
private var binding: FragmentVideoBinding? = null
private var btnsheetOptions: SheetOptionsBinding? = null
private var sheetDialog: BottomSheetDialog? = null
private var customPlayer: CustomPlayerBinding? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View
btnsheetOptions = SheetOptionsBinding.inflate(inflater, null, false)
sheetDialog = BottomSheetDialog(requireContext(), R.style.BottomSheetDialogTheme)
binding = FragmentVideoBinding.inflate(inflater, container, false)
customPlayer = CustomPlayerBinding.inflate(inflater, binding!!.root, true)
return binding!!.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
val simpleExoPlayer = SimpleExoPlayer.Builder(requireContext()).build()
binding!!.playerVIew.player = simpleExoPlayer
val mediaItem = MediaItem.fromUri(video.toString())
simpleExoPlayer.addMediaItem(mediaItem)
simpleExoPlayer.prepare()
simpleExoPlayer.playWhenReady = true
customPlayer!!.optionBtn.setOnClickListener
...
override fun onDestroy()
super.onDestroy()
binding = null
btnsheetOptions = null
sheetDialog= null
customPlayer = null
...
这种方式布局在彼此之上进行双重膨胀,一种布局与 onclick 监听器一起使用,而另一种则没有,这不是很有用。
有谁知道正确的解决方案,我几乎整个下午都在研究这个问题。
【问题讨论】:
【参考方案1】:您不能将视图绑定与 ExoPlayer 的自定义 HUD 布局一起使用。视图绑定仅适用于专门为活动/片段布局膨胀的布局。自定义 HUD 布局不属于玩家所在的父布局。它以独立的方式充气,不包含在布局中(因此是双充气)。由于自定义布局是膨胀的并且不是原始布局的一部分,因此您不能将视图绑定与其中包含的所有 id 一起使用。
如果视图绑定不适用于自定义布局的按钮,你该怎么办?
您应该使用 findViewById
这是一个属于 Activity 类的函数。
它非常易于使用,我假设您也已经知道如何使用:
findViewById<ImageButton>(R.id.optionBtn).setOnClickListener ...
//The next line is for usage inside a fragment class
activity?.findViewById<ImageButton>(R.id.optionBtn).setOnClickListener ...
确保在布局中为按钮指定 ID,例如:
android:id="@id/optionBtn"
如果您无法找到 (R.id.optionBtn) 怎么办?
这是一个常见问题,有两个R
目录需要注意。
android.R
通常只用作R
。还有应用程序的R
目录。为了区分两者并避免Unresolved reference
问题,您应该以不同的名称导入应用程序的资源,这是在您的类代码开始之前的import
部分完成的,添加以下内容:
import com.example.app.R as appR
然后您可以尝试改用appR.id.optionBtn
。您遇到这个特定的R.id
问题的可能性非常低,但如果发生这种情况,请遵循上面的解决方案。
底线:
1- Viewbinding 仅适用于连接到其上下文类的活动/片段布局,它将父布局的 id 及其所有子视图与实际的绑定变量绑定。
2-如果您想直接访问不属于活动/片段布局的布局,则应改用findViewById
。
3- 如果您在使用“R.id”时遇到问题,您应该以不同的名称导入应用程序的资源。我通常使用“X”而不是“R”。但这都是个人喜好..
【讨论】:
感谢您的回答,您不仅提供了文字和解释,还提供了解决方案。现在很清楚了。再次,非常感谢。【参考方案2】:不应夸大数据绑定,同时还要应用属性app:controller_layout_id
:
customPlayer = CustomPlayerBinding.inflate(inflater, binding!!.root, true)
这两种方式都只能有。
不知何故,这个问题毫无意义,除非提供 custom_player.xml
...因为它可能缺少一些强制性资源 ID,这些资源 ID 应该会存在(“自定义”可能允许的内容存在某些限制,其中可能包括:必须提供某些资源 ID,即使对用户隐藏这些 ID)。 XML 标记在 Android 上非常重要——因为所有代码都针对它运行。 ExoPlayer 支持overriding 布局文件,除非给它们一个不同的名称。
请参考原始布局资源,特别是它们的文件名和resId:https://github.com/google/ExoPlayer/tree/release-v2/library/ui/src/main/res/layout
我假设,当通过文件名覆盖时,也应该可以进行数据绑定。 因为,当只有 include 有数据绑定时,父级仍然无法绑定它。 父布局 XML 需要首先生成数据绑定。
使用.setControllerLayoutId()
,实际上可以在分配View
之前对其进行数据绑定:
customPlayer = CustomPlayerBinding.inflate(inflater, binding!!.root, true)
binding.playerView.setControllerLayoutId(customPlayer!!.root)
在这种情况下,app:controller_layout_id
不得设置。
【讨论】:
我可以通过什么方式在我的 kotlin 代码中绑定这些元素?通常,当我使用“binding!!.playerVIew.optionBtn.setOnClickListener ...”(saveBtn)时,一切都可以正常使用合成。一旦我删除了合成,就无法通过绑定再次绑定该元素。我在 Bindings 中尝试了几种方法,但到目前为止没有运气。我知道我在“包含”中绑定的方式,但使用 Exoplayer 似乎不起作用。以上是关于Android 和 Exoplayer 中的视图绑定的主要内容,如果未能解决你的问题,请参考以下文章
使用 Kotlin 的 Android TV 中的 ExoPlayer
Android TV 中的 ExoPlayer 以纵向模式而不是横向模式播放视频
Android 无法生成视图绑定器 com.sun.tools.javac.code.Symbol$CompletionFailure:
android tv 中的 Exoplayer 不会在直播中重现 (.m3u8) 文件
Android 依赖 'com.google.android.exoplayer:exoplayer' 有不同版本的编译(r2.1.0)和运行时(2.9.1)类路径