源码路径:com.android.systemui.statusbar.phone/StatusIconContainer.java
布局文件路径:SystemUI/res/layout/status_bar.xml

一、状态栏布局

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

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

<FrameLayout            android: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 the             individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and             DISABLE_NOTIFICATION_ICONS, respectively -->            <LinearLayout                android:id="@+id/status_bar_left_side"                android:layout_height="match_parent"                android:layout_width="match_parent"                android:clipChildren="false"            >                <ViewStub                    android: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.AlphaOptimizedFrameLayout                    android: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.Space            android:id="@+id/cutout_space_view"            android:layout_width="0dp"            android:layout_height="match_parent"            android:gravity="center_horizontal|center_vertical"        />        <com.android.systemui.statusbar.AlphaOptimizedFrameLayout            android: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"            >            <LinearLayout                android: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" />                <!-- HCT lishuo for show new battery icon style -->                <include layout="@layout/hct_status_bar_battery"/>                <!-- HCT lishuo for show new battery icon style end -->                <android.widget.Space                    android:layout_width="2dp"                    android:layout_height="match_parent"                />                <com.android.systemui.statusbar.policy.Clock                    android: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 battery    private static final int MAX_ICONS = 7;

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

@Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        mMeasureViews.clear();        int mode = MeasureSpec.getMode(widthMeasureSpec);        final int width = MeasureSpec.getSize(widthMeasureSpec);        final int count = getChildCount();        // Collect all of the views which want to be laid out        for (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 width        int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);        mNeedsUnderflow = mShouldRestrictIcons && visibleCount > MAX_ICONS;        for (int i = 0; i < mMeasureViews.size(); i++) {            // Walking backwards            View child = mMeasureViews.get(visibleCount - i - 1);            measureChild(child, childWidthSpec, heightMeasureSpec);            if (mShouldRestrictIcons) {                if (i < maxVisible && trackWidth) {                    totalWidth += getViewTotalMeasuredWidth(child);                } else if (trackWidth) {                    // We've hit the icon limit; add space for dots                    totalWidth += mUnderflowWidth;                    trackWidth = false;                }            } else {                totalWidth += getViewTotalMeasuredWidth(child);            }        }        if (mode == MeasureSpec.EXACTLY) {            if (!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();        float translationX = width - getPaddingEnd();        float contentStart = getPaddingStart();        //HCT: lishuo statusbar new style        if(isLayoutOpposite){            translationX = width - getPaddingStart();            contentStart = getPaddingEnd();        }        //HCT: lishuo statusbar new style end        int childCount = getChildCount();        // Underflow === don't show content until that index        if (DEBUG) android.util.Log.d(TAG, "calculateIconTranslations: start=" + translationX                + " width=" + width + " underflow=" + mNeedsUnderflow);        // Collect all of the states which want to be visible        //HCT: lishuo statusbar new style, Exchange SIM icons position        View firstSimIconView = null;        View secondSimIconView= null;        if(isLayoutOpposite){            for (int i = childCount - 1; i >= 0; i--) {                View child = getChildAt(i);                if(child instanceof StatusBarMobileView && firstSimIconView == null){                    firstSimIconView = child;                }else if(child instanceof StatusBarMobileView && firstSimIconView != null){                    secondSimIconView = child;                    break;                }            }        }        //HCT: lishuo statusbar new style, Exchange SIM icons position end        for (int i = childCount - 1; i >= 0; i--) {            View child = getChildAt(i);            //HCT: lishuo statusbar new style            if(isLayoutOpposite && firstSimIconView != null && secondSimIconView != null){                if(child.equals(firstSimIconView)){                    child = secondSimIconView;                }else if(child.equals(secondSimIconView)){                    child = firstSimIconView;                }            }            //HCT: lishuo statusbar new style end            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;            childState.xTranslation = translationX - getViewTotalWidth(child);            mLayoutStates.add(0, childState);            translationX -= getViewTotalWidth(child);        }        // Show either 1-MAX_ICONS icons, or (MAX_ICONS - 1) icons + overflow        int 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            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);                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 clean        if(isLayoutOpposite){            if (isLayoutRtl()) {            }else{                for (int i = 0; i < childCount; i++) {                    View child = getChildAt(i);                    StatusIconState state = getViewStateFromChild(child);                    state.xTranslation = width - state.xTranslation - child.getWidth();                }            }        }else if (isLayoutRtl()) {            for (int i = 0; i < childCount; i++) {                View child = getChildAt(i);                StatusIconState state = getViewStateFromChild(child);                state.xTranslation = width - state.xTranslation - child.getWidth();            }        }    }

更多相关文章

  1. 为Android应用程序添加两个入口
  2. Android权限问题 及 APP应用图标
  3. Android(安卓)res .9.png android九宫图
  4. Android(安卓)系列 5.9使用Inkscape创建Android(安卓)Launcher图
  5. SystemUI9.0系统应用图标加载流程
  6. 开发可统计单词个数的Android驱动程序(1)
  7. Android(安卓)菜单简析01(OptionsMenu)
  8. Android百度地图SDK—地图标记
  9. android editText 软键盘enter键图标的设置

随机推荐

  1. 灵犀告诉你5个小玩意证明你和安卓是真爱
  2. Android判断网络是否打开,并打开设置网络
  3. 如何学习Android开发编程-初学者的5个步
  4. android 左右切换对话框 dialog
  5. WebView与Javascript交互(相互调用参数、
  6. 一个使用FFmpeg库读取3gp视频的例子-Andr
  7. Android 智能TV电视系统遥控器键值添加
  8. android滑动解锁
  9. android之Activity基本跳转
  10. 【Android(安卓)开发】 : Activity之间传