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:
And here's a screenshot of the app on Nexus 7 running Android 4.2.2:
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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With