Android13-SystemUI_状态栏-时间居中显示和修改格式

227 阅读4分钟

居中显示

看状态栏的布局文件status_bar.xml

<com.android.systemui.statusbar.phone.PhoneStatusBarView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
    android:layout_width="match_parent"
    android:layout_height="@dimen/status_bar_height"
    android:id="@+id/status_bar"
    android:orientation="vertical"
    android:focusable="false"
    android:descendantFocusability="afterDescendants"
    android:accessibilityPaneTitle="@string/status_bar"
    >

    <ImageView
        android:id="@+id/notification_lights_out"
        android:layout_width="@dimen/status_bar_icon_size"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingBottom="2dip"
        android:src="@drawable/ic_sysbar_lights_out_dot_small"
        android:scaleType="center"
        android:visibility="gone"
        />
		
		 <!--这个外层的Linearlayout-->
    <LinearLayout android:id="@+id/status_bar_contents"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingStart="@dimen/status_bar_padding_start"
        android:paddingEnd="@dimen/status_bar_padding_end"
        android:paddingTop="@dimen/status_bar_padding_top"
        android:orientation="horizontal">

        <!-- Container for the entire start half of the status bar. It will always use the same
             width, independent of the number of visible children and sub-children. -->
        <FrameLayout
            android:id="@+id/status_bar_start_side_container"
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:clipChildren="false"
            android:layout_weight="1">

            <!-- Container that is wrapped around the views on the start half of the status bar.
                 Its width will change with the number of visible children and sub-children.
                 It is useful when we want to know the visible bounds of the content. -->
            <FrameLayout
                android:id="@+id/status_bar_start_side_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clipChildren="false">

                <include layout="@layout/heads_up_status_bar_layout" />

                <!-- The alpha of the start 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_start_side_except_heads_up"
                    android:layout_height="wrap_content"
                    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" />
                    <!--这里的Clock的外外层是LinearLayout,居中还是考虑放它在外面-->
<!--                    <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:singleLine="true"-->
<!--                        android:paddingStart="@dimen/status_bar_left_clock_starting_padding"-->
<!--                        android:paddingEnd="@dimen/status_bar_left_clock_end_padding"-->
<!--                        android:gravity="center_vertical|start"-->
<!--                    />-->

                    <include layout="@layout/ongoing_call_chip" />

                    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                        android:id="@+id/notification_icon_area"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:orientation="horizontal"
                        android:clipChildren="false"/>

                </LinearLayout>
            </FrameLayout>
        </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"
        />

        <!-- Container for the entire end half of the status bar. It will always use the same
             width, independent of the number of visible children and sub-children. -->
        <FrameLayout
            android:id="@+id/status_bar_end_side_container"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:clipChildren="false">

            <!-- Container that is wrapped around the views on the end half of the
                 status bar. Its width will change with the number of visible children and
                 sub-children.
                 It is useful when we want know the visible bounds of the content.-->
            <com.android.keyguard.AlphaOptimizedLinearLayout
                android:id="@+id/status_bar_end_side_content"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="end"
                android:orientation="horizontal"
                android:gravity="center_vertical|end"
                android:clipChildren="false">

                <include
                    android:id="@+id/user_switcher_container"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="@dimen/status_bar_user_chip_end_margin"
                    layout="@layout/status_bar_user_chip_container" />

                <include layout="@layout/system_icons" />
            </com.android.keyguard.AlphaOptimizedLinearLayout>
        </FrameLayout>
    </LinearLayout>
    
    <!-- 放在这里   -->
    <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:singleLine="true"
        android:gravity="center_vertical"
        android:layout_gravity="center_horizontal"
        />

    <ViewStub
        android:id="@+id/emergency_cryptkeeper_text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="@android:color/holo_blue_light"
        android:layout="@layout/emergency_cryptkeeper_text"
    />

</com.android.systemui.statusbar.phone.PhoneStatusBarView>

Clock控件同级还有其他控件的,且它的父布局还是LinearLayout,而且外外层的也没有铺满屏幕,而PhoneStatusBarView是继承自FrameLayout,考虑放在它的下面,多添加水平居中android:layout_gravity="center_horizontal”

    <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:singleLine="true"
        android:gravity="center_vertical"
        android:layout_gravity="center_horizontal"
        />

但这样还不能够居中,PhoneStatusBarView自己加了右内边距

Untitled.png

public class PhoneStatusBarView extends FrameLayout {
    private void updateSafeInsets() {
        Pair<Integer, Integer> insets = mContentInsetsProvider
                .getStatusBarContentInsetsForCurrentRotation();
        
        //这里PhoneStatusBarView给自己加了一个右内边距,所以单纯在布局居中,居中不了
        setPadding(
                insets.first,
                getPaddingTop(),
                insets.second,
                getPaddingBottom());
        //这里给Clock加了一个左外边距
        if(mClock instanceof Clock){
            Clock tempClock = (Clock) mClock;
            FrameLayout.LayoutParams layoutParams = (LayoutParams) tempClock.getLayoutParams();
            layoutParams.leftMargin = insets.second;
            tempClock.setLayoutParams(layoutParams);
        }
    }

为防止Clock控件自己设置了内边距,这里注释掉

    @Override
    public void onDensityOrFontScaleChanged() {
        FontSizeUtils.updateFontSize(this, R.dimen.status_bar_clock_size);
//        setPaddingRelative(
//                mContext.getResources().getDimensionPixelSize(
//                        R.dimen.status_bar_clock_starting_padding),
//                0,
//                mContext.getResources().getDimensionPixelSize(
//                        R.dimen.status_bar_clock_end_padding),
//                0);
    }

效果
Untitled 1.png

Clock显示时间格式修改

public class Clock extends TextView implements
        DemoModeCommandReceiver,
        Tunable,
        CommandQueue.Callbacks,
        DarkReceiver, ConfigurationListener {
    final void updateClock() {
        if (mDemoMode) return;
        mCalendar.setTimeInMillis(System.currentTimeMillis());
        CharSequence smallTime = getSmallTime();
        // Setting text actually triggers a layout pass (because the text view is set to
        // wrap_content width and TextView always relayouts for this). Avoid needless
        // relayout if the text didn't actually change.
        if (!TextUtils.equals(smallTime, getText())) {
            setText(smallTime);
        }
        setContentDescription(mContentDescriptionFormat.format(mCalendar.getTime()));
    }

看getSmallTime()方法,这里获取时间的文本

    private final CharSequence getSmallTime() {
        Context context = getContext();
        boolean is24 = DateFormat.is24HourFormat(context, mCurrentUserId);
        if (mDateTimePatternGenerator == null) {
            // Despite its name, getInstance creates a cloned instance, so reuse the generator to
            // avoid unnecessary churn.
            mDateTimePatternGenerator = DateTimePatternGenerator.getInstance(
                context.getResources().getConfiguration().locale);
        }

        final char MAGIC1 = '\uEF00';
        final char MAGIC2 = '\uEF01';

        final String formatSkeleton = mShowSeconds
                ? is24 ? "Hms" : "hms"
                : is24 ? "Hm" : "hm";
        String format = mDateTimePatternGenerator.getBestPattern(formatSkeleton);
        if (!format.equals(mContentDescriptionFormatString)) {
            mContentDescriptionFormatString = format;
            mContentDescriptionFormat = new SimpleDateFormat(format);
            /*
             * Search for an unquoted "a" in the format string, so we can
             * add marker characters around it to let us find it again after
             * formatting and change its size.
             */
            //mAmPmStyle默认值是AM_PM_STYLE_GONE
            if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
                int a = -1;
                boolean quoted = false;
                for (int i = 0; i < format.length(); i++) {
                    char c = format.charAt(i);

                    if (c == '\'') {
                        quoted = !quoted;
                    }
                    if (!quoted && c == 'a') {
                        a = i;
                        break;
                    }
                }

                if (a >= 0) {
                    // Move a back so any whitespace before AM/PM is also in the alternate size.
                    final int b = a;
                    while (a > 0 && Character.isWhitespace(format.charAt(a-1))) {
                        a--;
                    }
                    format = format.substring(0, a) + MAGIC1 + format.substring(a, b)
                        + "a" + MAGIC2 + format.substring(b + 1);
                }
            }
//            mClockFormat = new SimpleDateFormat(format);
            //改成想要的时间格式
            mClockFormat = new SimpleDateFormat("HH时mm分");
        }
        String result = mClockFormat.format(mCalendar.getTime());

        if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
            int magic1 = result.indexOf(MAGIC1);
            int magic2 = result.indexOf(MAGIC2);
            //修改自己的格式,不包含magic1/magic2,不会走这里的逻辑
            if (magic1 >= 0 && magic2 > magic1) {
                SpannableStringBuilder formatted = new SpannableStringBuilder(result);
                if (mAmPmStyle == AM_PM_STYLE_GONE) {
                    formatted.delete(magic1, magic2+1);
                } else {
                    if (mAmPmStyle == AM_PM_STYLE_SMALL) {
                        CharacterStyle style = new RelativeSizeSpan(0.7f);
                        formatted.setSpan(style, magic1, magic2,
                                          Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
                    }
                    formatted.delete(magic2, magic2 + 1);
                    formatted.delete(magic1, magic1 + 1);
                }
                return formatted;
            }
        }

        return result;

    }

效果

Untitled 2.png