源码路径:com.android.systemui.statusbar.phone/StatusIconContainer.java
布局文件路径:SystemUI/res/layout/status_bar.xml
下拉后状态栏布局文件路径:SystemUI/res/layout/quick_qs_status_icons.xml
锁屏状态栏文件布局:SystemUI/res/layout/keyguard_status_bar.xml

一、状态栏布局

在没下拉状态栏时,原生android会将状态栏分为两部分(如下图及布局源码)
1、android:id=“@+id/notification_icon_area
2、android:id=”@+id/system_icon_area"

从下面的布局文件可以看到这两块区域的权重都是1,左边放通知图标,右边放系统图标,中间留有一块控件用来放缺口(也就是水滴或刘海的位置),在这里如果没有水滴的话可以修改权重,来放置更多的系统图标或通知图标(有水滴的话改了图标过多时就会遮挡住图标)

<FrameLayoutandroid:layout_height="match_parent"android:layout_width="0dp"android:layout_weight="1"><include layout="@layout/heads_up_status_bar_layout" /><!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and theindividual views are controlled by StatusBarManager disable flags DISABLE_CLOCK andDISABLE_NOTIFICATION_ICONS, respectively --><LinearLayoutandroid:id="@+id/status_bar_left_side"android:layout_height="match_parent"android:layout_width="match_parent"android:clipChildren="false"><ViewStubandroid:id="@+id/operator_name"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout="@layout/operator_name" /><com.android.systemui.statusbar.phone.StatusIconContainer android:id="@+id/statusIcons_left"android:layout_width="wrap_content"android:layout_height="match_parent"android:paddingEnd="@dimen/signal_cluster_battery_padding"android:gravity="center_vertical"android:orientation="horizontal"/><com.android.systemui.statusbar.AlphaOptimizedFrameLayoutandroid:id="@+id/notification_icon_area"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal"android:clipChildren="false"/></LinearLayout></FrameLayout><!-- Space should cover the notch (if it exists) and let other views lay out around it --><android.widget.Spaceandroid:id="@+id/cutout_space_view"android:layout_width="0dp"android:layout_height="match_parent"android:gravity="center_horizontal|center_vertical"/><com.android.systemui.statusbar.AlphaOptimizedFrameLayoutandroid:id="@+id/centered_icon_area"android:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal"android:clipChildren="false"android:gravity="center_horizontal|center_vertical"/><com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal"android:gravity="center_vertical|end"><LinearLayoutandroid:id="@+id/system_icons"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"><com.android.systemui.statusbar.phone.StatusIconContainer android:id="@+id/statusIcons"android:layout_width="0dp"android:layout_weight="1"android:layout_height="match_parent"android:paddingEnd="@dimen/signal_cluster_battery_padding"android:gravity="center_vertical"android:orientation="horizontal"/><com.android.systemui.BatteryMeterView android:id="@+id/battery"android:layout_height="match_parent"android:layout_width="wrap_content"android:clipToPadding="false"android:clipChildren="false"android:textAppearance="@style/TextAppearance.StatusBar.Clock" /><android.widget.Spaceandroid:layout_width="2dp"android:layout_height="match_parent"/><com.android.systemui.statusbar.policy.Clockandroid:id="@+id/clock"android:layout_width="wrap_content"android:layout_height="match_parent"android:textAppearance="@style/TextAppearance.StatusBar.Clock"android:paddingBottom="2dip"android:singleLine="true"android:gravity="center_vertical|end"/></LinearLayout></com.android.keyguard.AlphaOptimizedLinearLayout>

二、状态栏右侧系统图标显示过多时显示一个点

在源码中,控制右侧系统图标显示的有两个限制:
1、图标个数
2、宽度限制

主要方法:onMeasure 和 calculateIconTranslations (下方贴上源代码)
在onMeasure中会测量水滴右边区域能放的下的图标的总宽度(totalWidth)
在calculateIconTranslations中会判断如果图标个数大于限定个数并且剩余宽度不足以绘制一个图标时,就去绘制那个点,达到开始那张图的效果

// Max 8 status icons including batteryprivate static final int MAX_ICONS = 7;

安卓原生定义了最大显示图标个数是8个(包括电池图标)

mUnderflowWidth :显示的点标框的宽度
mShouldRestrictIcons:是否需要限制图标的一个标志位,原生代码中的下拉后的状态栏是不限制图标的,就是在QuickStatusBarHeaderController.java中控制这个变量为false后就不会去画点

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {mMeasureViews.clear();int mode = MeasureSpec.getMode(widthMeasureSpec);final int width = MeasureSpec.getSize(widthMeasureSpec);//当前View的宽度final int count = getChildCount();// Collect all of the views which want to be laid outfor (int i = 0; i < count; i++) {StatusIconDisplayable icon = (StatusIconDisplayable) getChildAt(i);if (icon.isIconVisible() && !icon.isIconBlocked()&& !mIgnoredSlots.contains(icon.getSlot())) {mMeasureViews.add((View) icon);}}int visibleCount = mMeasureViews.size();int maxVisible = visibleCount <= MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;int totalWidth = mPaddingLeft + mPaddingRight;boolean trackWidth = true;// Measure all children so that they report the correct widthint childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);mNeedsUnderflow = mShouldRestrictIcons && visibleCount > MAX_ICONS;for (int i = 0; i < mMeasureViews.size(); i++) {// Walking backwardsView child = mMeasureViews.get(visibleCount - i - 1);measureChild(child, childWidthSpec, heightMeasureSpec);// mShouldRestrictIcons:是否限制图标的一个判断,原生代码中的下拉后的状态栏是//不限制图标的,就是在QuickStatusBarHeaderController.java中控制这个变量if (mShouldRestrictIcons) {  if (i < maxVisible && trackWidth) {//把不超过最大个数的所有图标的宽度加起来totalWidth += getViewTotalMeasuredWidth(child);} else if (trackWidth) {// We've hit the icon limit; add space for dots//mUnderflowWidth:最后加上圆点的宽度totalWidth += mUnderflowWidth;trackWidth = false;}} else {totalWidth += getViewTotalMeasuredWidth(child);}}if (mode == MeasureSpec.EXACTLY) {//如果图标个数没有超过最大限制的数量但是图标的总宽度大于View的宽度//此时也是需要显示点的,将mNeedsUnderflow 设置为trueif (!mNeedsUnderflow && totalWidth > width) {mNeedsUnderflow = true;}setMeasuredDimension(width, MeasureSpec.getSize(heightMeasureSpec));} else {if (mode == MeasureSpec.AT_MOST && totalWidth > width) {mNeedsUnderflow = true;totalWidth = width;}setMeasuredDimension(totalWidth, MeasureSpec.getSize(heightMeasureSpec));}}
private void calculateIconTranslations() {mLayoutStates.clear();float width = getWidth();//总宽度减去PaddingEnd,获取不显示图标时最大的X偏移量float translationX = width - getPaddingEnd();float contentStart = getPaddingStart();//获取当前需要显示的图标个数int childCount = getChildCount();// Underflow === don't show content until that indexif (DEBUG) android.util.Log.d(TAG, "calculateIconTranslations: start=" + translationX+ " width=" + width + " underflow=" + mNeedsUnderflow);// Collect all of the states which want to be visiblefor (int i = childCount - 1; i >= 0; i--) {View child = getChildAt(i);StatusIconDisplayable iconView = (StatusIconDisplayable) child;StatusIconState childState = getViewStateFromChild(child);if (!iconView.isIconVisible() || iconView.isIconBlocked()|| mIgnoredSlots.contains(iconView.getSlot())) {//满足以上条件设置图标状态为隐藏childState.visibleState = STATE_HIDDEN;if (DEBUG) Log.d(TAG, "skipping child (" + iconView.getSlot() + ") not visible");continue;}//设置图标状态为显示childState.visibleState = STATE_ICON;//总X偏移量减去图标的宽度,己算当前图标的X轴偏移量,//如果此时计算结果为负数,则说明View中剩余的宽度不足以将此图标显示完全childState.xTranslation = translationX - getViewTotalWidth(child);mLayoutStates.add(0, childState);translationX -= getViewTotalWidth(child);}// Show either 1-MAX_ICONS icons, or (MAX_ICONS - 1) icons + overflowint totalVisible = mLayoutStates.size();int maxVisible = totalVisible <= MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;mUnderflowStart = 0;int visible = 0;int firstUnderflowIndex = -1;for (int i = totalVisible - 1; i >= 0; i--) {StatusIconState state = mLayoutStates.get(i);// Allow room for underflow if we found we need it in onMeasure//如果需要画点,并且当前图标的X偏移量小于点标框的宽度+padding时,记录当前图标的下标if (mNeedsUnderflow && (state.xTranslation < (contentStart + mUnderflowWidth))||(mShouldRestrictIcons && visible >= maxVisible)) {firstUnderflowIndex = i;break;}mUnderflowStart = (int) Math.max(contentStart, state.xTranslation - mUnderflowWidth);visible++;}if (firstUnderflowIndex != -1) {int totalDots = 0;int dotWidth = mStaticDotDiameter + mDotPadding;int dotOffset = mUnderflowStart + mUnderflowWidth - mIconDotFrameWidth;for (int i = firstUnderflowIndex; i >= 0; i--) {//拿到当前下标的图标状态StatusIconState state = mLayoutStates.get(i);//系统定义的MAX_DOTS=1,也就是说点图标只会显示一个if (totalDots < MAX_DOTS) {state.xTranslation = dotOffset;//设置当前图标状态为点图标state.visibleState = STATE_DOT;dotOffset -= dotWidth;totalDots++;} else {//剩余的图标状态都设置为隐藏state.visibleState = STATE_HIDDEN;}}}// Stole this from NotificationIconContainer. Not optimal but keeps the layout logic cleanif(isLayoutRtl()) {for (int i = 0; i < childCount; i++) {View child = getChildAt(i);StatusIconState state = getViewStateFromChild(child);state.xTranslation = width - state.xTranslation - child.getWidth();}}}

Android Q : 安卓源码、水滴屏适配状态栏图标(图标过多时显示一个点)相关推荐

  1. Linux android studio 安卓源码导入及调试

    1.AndroidStudio导入源码和调试 需要注意以下,JDK的配置,android studio下JDK一般使用对应于SDK版本的默认JDK版本,例如android studio5.0源码--- ...

  2. Android高版本P/Q/R源码编译指南

           Android高版本P/Q/R源码编译指南 Android源码编译系列博客: Android.bp你真的了解吗 Android.bp入门指南之Android.mk转换成Android.b ...

  3. 基于android的门禁系统代码,基于ESP8266 base on esp8266门禁系统 安卓源码

    基于ESP8266门禁系统安卓源码 视频中的小伙伴是我的搭档,负责硬件电路搭建,为了搭电路没少熬夜,挺感谢他的. 这是本人的毕业设计(专科)历时一个月完成.在做毕业设计之前一直在准备转本考试,考完试, ...

  4. AndroidStudio配合android.jar查看安卓源码

    使用as在查看源码的时候经常会有类报错的情况,比如: 下面介绍一种方法修复类似错误,可以直接在as查看的方法. 获取源码 从各种渠道获取到安卓源码,可以从 清华大学开源软件镜像站下载,当然也可以单独下 ...

  5. Android海外应用和安卓源码的多国语言翻译

    前言:目前翻译只有baidu能直接进行调用,但是baidu支持的语言太少,无法支持对google play下发布的海外应用要求的多个翻译, 而且网上说的Android Studio的翻译插件,经过体验 ...

  6. 使用Android Studio导入安卓源码

    1 背景 这篇文章主要说明的是用它来看源码的相关配置(该实例依据官方源码进行配置说明).在android源码中发现有一个development/tools/idegen目录,查了一下发现是生成IDE的 ...

  7. Android 8.0学习(32)---Android 8.0源码目录结构详解

    Android 8.0源码目录结构详解 android的移植按如下流程:     (1)android linux 内核的普通驱动移植,让内核可以在目标平台上运行起来.     (2)正确挂载文件系统 ...

  8. 哪些手机支持android q,安卓Q首批升级名单公布,华为终于有一款机型支持原生...

    原标题:安卓Q首批升级名单公布,华为终于有一款机型支持原生 在今天凌晨举行的I/O大会上,谷歌正式发布了新一代Android 系统Android Q.新系统最大的特性就是在用户隐私和数据安全做了一系列 ...

  9. 从谷歌官网下载android 6.0源码、编译并刷入nexus 6p手机

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/fuchaosz/article/details/52473660 1 前言 经过一周的奋战,终于从谷 ...

最新文章

  1. 广东计算机好的2a学校,广东专插本2A院校排名情况
  2. c# char unsigned_c – unsigned char和char指针之间的区别
  3. NOIP2016普及组第一题:买铅笔
  4. POJ3169 Layout(差分约束)
  5. bootstrap 文字不换行
  6. python做excel表格合并_Python实战:合并 Excel 表格
  7. 计算机断电后自动启动,断电来电后自动开机,神奇的电脑开机方法
  8. Socket通讯连接常见错误代码
  9. 部署无鱼工时系统,超详细教程,并成功部署
  10. php执行shell脚本
  11. 型如=?gb2312?B?的转码
  12. 体积小性能强悍能吃鸡的电脑主机 NUC8I7HVK
  13. JAVA 数据库连接池系列 —— HikariCP 简介
  14. 【自学Python】Python类型转换
  15. HTTPS能否避免流量劫持?
  16. NTIRE2020~21 SISR超分 总结
  17. oracle怎样建表,oracle怎样建表?_数据库
  18. 【ML】KMeans 原理 + 实践(基于sklearn)
  19. python while循环求和_Python基础——for/while循环
  20. 百度PC关键词排名查询API接口-(api_submit- 百度PC关键词排名查询API接口)

热门文章

  1. java netty 教程_Java NIO框架Netty教程(十六)
  2. css常用(2):毛玻璃 、模糊滤镜
  3. CMD命令下图片马生成命令
  4. 2012年十大消费趋势预测 移动互联网占七项
  5. Thinkphp基本使用知识
  6. ctfshow-misc40
  7. android+final+框架,使用android快速开发框架afinal 开发android应用程序
  8. 通俗易懂,十分钟读懂DES,详解DES加密算法原理,DES攻击手段以及3DES原理。Python DES实现源码
  9. NVIDIA之Tesla、GeForce和Quadro系列GPU对比
  10. Git是什么?Git常用的命令是什么?