MediaController Positioning - bind to VideoView
Asked Answered
S

3

11

There have been a lot of discussions about how to position a MediaController and most answers are to use the setAnchorView-Method. At the first glance this solution seems to work but in my case it doesn't.

According to this Post setAnchorView only acts as a reference for initial positioning of the MediaController, but actually creates a new floating Window on top.

So what I want is a MediaController that is really bound to a parent View (e.g. VideoView).

For example if you have a LinearLayout within a ScrollView and you have to scroll down to your VideoView where the MediaController is attached to, the MediaController should really be attached to this VideoView so that the MediaController scrolls along with the VideoView.

Another Use-Case where this problem accurs is discussed here, where the MediaController is used within a ViewPager.

So how to achieve such a behavior for a MediaController?

Sigil answered 25/3, 2014 at 14:23 Comment(0)
S
9

I ended up by doing a dirty hack... i just manually attached the view to my videoView to achieve the wanted behavior:

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

the problem with this solution is, that setting the anchorView doesn't have any effect and therefore tapping on the VideoView doesn't hide/show the MediaController as it's supposed to.

There definitly is a much better solution and hopefully someone can give me a hint!

Sigil answered 2/4, 2014 at 19:36 Comment(0)
R
1

Just wanted to add to DERIIIFranz's answer. I used the same method to assign the media controller to the view I wanted and to get the Hide() and Show() functions to work properly I simply made my own MediaController class and overrode the Hide() and Show() methods as well as the isShowing property (I'm doing this in C# with Xamarin, so I don't know what issues you would have with Java).

I also added my own click listener on the VideoView to ensure that I could handle the Hide() and Show() events myself.

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;
    }
}
Rustler answered 30/9, 2015 at 16:30 Comment(1)
Just in case this helps anyone else: Since I overrode the MediaController I was getting an InvocationException when the activity finished or if the videoview was removed since I needed to call MediaPlayer.Release(). In order to avoid that make sure you call super.Hide() and super.Show() in your own Hide and Show methods. Even though they have no visual affect in this case there are still things in the underlying class that are affected.Rustler
P
1

To convert Jonathan Hockman's answer to Java and add it to DERIIIFranz's answer:

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

For the videoView:

    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);
    }
Psychedelic answered 18/8, 2016 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.