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);