Frage

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.

War es hilfreich?

Lösung

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" />

Andere Tipps

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" />

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

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

android:background="@color/transparent"
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top