Android自定义音量弹窗

GitHub地址:https://github.com/lyric315/CustomVolueAdjust

定义

CustomVolueAdjust是一个Android自定义音量弹窗Demo,当用户按下音量按键后,将系统音量弹窗替换为我们自定义的音量弹窗。

原理

Android系统音量按键的控制逻辑在PhoneWindow类中

//PhoneWindow的onKeyDown用于方法处理音量按键
protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) {
    final KeyEvent.DispatcherState dispatcher =
            mDecor != null ? mDecor.getKeyDispatcherState() : null;
    //Log.i(TAG, "Key down: repeat=" + event.getRepeatCount()
    //        + " flags=0x" + Integer.toHexString(event.getFlags()));
    switch (keyCode) {
        case KeyEvent.KEYCODE_VOLUME_UP://调大音量
        case KeyEvent.KEYCODE_VOLUME_DOWN://调小音量
        case KeyEvent.KEYCODE_VOLUME_MUTE: {
            if (mMediaController != null) {
                int direction = 0;
                switch (keyCode) {
                    case KeyEvent.KEYCODE_VOLUME_UP:
                        direction = AudioManager.ADJUST_RAISE;
                        break;
                    case KeyEvent.KEYCODE_VOLUME_DOWN:
                        direction = AudioManager.ADJUST_LOWER;
                        break;
                    case KeyEvent.KEYCODE_VOLUME_MUTE:
                        direction = AudioManager.ADJUST_TOGGLE_MUTE;
                        break;
                }
                mMediaController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
            } else {
                MediaSessionLegacyHelper.getHelper(getContext()).sendVolumeKeyEvent(
                        event, mVolumeControlStreamType, false);
            }
            return true;
        }
        case KeyEvent.KEYCODE_MEDIA_PLAY:
        ...
    }

    return false;
}

因此,我们wrapper了window的callback事件:

Window window = activity.getWindow();
Window.Callback wrapped = window.getCallback();
window.setCallback(wrapperWindowCallback(wrapped));

在WindowCallbackWrapper中拦截了dispatchKeyEvent事件:

private WindowCallbackWrapper wrapperWindowCallback(Window.Callback wrapped) {
    WindowCallbackWrapper wrapper = new WindowCallbackWrapper(wrapped) {
        //拦截dispatchKeyEvent事件,自己处理KeyEvent.KEYCODE_VOLUME_DOWN、KeyEvent.KEYCODE_VOLUME_UP
        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            final int keyCode = event.getKeyCode();
            final boolean isDown = (event.getAction() == KeyEvent.ACTION_DOWN);
            boolean consumed = onKeyDown(isDown, keyCode);
            return consumed || super.dispatchKeyEvent(event);
        }
    };
    return wrapper;
}

接入使用

几行代码搞定

1、针对Activity,在Application创建时调用:

LRVolumeAdjustManager.registerApplication(this);

2、针对Dialog,两种方式处理:

1)第一种:所有的Dialog都继承BaseVolumeDialog;

2)第二种:在基类Dialog中调用:

LRVolumeHelper.registerLRVolumeAdjust(getWindow(), mHostActivity);

你可能感兴趣的:(Android)