Android GLSurfaceView 覆盖其它控件问题 (RK平台)

平台

涉及主控: RK3566

Android: 11/13

问题

在使用GLSurfaceView播放视频的过程中, 增加了一个播放控制面板, 覆盖在视频上方. 默认隐藏setVisibility(View.INVISIBLE);点击屏幕再显示出来. 然而, 在RK3566上这个简单的功能却无法正常工作. 通过缩小视频窗口可以看到, 实际UI是已经展示, 但是被GLSurfaceView 覆盖了.

在Pixel Android 13 上不存在这个问题

如上图 红色 框选区域, 显示不出来.

分析

后续测试发现问题复现需要2个条件:

  1. 覆盖层默认布局设置了隐藏: android:visibility="invisible"
  2. 布局中使用了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();
    }

调用父容器 rlRootrlMenu本身requestLayout 都可以

参考


Android自定义GLSurfaceView
SurfaceView、GLSurfaceView、SurfaceTexture、TextureView简单对比

相关推荐
奋斗的小鹰33 分钟前
Android中使用Glide加载图片闪烁问题
android·glide
Wgllss40 分钟前
金三银四,分享N年前准备的面试真经,可能适用绝大部分人
android·架构·android jetpack
CL_IN42 分钟前
如何将聚水潭·奇门平台数据高效集成到MySQL
android·数据库·mysql
pengyu1 小时前
系统化掌握Flutter组件之Draggable/DragTarget
android·flutter·dart
_祝你今天愉快1 小时前
Android源码学习之开机动画
android·源码
Yang-Never3 小时前
OpenGL ES ->帧缓冲对象(Frame Buffer Object)离屏渲染获取纹理贴图
android·开发语言·kotlin·android studio·贴图
Andy.Zeng3 小时前
Android StrictMode 使用与原理深度解析
android·性能优化·kotlin·代码规范·内存泄漏·strictmode·耗时检测
Andy.Zeng3 小时前
《Android应用性能优化全解析:常见问题与解决方案》
android·性能优化
kfepiza3 小时前
android用java设置button之间的间距 笔记250311
android·java·前端