22

We have an Android application running on Android API 4.0. One of the activities has a layout that divides the screen in 2 parts. On the left side we have a static part with some buttons. On the right side we have a FrameLayout that will switch to the corresponding fragment depending on the button that is pressed.

Problem: One of the fragments on the right side contains a VideoView. When the user clicks on the button to show this fragment the fragment is shown and the video immediately starts playing however: upon rendering this fragment the complete screen flickers in black which is very annoying.

Here is some code of the VideoFragment class:

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;
    }

}

Here is the layout of the video fragment:

<?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>

Does anyone have an idea what could be causing this flickering issue upon rendering the fragment that contains the VideoView? A solution would be appreciated!

EDIT1: If I click on the fragment where the VideoView is on the screen flickers in the beginning. When I then navigate to anoter fragment and go back to the one containing the VideoView the flicker is gone.

Kenny
  • 5,350
  • 7
  • 29
  • 43
  • Did you run your application in emulator ? – Tugrul Jul 18 '13 at 08:04
  • Running the application on a Samsung Galaxy Tab 2 10.1 tablet – Kenny Jul 18 '13 at 08:14
  • Try `setAnchorView(videoView)` on your `MediaController` http://developer.android.com/reference/android/widget/MediaController.html – Ken Wolf Jul 18 '13 at 08:19
  • @KenWolf Tried it and the flicking still persists. – Kenny Jul 18 '13 at 08:28
  • That code works perfect now. http://stackoverflow.com/questions/17697670/android-does-not-display-m3u8-format-in-videoview-only-sound – Tugrul Jul 18 '13 at 08:29
  • Hmm, I can't see really anything wrong with what you've posted. I have apps that render VideoViews in fragments much like you describe without any problem. I would see if I could test on a different device or alternatively, post your fragment code/layout too. – Ken Wolf Jul 18 '13 at 08:31
  • @KenWolf Same problem on a Samsung Galaxy Tab 10.1. I have updated my question with the complete VideoFragment class. – Kenny Jul 18 '13 at 08:37
  • OK, last guess and I'll stop hogging the comments :) Try removing the following 3 lines: `getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT);` `videoView.requestFocus();` and `videoView.setVisibility(View.VISIBLE);` – Ken Wolf Jul 18 '13 at 08:45
  • @KenWolf Same problem still persists :( – Kenny Jul 18 '13 at 09:42
  • Added Edit1 to the question – Kenny Jul 18 '13 at 10:34

4 Answers4

44

I was able to fix this by adding a 0px by 0px SurfaceView in the layout of the parent activity of the fragment:

<SurfaceView
        android:layout_width="0px"
        android:layout_height="0px" />
Kenny
  • 5,350
  • 7
  • 29
  • 43
13

KennyDs is right, but better be sure to hide the SurfaceView, otherwise you'll have really weird behavior if you animate fragments, then you won't see anything but black screen in the place of the animated fragment. Fortunately this collateral issue has a easy fix too:

<SurfaceView
    android:layout_width="0px"
    android:layout_height="0px"
    android:visibility="gone" />
David
  • 623
  • 7
  • 16
4

If you wonder why adding a zero sized SurfaceView solves the problem, you can take a look at this question SurfaceView flashes black on load. It explains well.

Quoted from Evos's answer

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.

And here is a cleaner way to solve this problem, call this before you call setContentView(), just tested on my ViewPager with some Fragments containing VideoView, it works as good as adding zero-sized SurfaceView:

getWindow().setFormat(PixelFormat.TRANSLUCENT);
Community
  • 1
  • 1
Xavier Lin
  • 328
  • 2
  • 7
-4

Just add transparent background color of VideoView. It will solve the problem.

android:background="@color/transparent"
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Rohail
  • 21
  • 1
  • 4