平台
涉及主控: RK3566
Android: 11/13
问题
在使用GLSurfaceView播放视频的过程中, 增加了一个播放控制面板, 覆盖在视频上方. 默认隐藏setVisibility(View.INVISIBLE);
点击屏幕再显示出来. 然而, 在RK3566上这个简单的功能却无法正常工作. 通过缩小视频窗口可以看到, 实际UI是已经展示, 但是被GLSurfaceView 覆盖了.
在Pixel Android 13 上不存在这个问题
如上图 红色 框选区域, 显示不出来.
分析
后续测试发现问题复现需要2个条件:
- 覆盖层默认布局设置了隐藏:
android:visibility="invisible"
- 布局中使用了SurfaceView / GLSurfaceView
参考代码:
布局
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:id="@+id/rlRoot">
<RelativeLayout android:id="@+id/rlScreen"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout android:id="@+id/rlMenu"
android:layout_width="480dp"
android:layout_height="320dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="100dp"
android:visibility="invisible"
android:background="@drawable/selector_beauty_window_bg">
<TextView
android:text="Overlay Menu"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</RelativeLayout>
Activity文件
java
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.ansondroider.acore.BaseActivity;
import com.ansondroider.acore.media.VideoPlayer;
import com.ansondroider.apitester.gl.GLVideoView;
import java.io.IOException;
public class GlMenuOverlay extends BaseActivity {
MediaPlayer mmp;
GLVideoView glView;
RelativeLayout rlScreen;
RelativeLayout rlMenu;
boolean playVideo = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_gl_menu_overlay);
findViewById(R.id.rlRoot).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showOrHideMenu();
}
});
rlScreen = (RelativeLayout) findViewById(R.id.rlScreen);
rlMenu = (RelativeLayout) findViewById(R.id.rlMenu);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
if(playVideo) {
glView = new GLVideoView(this);
rlScreen.addView(glView, lp);
}
/*ImageView iv = new ImageView(this);
iv.setImageResource(R.mipmap.ic_launcher);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
rlScreen.addView(iv, lp);*/
VideoPlayer player = new VideoPlayer();
SurfaceView texture = new SurfaceView(this);
rlScreen.addView(texture, lp);
player.setDisplay(texture);
player.setDataSource("/sdcard/Movies/10012271.mp4");
player.play();
}
void showOrHideMenu(){
Log.d(TAG, "showOrHideMenu");
rlMenu.setVisibility(rlMenu.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
}
@Override
protected void onStart() {
super.onStart();
if(playVideo) {
mmp = new MediaPlayer();
try {
mmp.setDataSource("/sdcard/Movies/10012271.mp4");
mmp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
glView.onVideoPrepared(mediaPlayer);
}
});
mmp.prepare();
mmp.setLooping(true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
protected void onStop() {
super.onStop();
if(mmp != null){
mmp.stop();
mmp.release();
}
}
}
解决
在需要展示覆盖层的时候调用一次requestLayout
, 比如:
java
void showOrHideMenu(){
Log.d(TAG, "showOrHideMenu");
rlMenu.setVisibility(rlMenu.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
//
//((RelativeLayout)findViewById(R.id.rlRoot)).requestLayout();
rlMenu.requestLayout();
}
调用父容器 rlRoot 或 rlMenu本身 的requestLayout
都可以
参考
Android自定义GLSurfaceView
SurfaceView、GLSurfaceView、SurfaceTexture、TextureView简单对比