SurfaceView 之上的 VideoView

Posted

技术标签:

【中文标题】SurfaceView 之上的 VideoView【英文标题】:VideoView on top of SurfaceView 【发布时间】:2011-07-22 22:56:25 【问题描述】:

我尝试在SurfaceView 之上显示VideoView。但它不可见,但会在点击时做出反应(MediaController 出现并播放声音)。视频似乎在SurfaceView 后面播放,所以我也尝试使用setZOrderMediaOverlay() 和/或setZOrderOnTop(),但没有任何改变

当我转到主屏幕时,我看到 VideoView 在淡入淡出的动画中有一瞬间,所以它确实存在。

我尝试使用 xml 布局,也完全以编程方式尝试,但没有任何效果。

这是我的活动:

public class VideoTest extends Activity 
    private RelativeLayout mLayout;
    private VideoView mVideo;
    private Handler mHandler;
    private FrameLayout mFrameLayout;
    private SurfaceView mSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        mFrameLayout = new FrameLayout(this);
        mFrameLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

        mLayout = new RelativeLayout(this);
        mLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        mVideo = new VideoView(this);
        mVideo.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mSurfaceView = new SurfaceView(this);
        mSurfaceView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

        mSurfaceView.setZOrderMediaOverlay(false);
        mSurfaceView.setZOrderOnTop(false);

        mFrameLayout.addView(mSurfaceView);
        mLayout.addView(mVideo);
        mFrameLayout.addView(mLayout);

        setContentView(mFrameLayout);

        // with xml
//        setContentView(R.layout.main);
//        mFrameLayout = (FrameLayout) findViewById(R.id.activity_reader);
//        mLayout = (RelativeLayout) findViewById(R.id.videoview);
//        mVideo = (VideoView) findViewById(R.id.video_view);
//        mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);

        // Set the handler to me messaged from the threads
        mHandler = new Handler() 
            @Override
            public void handleMessage(Message msg) 
                if (msg != null) 
                    mVideo.setMediaController(new MediaController(mVideo.getContext()));
                    mVideo.setVideoPath("/mnt/sdcard/myvideo.mp4");
                    if (mLayout.getVisibility() == View.VISIBLE) 
                        mLayout.setVisibility(View.GONE);
                     else 
                        mLayout.setVisibility(View.VISIBLE);
                    
//                    mFrameLayout.bringChildToFront(mLayout);
//                    mFrameLayout.bringChildToFront(mVideo);
//                    mFrameLayout.requestLayout();
//                    mFrameLayout.invalidate();
//                    mFrameLayout.postInvalidate();
//                    mVideo.requestFocus();
                
                super.handleMessage(msg);
            
        ;
    

    /** Inflate the menu */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.activity_reader_menu, menu);
            return true;
    

    /** Handle menu items events */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        switch (item.getItemId()) 
            case R.id.toggle_video:
                new Thread() 
                    public void run() 
                        mHandler.sendEmptyMessage(0);
                    ;
                .start();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        
    

我的 xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_reader"
    android:layout_
    android:layout_>
    <SurfaceView android:id="@+id/surface_view"
        android:layout_
        android:layout_ />
    <RelativeLayout android:id="@+id/videoview"
        android:layout_
        android:layout_
        android:visibility="gone">
        <VideoView android:id="@+id/video_view"
            android:layout_
            android:layout_ />
    </RelativeLayout>
</FrameLayout>

一个提示:由于这只是一个测试以找出它为什么不起作用,我试图最小化我的实际应用程序中的代码,其中VideoView 的可见性由一个处理程序控制,该处理程序从SurfaceView 的绘图线程。这就是为什么我在使用菜单时实现了一个线程发送消息的原因。

【问题讨论】:

【参考方案1】:

我不认为你可以有重叠的SurfaceViews,根据Android框架工程师回答的this thread:

抱歉,您不能这样做——因为 表面视图很特别 真正的意见(表面是一个 单独的窗口 Z 排序与您的 自己),它们的 Z 排序不匹配 你的意见。表面视图很大, 重物;你不打算 将 SurfaceView 视为常规视图 以这种方式。

【讨论】:

但我让它在特殊情况下工作。在我的真实应用程序中,我可以使用对话框主题调用另一个活动,并且 VideoView 立即位于顶部并保持在那里,即使我关闭顶部的活动也是如此。所以它以某种方式工作,但我无法控制它......无论如何,谢谢你的链接! 看起来我需要在我拥有的surfaceview上实现我自己的视频播放器......或者在API演示中找到这个:developer.android.com/resources/samples/ApiDemos/src/com/… @WarrenFaith 嘿,很久以前,但也许你回来了:我认为当你显示视频视图时隐藏表面视图时它会起作用,反之亦然!?谢谢! 遗憾的是,由于视频从未全屏显示,因此别无选择。所以我总是看到它背后的SurfaceView内容。 重叠的表面视图可以使用这篇文章的答案:***.com/questions/18358852/…。我自己为视频应用做这个,效果很好。

以上是关于SurfaceView 之上的 VideoView的主要内容,如果未能解决你的问题,请参考以下文章

android videoview和surfaceview的区别

android videoview和surfaceview的区别

放置在 SurfaceView 上时,VideoView 在 FrameLayout 中不可见

Android多媒体功能开发——使用VideoView控件播放视频

TextureView/SurfaceView/GLSurfaceView/VideoView渲染视频(点播播放器)

android java中的圆角videoview