我正在使用他们的 Android SDK 开发 Bitmovin 播放器的 React Native 实现。在这个阶段,我不确定这对 Bitmovin 播放器有多具体,但由于他们现阶段不正式支持 React Native,所以我想先在 SO 上询问这个问题。这是一个带有自定义视图的 React Native UI 组件,使用布局文件。我试图在播放器视图之上呈现一个字幕视图,并且我的布局基于 Bitmovin 的简单示例。事实上,我已经进一步简化了布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.bitmovin.player.PlayerView
android:id="@+id/bitmovinPlayerView"
app:shutter_background_color="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bootsplash_background">
<com.bitmovin.player.SubtitleView
android:id="@+id/bitmovinSubtitleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foregroundGravity="center" />
</com.bitmovin.player.PlayerView>
</LinearLayout>
这会在屏幕顶部显示 SubtitleView。到目前为止,我没有尝试过在屏幕底部以更常见的位置呈现 SubtitleView。据我所知,我已经对所有这些元素的每一个参数进行了试验。这是初始化视图的代码:
public void init() {
inflate(context, R.layout.player_container, this);
StyleConfig styleConfig = new StyleConfig();
styleConfig.setUiEnabled(false);
PlayerConfig playerConfig = new PlayerConfig();
playerConfig.setStyleConfig(styleConfig);
playerView = findViewById(R.id.bitmovinPlayerView);
player = Player.create(context, playerConfig);
playerView.setPlayer(player);
player.on(SourceEvent.Loaded.class, this::onLoad);
player.on(PlayerEvent.Playing.class, this::onPlay);
player.on(PlayerEvent.Paused.class, this::onPause);
player.on(PlayerEvent.Seek.class, this::onSeek);
player.on(PlayerEvent.TimeChanged.class, this::onTimeChanged);
player.on(PlayerEvent.Destroy.class, this::onDestroy);
player.on(PlayerEvent.Seeked.class, this::onSeeked);
player.on(PlayerEvent.PlaybackFinished.class, this::onPlaybackFinished);
player.on(PlayerEvent.Ready.class, this::onReady);
player.on(SourceEvent.Error.class, this::onError);
player.on(SourceEvent.SubtitleChanged.class, this::onSubtitleChanged);
player.on(PlayerEvent.Error.class, this::onError);
subtitleView = findViewById(R.id.bitmovinSubtitleView);
subtitleView.setPlayer(player);
player.setVolume(100);
}
我读过 React Native 为 UI 组件的顶级视图设置样式,所以这是我现阶段唯一的线索。但是我不确定如何回复该信息...
编辑:问题可能是在 React Native 中动态更新 Android 中的视图布局并不简单。这已在此处详细讨论。
编辑 2:我试图监听全局布局更改,这是针对视图布局问题提出的解决方法之一:
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
requestLayout();
}
});
这按预期调用,但对 subtitleView 没有影响,它仍然显示在播放器的顶部,这似乎是因为它的高度为 0。
编辑 3:另一个对我不起作用的建议解决方案:
private void setupLayoutHack() {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
manuallyLayoutChildren();
getViewTreeObserver().dispatchOnGlobalLayout();
Choreographer.getInstance().postFrameCallback(this);
}
});
}
private void manuallyLayoutChildren() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
}
我在构造函数中调用了 setupLayoutHack() 但在应用这些更改后也没有看到任何区别:(
编辑 4:我修复 SubtitleView 布局的最后一次尝试是尝试以各种方式进行测量和布局:
private void refreshViewChildrenLayout(View view){
view.measure(
View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
但是,在我尝试的所有情况下,高度都是 0,这意味着没有任何改变。上面的 RN 问题中提到了一个解决方案,建议应该覆盖字幕视图的阴影节点。因此,一种前进的方式可能是构建一个包含该内容的新字幕视图。
然而,在这个阶段,在我看来,在 React Native 中响应字幕提示并在那里执行所有显示和样式设置似乎是一种更简单的方法。
(还有一个较小的问题是如何使文本两侧的背景透明,但在此阶段布局问题更为重要)。