关于android:片段内的VideoView导致黑屏闪烁

VideoView inside fragment causes black screen flicking

我们有一个在Android API 4.0上运行的Android应用程序。其中一项活动的布局将屏幕分为两部分。在左侧,我们有一些静态按钮。在右侧,我们有一个FrameLayout,它将根据所按下的按钮切换到相应的片段。

问题:
右侧的片段之一包含VideoView。当用户单击按钮以显示该片段时,将显示该片段,然后视频立即开始播放:渲染该片段后,整个屏幕会以黑色闪烁,这非常令人讨厌。

这是VideoFragment类的一些代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class VideoFragment extends Fragment {

    public VideoView videoView;

    private ExternalVideo mVideo;
    private boolean mVideoExists;
    private String mDestination;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDestination = ApplicationParams.MEDIA_STORAGE_PATH +"videos/"
                + FilenameUtils.getBaseName(((DetailActivity)getActivity()).getProduct().getVideoUrl())
                +"."
                + FilenameUtils.getExtension(((DetailActivity) getActivity()).getProduct().getVideoUrl());

        File file = new File(mDestination);
        mVideoExists = file.exists() && file.isFile();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view;

        if (mVideoExists) {
            getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT);
            view = inflater.inflate(R.layout.video, null);
            mVideo = new ExternalVideo(mDestination);

            videoView = (VideoView) view.findViewById(R.id.video_video);

            MediaController mediaController = new MediaController(getActivity());
            mediaController.setAnchorView(videoView);

            videoView.setMediaController(mediaController);
            videoView.setVideoPath(mVideo.getFullPath());
            videoView.requestFocus();
            videoView.setVisibility(View.VISIBLE);

            videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                public void onPrepared(MediaPlayer mp) {
                    videoView.start();

                }
            });
        } else {
            TextView textView = new TextView(getActivity());
            textView.setText(getActivity().getString(R.string.videofragment_video_coming_soon));
            textView.setPadding(50, 50, 50, 50);
            view = textView;
        }

        return view;
    }

}

这是视频片段的布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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">
    <VideoView android:id="@+id/video_video"
               android:layout_width="fill_parent"
               android:layout_alignParentRight="true"
               android:layout_alignParentLeft="true"
               android:layout_alignParentTop="true"
               android:layout_alignParentBottom="true"
               android:layout_height="fill_parent"/>
</RelativeLayout>

有谁知道渲染包含VideoView的片段时会导致此闪烁问题的原因?一个解决方案将不胜感激!

EDIT1:如果我单击VideoView在屏幕上的片段,开始时会闪烁。然后,当我导航到注释片段并返回到包含VideoView的片段时,闪烁消失了。


我可以通过在片段的父活动的布局中添加一个0px x 0px SurfaceView来解决此问题:

1
2
3
<SurfaceView
        android:layout_width="0px"
        android:layout_height="0px" />


KennyDs是正确的,但是最好确保隐藏SurfaceView,否则,如果给片段设置动画,您将有真正的怪异行为,那么除了动画片段之外,您只会看到黑屏。 幸运的是,这个附带问题也很容易解决:

1
2
3
4
<SurfaceView
    android:layout_width="0px"
    android:layout_height="0px"
    android:visibility="gone" />


如果您想知道为什么添加大小为零的SurfaceView可以解决此问题,可以看看这个问题SurfaceView在加载时呈黑色闪烁。 它很好地解释了。

引自Evos的答案

when the surface view appears in the window the very fist time, it requests the window's parameters changing by calling a private IWindowSession.relayout(..) method. This method"gives" you a new frame, window, and window surface. I think the screen blinks right at that moment.The solution is pretty simple: if your window already has appropriate parameters it will not refresh all the window's stuff and the screen will not blink. The simplest solution is to add a 0px height plain SurfaceView to the first layout of your activity. This will recreate the window before the activity is shown on the screen, and when you set your second layout it will just continue using the window with the current parameters.

这是解决此问题的一种更干净的方法,请在调用setContentView()之前先调用此方法,该方法刚刚在我的ViewPager上进行了测试,并带有一些包含VideoView的Fragments,它的作用与添加零尺寸的SurfaceView一样好:

1
getWindow().setFormat(PixelFormat.TRANSLUCENT);


只需添加VideoView的透明背景色。 它将解决问题。

1
android:background="@color/transparent"