Подтвердить что ты не робот

Видеофрагмент внутри фрагмента вызывает черный экран

У нас есть Android-приложение, работающее на Android API 4.0. В одном из действий есть макет, который делит экран на 2 части. С левой стороны у нас есть статическая часть с некоторыми кнопками. С правой стороны у нас есть FrameLayout, который переключится на соответствующий фрагмент в зависимости от нажатой кнопки.

Проблема: Один из фрагментов с правой стороны содержит VideoView. Когда пользователь нажимает на кнопку, чтобы показать этот фрагмент, фрагмент отображается, и видео сразу же начинает воспроизводиться: при рендеринге этого фрагмента весь экран мерцает в черном, что очень раздражает.

Вот какой код класса VideoFragment:

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

}

Вот макет фрагмента видео:

<?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, мерцание исчезло.

4b9b3361

Ответ 1

Мне удалось исправить это, добавив 0px 0px SurfaceView в макет родительской активности фрагмента:

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

Ответ 2

KennyDs прав, но лучше спрячьте SurfaceView, иначе у вас будет действительно странное поведение, если вы будете анимировать фрагменты, тогда вместо анимированного фрагмента вы не увидите ничего, кроме черного экрана. К счастью, эта проблема с обеспечением также имеет легкое исправление:

<SurfaceView
    android:layout_width="0px"
    android:layout_height="0px"
    android:visibility="gone" />

Ответ 3

Если вам интересно, почему добавление нулевого размера SurfaceView решает проблему, вы можете взглянуть на этот вопрос SurfaceView мигает черным при загрузке. Это хорошо объясняет.

Цитата из ответа Evos

когда представление поверхности появляется в окне в самое первое время, оно запрашивает изменение параметров окна, вызывая частный метод IWindowSession.relayout(..). Этот метод "дает" вам новый кадр, окно и поверхность окна. Я думаю, что в этот момент экран мигает. Решение довольно простое: если у вашего окна уже есть соответствующие параметры, он не обновит все материалы окна, и экран не будет мигать. Самое простое решение - добавить SurfaceView высотой 0px в первый макет вашей деятельности. Это заново воссоздает окно до того, как действие будет показано на экране, а когда вы установите второй макет, он просто продолжит использовать окно с текущими параметрами.

И вот более чистый способ решить эту проблему, вызовите это, прежде чем вы вызовите setContentView(), только что протестированный на моем ViewPager с некоторыми фрагментами, содержащими VideoView, он работает так же хорошо, как добавление SurfaceView с нулевым размером:

getWindow().setFormat(PixelFormat.TRANSLUCENT);

Ответ 4

Просто добавьте прозрачный цвет фона VideoView. Это решит проблему.

android:background="@color/transparent"