Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

position MediaController inside a Fragment

I've noticed a problem concerning the position of a MediaController for a VideoView inside a Fragment. Here's a screenshot of how it looks on Nexus 7 running Android 4.3: Screenshot of app with MediaController on 4.3

And here's a screenshot of the app on Nexus 7 running Android 4.2.2: enter image description here

As you can see, the position of the MediaController is in the middle of my Activity on API 17 or lower (tested on another tablet with 4.1.2 as well). I've noticed that the size of the MediaController is correct.

My Fragment is shown in a FrameLayout whose width is defined by it's weight (0.6 here), so not by a specific dpi value.

I've checked the source code of MediaController on Grepcode and compared the one of 4.3 with the code of 4.2.2 and there are some small changes with the LayoutParams, but I can't find a way to make this work.

I initialize my VideoView and MediaController in the onActivityCreated() of my Fragment

mMediaController = new MediaController(getActivity());
mMediaController.setAnchorView(videoView);
videoView.setMediaController(mMediaController);

Does somebody know how I can position it right?

like image 418
dumazy Avatar asked Oct 09 '13 11:10

dumazy


People also ask

How does the mediacontroller work?

The MediaController will then provide a set of controls allowing the user to manage the playback (such as pausing and seeking backwards/forwards in the video timeline). The position of the controls is designated by anchoring the controller instance to a specific view in the user interface layout.

How do I put a videoview on top of a fragment?

As is the case with most Views, when adding a Fragment on top of another, the top Fragment will have its Views drawn on top of the bottom Fragment. This however, is not the case when it comes to VideoViews, which require you to call `videoView.setZOrderMediaOverlay(true)` on the VideoView you would like to appear on top.

What is setmediacontroller in Android?

setMediaController (MediaController) – Designates a MediaController instance allowing playback controls to be displayed to the user. Introducing the Android MediaController Class If a video is simply played using the VideoView class, the user will not be given any control over the playback, which will run until the end of the video is reached.

What is a fragment in Android?

In Android, the fragment is the part of Activity that represents a portion of the User Interface (UI) on the screen. It is the modular section of the android activity that is very helpful in creating UI designs that are flexible in nature and auto-adjustable based on the device screen size.


1 Answers

First of all, we will need custom MediaController to alter it's weird behaviour in android prior 4.3

class CustomMediaController extends MediaController
{

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

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

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

    @Override
    public void show(int timeout) {
        super.show(timeout);
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (currentapiVersion < 18) //android.os.Build.VERSION_CODES.JELLY_BEAN_MR2
        {
            try {
                Field field1 = MediaController.class.getDeclaredField("mAnchor");
                field1.setAccessible(true);
                View mAnchor = (View)field1.get(controller);

                Field field2 = MediaController.class.getDeclaredField("mDecor");
                field2.setAccessible(true);
                View mDecor = (View)field2.get(controller);

                Field field3 = MediaController.class.getDeclaredField("mDecorLayoutParams");
                field3.setAccessible(true);
                WindowManager.LayoutParams mDecorLayoutParams = (WindowManager.LayoutParams)field3.get(controller);

                Field field4 = MediaController.class.getDeclaredField("mWindowManager");
                field4.setAccessible(true);
                WindowManager mWindowManager = (WindowManager)field4.get(controller);

                int [] anchorPos = new int[2];
                mAnchor.getLocationOnScreen(anchorPos);

                // we need to know the size of the controller so we can properly position it
                // within its space
                mDecor.measure(MeasureSpec.makeMeasureSpec(mAnchor.getWidth(), MeasureSpec.AT_MOST),
                                MeasureSpec.makeMeasureSpec(mAnchor.getHeight(), MeasureSpec.AT_MOST));

                WindowManager.LayoutParams p = mDecorLayoutParams;
                p.width = mAnchor.getWidth();
                p.x = anchorPos[0] + (mAnchor.getWidth() - p.width) / 2;
                p.y = anchorPos[1] + mAnchor.getHeight() - mDecor.getMeasuredHeight();
                mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);

            } catch (Exception e) {
                    e.printStackTrace();
            }
        }
    }
}

Then just replace MediaController in variable declaration with CustomMediaController and everything will do. The reason is android code prior to 4.3 was bugged. We're using reflection to correct position in show() method.

Tested with android 4.0.

like image 158
Rigeborod Avatar answered Nov 01 '22 12:11

Rigeborod