Позиционирование MediaController — привязка к VideoView

Было много дискуссий о том, как позиционировать MediaController, и большинство ответов заключаются в использовании setAnchorView-метода. На первый взгляд кажется, что это решение работает, но в моем случае это не так.

В соответствии с этим Post setAnchorView действует только как ссылка для начального позиционирования MediaController, но фактически создает новый плавающий Window сверху .

Итак, что мне нужно, так это MediaController, который действительно привязан к родительскому элементу View (например, VideoView).

Например, если у вас есть LinearLayout внутри ScrollView, и вам нужно прокрутить вниз до VideoView, к которому присоединен MediaController, MediaController действительно должен быть присоединен к этому VideoView, чтобы MediaController прокручивался вместе с VideoView.

Другой вариант использования, в котором возникает эта проблема, обсуждается здесь, где MediaController используется внутри ViewPager.

Итак, как добиться такого поведения для MediaController?


person FranBran    schedule 25.03.2014    source источник


Ответы (3)


В итоге я сделал грязный взлом... я просто вручную прикрепил представление к моему videoView, чтобы добиться желаемого поведения:

public void onPrepared(MediaPlayer mp) {

                MediaController mc = new MediaController(videoView.getContext(), false);
                // set correct height
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) videoView.getLayoutParams();
                params.height =  mp.getVideoHeight();
                videoView.setLayoutParams(params);

                videoView.setMediaController(mc);
                pBar.setVisibility(View.GONE);
                mc.show(0);

                FrameLayout f = (FrameLayout) mc.getParent();
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                        RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
                lp.addRule(RelativeLayout.ALIGN_BOTTOM, videoView.getId());

                ((LinearLayout) f.getParent()).removeView(f);
                ((RelativeLayout) videoView.getParent()).addView(f, lp);

                mc.setAnchorView(videoView);
            }

проблема с этим решением заключается в том, что настройка anchorView не имеет никакого эффекта, и поэтому нажатие на VideoView не скрывает/не показывает MediaController, как предполагалось.

Там определенно есть гораздо лучшее решение, и, надеюсь, кто-то может дать мне подсказку!

person FranBran    schedule 02.04.2014
comment
фантастически, это спасло мой день. - person Rohit Mandiwal; 06.06.2015

Просто хотел добавить к ответу DERIIIFranz. Я использовал тот же метод, чтобы назначить медиа-контроллер тому представлению, которое хотел, и чтобы функции Hide() и Show() работали правильно. Я просто создал свой собственный класс MediaController и переопределил методы Hide() и Show(). как свойство isShowing (я делаю это на C# с Xamarin, поэтому не знаю, какие проблемы у вас могут возникнуть с Java).

Я также добавил свой собственный прослушиватель кликов в VideoView, чтобы убедиться, что я могу сам обрабатывать события Hide() и Show().

public class MyMediaController : MediaController
{
    private bool _isShowing { get; set; } = false;
    public override bool IsShowing { get { return _isShowing; } }

    public override void Show ()
    {
        base.Show();
        _isShowing = true;

        Native.ViewGroup parent = ((Native.ViewGroup)this.Parent);
        parent.Visibility = Native.ViewStates.Visible;
    }

    public override void Hide ()
    {
        base.Hide();
        _isShowing = false;

        Native.ViewGroup parent = ((Native.ViewGroup)this.Parent);
        parent.Visibility = Native.ViewStates.Gone;
    }
}
person Jonathan Hockman    schedule 30.09.2015
comment
На всякий случай это поможет кому-то еще: поскольку я переопределил MediaController, я получил InvocationException, когда действие завершилось или если видеопросмотр был удален, так как мне нужно было вызвать MediaPlayer.Release(). Чтобы избежать этого, убедитесь, что вы вызываете super.Hide() и super.Show() в своих собственных методах Hide и Show. Несмотря на то, что в этом случае они не имеют визуального эффекта, в базовом классе все еще есть вещи, на которые это влияет. - person Jonathan Hockman; 02.10.2015

Чтобы преобразовать ответ Джонатана Хокмана на Java и добавить его в ответ DERIIIFranz:

public class MyMediaController extends MediaController {

        public MyMediaController(Context context) {
                super(context);
        }

        public MyMediaController(Context context, boolean useFastForward) {
                super (context, useFastForward);
        }

        public MyMediaController(Context context, AttributeSet attrs) {
                super(context, attrs);
        }

        private boolean _isShowing = false;

        @Override
        public boolean isShowing() { return _isShowing; }

        @Override
        public void show() {
                super.show();
                _isShowing = true;

                ViewGroup parent = (ViewGroup) this.getParent();
                parent.setVisibility(View.VISIBLE);
        }

        @Override
        public void hide() {
                super.hide();
                _isShowing = false;

                ViewGroup parent = (ViewGroup) this.getParent();
                parent.setVisibility(View.GONE);
        }
}

Для просмотра видео:

    public void onPrepared(MediaPlayer mediaPlayer) {
            MyMediaController mediaController = new MyMediaController(videoView.getContext(), false);

            RelativeLayout parentLayout = (RelativeLayout) videoView.getParent();
            RelativeLayout.LayoutParams parentParams = (RelativeLayout.LayoutParams) parentLayout.getLayoutParams();
            parentParams.height = this.getHeight();
            parentLayout.setLayoutParams(parentParams);

            FrameLayout frameLayout = (FrameLayout) mediaController.getParent();
            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, this.getId());

            ((ViewGroup)frameLayout.getParent()).removeView(frameLayout);
            parentLayout.addView(frameLayout, layoutParams);

            mediaController.setAnchorView(this);
            mediaController.hide();

            videoView.setMediaController(mediaController);
    }
person TTransmit    schedule 18.08.2016