MediaController Positioning - привязка к VideoView

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

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

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

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

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

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

Ответ 1

Я закончил тем, что сделал грязный взлом... я просто привязал представление к моему 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, как предполагалось.

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

Ответ 2

Просто хотел добавить ответ DERIIIFranz. Я использовал тот же метод, чтобы назначить медиа-контроллер виду, которое я хотел, и чтобы функции Hide() и Show() работали правильно, я просто создал свой собственный класс MediaController и переопределил методы Hide() и Show() как свойство isShowing (я делаю это в С# с 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;
    }
}

Ответ 3

Чтобы преобразовать ответ Джонатана Хокмана на 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);
    }