最近基于工作需要,在Android5.0上研究了一下系统下拉状态栏的知识,并参考了“LYJ的IT生活”的http://blog.csdn.net/lyjit/article/details/51579067文章,在学习了他的做法之后,现在总结一下自己的实际应用:
添加自己的快捷开关
此处以添加静音快捷开关为例,首先,打开这个文件frameworks/base/packages/SystemUI/res/values/config.xml,搜索“quick_settings_tiles_default”找到该处内容,如我的代码是
<!– The default tiles to display in QuickSettings –>
<string name=”quick_settings_tiles_default” translatable=”false”>
wifi,bt,inversion,cell,airplane,rotation,flashlight,location,cast,hotspot
</string>
这是自适应的布局,这些快捷按键的定义都在这里,如要添加或替换,在这里修改即可。这里我添加了静音开关mute,代码如下:
<!– The default tiles to display in QuickSettings –>
<string name=”quick_settings_tiles_default” translatable=”false”>
wifi,bt,inversion,cell,airplane,rotation,flashlight,location,cast,hotspot,mute
</string>
其次,打开frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java文件,找到private QSTile<?> createTile(String tileSpec) 函数,并添加mute相关代码,如下所示:
private QSTile<?> createTile(String tileSpec) {
if (tileSpec.equals(“wifi”)) return new WifiTile(this);
else if (tileSpec.equals(“bt”)) return new BluetoothTile(this);
else if (tileSpec.equals(“mute”)) return new MuteTile(this);
……
}
这里主要是获取到预定义好的各个快捷图标的QSTile。
下面是新建MuteTile这个文件,在frameworks/base/packages/SystemUI/src/com/Android/systemui/qs/tiles
这个路径下面就是你定义的开关实现功能的地方,这里新添加的mute在原有的快捷开关里面是没有的,所以要在这里新添加一个文件MuteTile.java,该文件代码如下:
package com.android.systemui.qs.tiles;
import android.media.AudioManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import com.android.systemui.R;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.qs.QSTile;
public class MuteTile extends QSTile<QSTile.BooleanState> {
private boolean mListening;
private AudioManager mAudioManager;
private final GlobalSetting mSetting;
public MuteTile(Host host) {
super(host);
// TODO Auto-generated constructor stub
mAudioManager = (AudioManager)mContext.getSystemService(mContext.AUDIO_SERVICE);
mSetting = new GlobalSetting(mContext, mHandler, Settings.System.MODE_RINGER_STREAMS_AFFECTED) {
@Override
protected void handleValueChanged(int value) {
handleRefreshState(value);
}
};
}
public void setListening(boolean listening) {
// TODO Auto-generated method stub
if (mListening == listening) return;
mListening = listening;
mSetting.setListening(listening);
}
@Override
protected BooleanState newTileState() {
// TODO Auto-generated method stub
return new BooleanState();
}
@Override
protected void handleClick() {
// TODO Auto-generated method stub
setMute();
}
@Override
protected void handleUpdateState(
BooleanState state, Object arg) {
// TODO Auto-generated method stub
//int mode = mSetting.getValue();
state.visible = true;
state.value = true;
state.label = mContext.getString(R.string.quick_settings_mute_label);
if (mAudioManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_mute_off);
state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_mute_off);
} else {
state.icon = ResourceIcon.get(R.drawable.ic_qs_mute_on);
state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_mute_on);
}
}
private void setMute() {
if (mAudioManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
mAudioManager.setStreamMute(AudioManager.STREAM_RING, true);
} else {
mAudioManager.setStreamMute(AudioManager.STREAM_RING, false);
}
mSetting.setValue(mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
}
}
其中mSetting的定义很关键,GlobalSetting里的参数要结合自己的具体实际来写,不然点击图标是不会刷新界面的,另外,setMute()函数须放在handleClick中,不能放在handleUpdateState中,因为handleUpdateState是负责刷新界面的,会一直都在程序的刷新监听中,放在里面有可能会导致图标不断变化。
最后,mSetting.setValue(mAudioManager.getStreamVolume(AudioManager.STREAM_RING));这一句是刷新页面的关键,因为我们程序里面通过GlobalSetting定义了相关的监听ContentObserver ,每次点击图标后都是通过设置这个value的方式通知ContentObserver 刷新界面的。