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简单对比

相关推荐
jiet_h4 小时前
Android Kotlin 算法详解:链表相关
android·算法·kotlin
@老蝴5 小时前
C语言 — 动态内存管理
android·c语言·开发语言
每次的天空7 小时前
Android第十一次面试flutter篇
android·flutter·面试
renxhui9 小时前
Android 性能优化(四):卡顿优化
android·性能优化
二流小码农9 小时前
鸿蒙开发:UI界面分析利器ArkUI Inspector
android·ios·harmonyos
CYRUS_STUDIO9 小时前
FART 精准脱壳:通过配置文件控制脱壳节奏与范围
android·安全·逆向
小疯仔9 小时前
使用el-input数字校验,输入汉字之后校验取消不掉
android·开发语言·javascript
墨狂之逸才10 小时前
Data Binding Conversion 详解
android
iceBin10 小时前
uniapp打包安卓App热更新,及提示下载安装
android·前端
杨充10 小时前
高性能图片优化方案
android