6

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?

4

1 回答 1

2

首先,我们需要自定义 MediaController 来改变它在 android 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();
            }
        }
    }
}

然后只需将变量声明中的 MediaController 替换为 CustomMediaController 就可以了。原因是 4.3 之前的 android 代码被窃听。我们正在使用反射来纠正show()方法中的位置。

用安卓4.0测试。

于 2014-04-01T12:43:50.867 回答