居中显示
看状态栏的布局文件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自己加了右内边距
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);
}
效果
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;
}
效果