SystemUI问题修改总结

案例一:状态栏多图标情况下三角按钮闪烁问题。
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\IconMerger.java
此文件的主要作用是合并通知栏图标,其中:
onLayout 和 checkOverflow 方法是测量状态栏的宽度来决定是否显示隐藏三角指示图标
案例二:下拉栏实现双卡数据开关
①config.xml添加关键字
②QSTileHost.java中创建实例
③创建Sim1 & Sim2的Tile类分别继承之前的Date类
④在两个类中分别做数据初始化及互斥逻辑操作
案例三:状态栏左边是给其他应用显示图标的
案例三、一: 如何将下拉通知栏的宽度修改为适应屏幕宽度?
请在/frameworks/base/packages/SystemUI/res/values/dimens.xml文件中,找到如下内容:
    <!-- Width for the notification panel and related windows -->
    <dimen name="match_parent">-1px</dimen>
    <dimen name="standard_notification_panel_width">416dp</dimen><!-- includes notification_side_padding on each side -->
    <dimen name="notification_panel_width">@dimen/match_parent</dimen>
将上述内容中的 <dimen name="standard_notification_panel_width">416dp</dimen>
修改为:<dimen name="standard_notification_panel_width">@dimen/match_parent</dimen>
修改notification之间的间隔
<!-- The height of the divider between the individual notifications. -->
<dimen name= "notification_divider_height" > 2dp </dimen>
修改日期到时钟的距离 在布局中设置的
设置下拉栏图片及字体的大小
<dimen name= "qs_tile_icon_size" > 24dp </dimen>
<dimen name= "qs_tile_text_size" > 11sp </dimen>
快捷图标(item)设置布局模板
图标:SystemUI\src\com\android\systemui\qs\tileimpl\QSIconViewImpl.java
字体:SystemUI\res\layout\qs_tile_label.xml(里面有图标距离字体的高度)
对字体的设置(如颜色等):SystemUI\src\com\android\systemui\qs\tileimpl\QSTileView.java
下拉栏快捷设置点击进入详情界面布局文件
SystemUI\res\layout\qs_detail.xml
下拉栏底部显示及编辑控件
SystemUI\res\layout\qs_paged_tile_layout.xml
二级菜单界面整体布局
SystemUI\res\layout\qs_detail.xml
二级菜单详情界面信息列表布局
SystemUI\res\layout\qs_detail_item.xml
二级菜单详情界面列表信息为空的时候的布局
SystemUI\res\layout\qs_detail_items.xml
用户信息详情界面布局
SystemUI\res\layout\qs_user_detail_item.xml
设置下拉栏高度的尺寸值
<dimen name="qs_tile_height">88dp</dimen> 设置每行之间的距离
锁屏界面充电指示字符串的类
SystemUI\src\com\android\systemui\statusbar\KeyguardIndicationController.java
下拉栏顶部时间布局
SystemUI\res_transsion\layout-v24\status_bar_alarm_group.xml
<!-- The font size of the time when collapsed in QS 。时间字体大小-->
<dimen name="qs_time_collapsed_size">18dp</dimen>
<!-- The font size of the time when expanded in QS。 AM、PM字体大小-->
<dimen name="qs_time_expanded_size">18dp</dimen>
下拉栏编辑快捷设置界面高度的修改方式
SystemUI\res\layout\qs_customize_divider.xml
SystemUI\res\layout\qs_customize_tile_frame.xml
自定义下拉栏图标位置的位置
布局:res/layout/qs_customize_panel_content.xml( RecyclerView
类:SystemUI\src\com\android\systemui\qs\customize\QSCustomizer.java
8.0下拉栏统一对快捷图标着色的地方,修改快捷图标title的地方
SystemUI\src\com\android\systemui\qs\tileimpl\QSIconViewImpl.java
SystemUI\src\com\android\systemui\qs\tileimpl\QSTileView.java
下拉栏控制主题颜色的几个颜色变量
7.0:qs_detail_transition system_primary_color
8.0:qs_detail_transition ?android:attr/colorPrimary
下拉栏快捷设置每行修改为四个,自定义界面修改为每行四个
<integer name= "quick_settings_num_columns" > 4 </integer>
SystemUI\src\com\android\systemui\qs\customize\QSCustomizer.java
SystemUI\src\com\android\systemui\qs\customize\TileAdapter.java

修改Notification样式的几个xml文件

core/res/res/layout/notification_material_action_list.xml

packages/Keyguard/res_transsion/layout-v24/keyguard_status_view.xml

packages/SystemUI/res_transsion/drawable-v24/notification_guts_bg.xml

packages/SystemUI/res_transsion/drawable-v24/notification_material_bg.xml

packages/SystemUI/res_transsion/drawable-v24/notification_material_bg_dim.xml

packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java

案例四:状态栏默认图标修改处
SystemUI\res\layout\signal_cluster_view.xml
案例五:状态栏显示图标更换修改处
base/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
案例六:statusbar图标根据背景显示颜色
SystemUI\src\com\android\systemui\statusbar\phone\StatusBarIconController.java 此类提供所有图标显示颜色数据
private void setIconTintInternal ( float darkIntensity) {
mDarkIntensity = darkIntensity ;
mIconTint = ( int ) ArgbEvaluator.getInstance().evaluate(darkIntensity ,
mLightModeIconColorSingleTone , mDarkModeIconColorSingleTone ) ;
applyIconTint() ;
}
下面的类根据传递来的数据进行颜色的改变
SystemUI\src\com\android\systemui\statusbar\SignalClusterView.java
public void setIconTint( int tint , float darkIntensity) {
private void applyIconTint() {
系统下拉栏的电量显示在
SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBarView.java
SystemUI\res\layout\system_icons.xml
案例六、一:节电助手改变StatusBar背景颜色的方法
一开始想在SystemUI中设置颜色来达到状态栏和壁纸颜色冲突问题,但是最后还是决定在Launcher中修改,因为这样影响范围较小
在文件:SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBar.java
    private void checkBarMode(int mode, int windowState, BarTransitions transitions,
            boolean noAnimation) {
        final boolean powerSave = mBatteryController.isPowerSave();
        final boolean anim = !noAnimation && (mScreenOn == null || mScreenOn)
                && windowState != WINDOW_STATE_HIDDEN && !powerSave;
         if (powerSave && getBarState() == StatusBarState.SHADE) {
这里同时判断getBarState() == StatusBarState.SHADE,锁屏是StatusBarState.KEYGUARD
            mode = MODE_WARNING;
        }
        transitions.transitionTo(mode, anim);
    }
在节电模式下,powerSave = mBatteryController.isPowerSave();会为true,然后当前mode = MODE_WARNING;
在文件:SystemUI\src\com\android\systemui\statusbar\phone\BarTransitions.java
会进行状态栏背景颜色切换,节电模式下的颜色为:
mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
最后通过绘制函数进行绘图,显示红色状态栏。
   @Override
        public void draw(Canvas canvas) {
            int targetGradientAlpha = 0, targetColor = 0;
            if (mMode == MODE_WARNING) {
                targetColor = mWarning;
            } else if (mMode == MODE_TRANSLUCENT) {
                targetColor = mSemiTransparent;
            } else if (mMode == MODE_SEMI_TRANSPARENT) {
                targetColor = mSemiTransparent;
            } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) {
                targetColor = mTransparent;
            } else {
                targetColor = mOpaque;
            }
案例七:其他应用收起下拉栏
[QUESTION]
SC7731,来电接通时,如何收起下拉通知栏?
[ANSWER]
来电接通时,要收起下拉通知栏,请做以下修改:
packages\apps\Dialer\AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_SMS"/>
++ <uses-permission android:name="android.permission.STATUS_BAR" />

packages\apps\InCallUI\src\com\android\incallui\CallCardPresenter.java

import com.google.common.base.Preconditions;
++import android.app.StatusBarManager;
... ...

private Context mContext;
++ private StatusBarManager mStatusBarManager;
... ...
mContext = Preconditions.checkNotNull(context);
++ mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
... ...

@Override
public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
Log.d(this, "onStateChange() " + newState);
final CallCardUi ui = getUi();
if (ui == null) {
return;
}
Call primary = null;
Call secondary = null;
++ if(newState == InCallState.INCALL && oldState != InCallState.INCALL){
++ mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
++ mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
++ }
案例八:截屏的具体实现
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java 这个类中判断是按了电源键和音量下键进行截屏截屏的方式是
mHandler.post(mScreenshotRunnable);
takeScreenshot();是绑定截屏服务的主要接口
截屏服务:SystemUI\src\com\android\systemui\screenshot\TakeScreenshotService.java
截屏服务中用的是类SystemUI\src\com\android\systemui\screenshot\GlobalScreenshot.java 的方法 takeScreenshot();
this.mHost.collapsePanels(); 用于收起下拉栏
案例九:recent task 数量的控制
[SC7731C][ITEL][A11]点击Menu键之后出现的recent task数量是在哪控制的?
解决方案: 
frameworks/base/core/java/android/app/ActivityManager.java中
static public int getMaxRecentTasksStatic() {
        if (gMaxRecentTasks < 0) {
            return gMaxRecentTasks = isLowRamDeviceStatic() ? 10 : 100;//这里修改下10改成22
        }
        return gMaxRecentTasks;
    }
这是google原生设计如此,低内存最近任务数做了限制,默认是10,这个主要减少ActivityManager后台维护的开销和最近任务界面的显示负荷
这个限制可以根据情况修改,但不建议改的很大,目前看改成22没有什么问题
案例十:改变下拉栏每行显示的数量
SystemUI\res\values\config.xml
<!-- The number of columns in the QuickSettings -->
<integer name="quick_settings_num_columns">3</integer>
案例十一:各个锁屏界面紧急拨号按钮
frameworks\base\packages\Keyguard\src\com\android\keyguard\EmergencyButton.java 按钮的点击事件是在控件中实现的
案例十二:音量控制按钮
frameworks\base\packages\SystemUI\src\com\android\systemui\volume\VolumeDialog.java
案例十三:锁屏界面不显示相机图标
frameworks\base\packages\SystemUI\res\values\config.xml
<!-- Show camera affordance on Keyguard -->
<bool name= "config_keyguardShowCameraAffordance" > false </bool>
案例十四:下拉栏点击勿扰模式后进入的界面
(想去除这个界面和自己用的魅族手机相同)
frameworks\base\packages\SystemUI\src\com\android\systemui\volume\ZenModePanel.java
案例十五:电量百分比代码位置
不下拉statusbar显示电池的百分比有PhoneStatusbarView和KeyguardStatusbarView两个部分。
下拉栏在StatusBarHeaderView.java类中。下面是设置方法
tempBatteryLevel = level;
String percentage = NumberFormat. getPercentInstance ().format((double) level / 100.0);
mBatteryLevel.setText(percentage);
案例十六:下拉栏的头部中的图标都在这个布局中(自定义的控件)
frameworks\base\packages\SystemUI\res\layout\status_bar_expanded_header.xml 首先此布局中有一个控件frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\MultiUserSwitch.java 此控件中有实现点击图标打开联系人界面的功能
首先:自测试当滑动下拉栏的时候第一次点击用户设置头像会彻底将下拉栏展开第二次点击的时候才会打开用户信息设置界面。
Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
getContext(), v, ContactsContract.Profile. CONTENT_URI ,
ContactsContract.QuickContact. MODE_LARGE , null);
getContext().startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
这段代码是打开用户信息设置界面的
if (mQsPanel != null && mQsPanel.getHost() != null) {
mQsPanel.getHost().collapsePanels();
} 这段代码是收起下拉栏功能
如果之前没有设置用户信息的话打开的界面是 com.android.contacts/com.android.contacts.activities.CompactContactEditorActivity
如果之前有设置用户信息的话则打开的是
com.android.contacts/com.android.contacts.quickcontact.QuickContactActivity
从打印出的log的信息来看当没有用户信息的时候先显示此activity然后瞬间打开 CompactContactEditorActivity 来实现打开不同界面的目的此类中的 editContact() 方法即为打开 CompactContactEditorActivity 的具体实现,打开的intent可追溯到是 "android.intent.action.EDIT" 。此activity中加载的是一个 packages\apps\Contacts\src\com\android\contacts\editor\CompactContactEditorFragment.java 此类继承类 packages\apps\Contacts\src\com\android\contacts\editor\ContactEditorBaseFragment.java 此类中含有onOptionsItemSelected() 方法首个菜单即为保存编辑
到此我想了解他是怎么报错和删除用户信息的以及怎样通知SystemUI的?
用户信息查询追踪到 frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\UserInfoController.java queryForUserInformation方法 这个方法是在本类中的reloadUserInfo() 方法中使用的,而此方法的使用除此类中的 broadcastrecever 监听使用外还在另外两个类中使用到了分别使用一次这两个类是: src/com/android/systemui/statusbar/phone/PhoneStatusBar.java 和 src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
是个 Imageview ,控件的id为 multi_user_avatar 。他在 StatusBarHeaderView.java 中做了个监听当用户信息改变的时候会更新用户的头像。
public void setUserInfoController(UserInfoController userInfoController) {
userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
@Override
public void onUserInfoChanged(String name, Drawable picture) {
mMultiUserAvatar.setImageDrawable(picture);
}
});
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\policy\UserInfoController.java 此类中有 addListener 方法参数是此类中的 OnUserInfoChangedListener 接口,此接口中有一个抽象方法 onUserInfoChanged
此类中还存在一个方法 notifyChanged ,此方法中使用for循环调用接口的 onUserInfoChanged 方法。notifyChanged调用的时机是:此控制类中的 queryForUserInformation 方法中的AysnTask执行完成的时候会将图片返回到此类中。
// Fall back to the UserManager nickname if we can't read the name from the local
// profile below.
String name = userName;
Drawable avatar = null;
Bitmap rawAvatar = um.getUserIcon(userId);
if (rawAvatar != null) {
Log. d ( TAG , "****************rawAvatar != null");
avatar = new BitmapDrawable(mContext.getResources(),
BitmapHelper. createCircularClip (rawAvatar, avatarSize, avatarSize));
} else {
此处的代码显示将得到的图片进行了处理,处理为圆形的头像图片。
到此处逻辑上似乎没有什么问题。下面来看Bitmap来源
Bitmap rawAvatar = um.getUserIcon(userId);
调用的是这个类 frameworks\base\core\java\android\os\UserManager.java 中的方法 public Bitmap getUserIcon(int userHandle) { 然后这个方法中调用了 frameworks\base\core\java\android\os\IUserManager.aidl 中的 ParcelFileDescriptor getUserIcon(int userHandle) ;具体实现是在 frameworks\base\services\core\java\com\android\server\pm\UserManagerService.java 这个类中的。
@Override
public ParcelFileDescriptor getUserIcon(int userId) {
此方法中通过 UserInfo info = mUsers.get(userId) ;的到用户信息,其中包括用户图片的存放地址然后返回。 return ParcelFileDescriptor. open (
new File(iconPath), ParcelFileDescriptor. MODE_READ_ONLY );
过程中有好多的非空判断如果返回的是为null的话则显示默认的图片不会刷新。
此类中的 private UserInfo readUserLocked(int id) { 方法有用户信息的一些数据如:用户图片路径。
案例十七:如何根据省电的模式来动态修改电池的颜色
首先SystemUI\res\values\arrays.xml中保存了三个数组,第一个数组 batterymeter_color_levels 保存的是电量的几个重要的节点状态,有15,、100。 batterymeter_color_values 保存的是电池的颜色。这些数据是在SystemUI\src\com\android\systemui\BatteryMeterView.java这个类中使用的,这个类就是电池的控件。这个类有实现了接口 BatteryController.BatteryStateChangeCallback 中的两个方法
void onBatteryLevelChanged ( int level , boolean pluggedIn , boolean charging) ;
void onPowerSaveChanged () ; 这两个方法是通过回调实现的。
SystemUI\src\com\android\systemui\statusbar\policy\BatteryController.java是继承BrodcastReceive的可以通过传过来的Intent来判断并通过方法 updatePowerSave和 setPowerSave进行电量模式的更新。在updatePowerSave中使用 setPowerSave( mPowerManager .isPowerSaveMode()) ; 来实现的。然后我们查找mPowerManager的具体类frameworks\base\core\java\android\os\PowerManager.java在 isPowerSaveMode里 调用的是 mService .isPowerSaveMode() ; mService 的具体实现类是 frameworks\base\core\java\android\os\IPowerManager.aidl 而具体的实现是在 frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java 中的内部类 BinderService 实现的 return isLowPowerModeInternal(); 我们在跟进这个方法返回的是 return mLowPowerModeEnabled; 再跟进这个变量的赋值地点是 void updateLowPowerModeLocked() { 中的 mLowPowerModeEnabled = lowPowerModeEnabled; lowPowerModeEnabled 这个变量的赋值方式是 final boolean autoLowPowerModeEnabled = !mIsPowered && mAutoLowPowerModeConfigured
&& !mAutoLowPowerModeSnoozing && mBatteryLevelLow ;这几个变量的意思是不是在充电状态、自动打开低电量模式是开启的、低电量模式自动睡眠是关闭的,电池电量是比较低的。
用到电池的地方一共有三个分别是:锁屏、状态栏和下拉栏,对应的三个类分别是: src/com/android/systemui/statusbar/phone/PhoneStatusBar.java、src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java、
src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java这三个类
统一使用的代码为: ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
在我们发送广播的时候打印log显示onReceive走了两次,原因是BatteryController被实例了两次
systemui/statusbar/phone/PhoneStatusBar.java: mBatteryController = new BatteryController(mContext);
systemui/statusbar/phone/PhoneStatusBarView.java:
mBatteryController = new BatteryController(context);
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值