在Fragment中定位MediaController

dum*_*azy 6 android android-mediaplayer android-view

我注意到有关的位置有问题MediaControllerVideoView内部Fragment.以下是运行Android 4.3的Nexus 7的外观截图: 在4.3上使用MediaController的应用程序的屏幕截图

这是运行Android 4.2.2的Nexus 7上应用程序的屏幕截图: 在此输入图像描述

正如您所看到的,MediaController的位置位于我的API 17或更低版​​本的活动中间(在另一个平板电脑上测试4.1.2).我注意到MediaController的大小是正确的.

My Fragment显示在FrameLayout中,其宽度由其权重(此处为0.6)定义,因此不是特定的dpi值.

我已经检查了Grepcode上的MediaController的源代码,并将4.3中的一个与4.2.2的代码进行了比较,并且LayoutParams有一些小的变化,但我找不到一种方法来使这个工作.

我在我的片段的onActivityCreated()中初始化我的VideoView和MediaController

mMediaController = new MediaController(getActivity());
mMediaController.setAnchorView(videoView);
videoView.setMediaController(mMediaController);
Run Code Online (Sandbox Code Playgroud)

有人知道我怎么能正确定位吗?

Rig*_*rod 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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

使用安卓4.0测试。