在Android VideoView上绘制覆盖层(HUD)?

7

我有一个绘制HUD的自定义视图:

HUD

这是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <VideoView
        android:id="@+id/videoView1"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <com.widgets.HUD
            android:id="@+id/hud"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />

</FrameLayout>

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.hud_fragment, container, false);

    frameLayout = (FrameLayout) view.findViewById(R.id.frameLayout);

    hudWidget = (HUD) view.findViewById(R.id.hudWidget);

    videoView = (VideoView) view.findViewById(R.id.videoView1);
    videoView.setVideoURI(Uri.parse("http://88.150.210.138:5001/spor"));
    videoView.start();

    frameLayout.removeView(hudWidget);
    frameLayout.addView(hudWidget);
    hudWidget.bringToFront();

    return view;
}

我在我的VideoView上播放一个RTSP流,当视频开始播放时,它看起来像这样:

Video On HUD

如何强制HUD extends SurfaceViewVideoView的顶部绘制?

项目

  • 我试图将VideoView添加到的项目是DroidPlanner。您可以尝试克隆并查看问题。(需要手动添加VideoView,因为它不在代码库中)。


1
我尝试重现你的问题,但实际上失败了。这是我做的项目: https://github.com/andrask/androidhud 它复制了你用视频视图、按钮和自定义视图创建的相同类型接口。当视频开始播放时,所有元素都保持在顶部,没有发生任何变化。唯一的区别是它不使用片段。你是否尝试过使用单个活动或静态链接片段? - allprog
你能展示给我这个命令的结果吗:adb shell dumpsys SurfaceFlinger? - pierrotlefou
@allprog 我的HUD视图是SurfaceView,也许就是这个原因?你需要将com1文件夹的名称更改为com,这会导致Git在Windows上出现路径问题。 - Danpe
是的,我正在使用 Mac,并尝试尽快组合测试。我会尝试与您的项目玩一下。 - allprog
@Danpe 我向您发送了一个具有可行解决方案的拉取请求。花费了相当多的时间来完成它。 :) - allprog
显示剩余2条评论
5个回答

3
我找到了你问题的答案:VideoView on top of SurfaceView。SurfaceView和VideoView都是表面视图,在旧版安卓中重叠这些视图不被支持,但自2.0版本可用。

你需要做:

  1. 将像素格式设置为TRANSPARENT,以便让视频透过界面闪耀。

hudWidget.getHolder().setFormat(PixelFormat.TRANSPARENT);

  1. 将HUD surface设置为Media Overlay。

hudWidget.setZOrderMediaOverlay(true);

  1. 创建新的surface并将其设置为播放视频的MediaPlayer的显示屏幕。

这里有一个拉取请求,你可以尝试使用这些方法。https://github.com/arthurbenemann/droidplanner/pull/247

提供解决方案的线程:https://groups.google.com/forum/?fromgroups#!msg/android-developers/nDNQcceRnYA/ps9wTBfXIyEJ


你的回答看起来不错!我测试了一下,但是出现了问题,流媒体在播放1-3帧后就卡住了... 你也遇到这个问题了吗?还是你那边可以正常播放? - Danpe
是的,有时候我也会遇到这种情况,因为主线程被阻塞时间太长了。我很高兴现在它能正常工作了。 - allprog

1

从这里可以查看有关FrameLayout的文档:链接

子视图以堆栈方式绘制,最近添加的子视图位于顶部。

在布局文件中为FrameLayout添加一个id。在onCreate(Bundle)中,您将有类似以下内容:

// find your framelayout
frameLayout = (FrameLayout) findViewById(....);

videoView = (VideoView) findViewById(R.id.videoView1);

hudView = (com.widgets.HUD) findViewById(R.id.hud);

在视频开始后,执行以下操作:
frameLayout.removeView(hudView);

frameLayout.addView(hudView);

仍然没有任何进展...我更新了原始项目的链接。 - Danpe

1
创建一个Handler,每50或100毫秒invalidate你的hudView。像这样:
@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.hud_fragment, container, false);

        frameLayout = (FrameLayout) view.findViewById(R.id.frameLayout);

        hudWidget = (HUD) view.findViewById(R.id.hudWidget);

        videoView = (VideoView) view.findViewById(R.id.videoView1);
        videoView.setVideoURI(Uri.parse("http://88.150.210.138:5001/spor"));
        videoView.start();

        frameLayout.removeView(hudWidget);
        frameLayout.addView(hudWidget);
        hudWidget.bringToFront();

        //The Handler which invalidate your (hudWidget) every 50 milliseconds 

        new Handler() {
            public void handleMessage(android.os.Message msg) {
                super.handleMessage(msg);
                hudWidget.invalidate();
                sendEmptyMessageDelayed(0, 50);

            };
        }.sendEmptyMessage(0);

        return view;
    }

还是没有任何进展...我已经更新了原始项目的链接。 - Danpe

0

扩展VideoView并在其构造函数中调用setWillNotDraw(false)。这样,您就可以在onDraw(Canvas)中进行绘制。


0

测试FrameLayout以替换RelativeLayout。

也许它能很好地工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接