statusbar状态栏的相关ui嵌套简单说明梳理下:
父布局
/frameworks/base/packages/SystemUI/res/layout/super_notification_shade.xml
滑动布局相关控制父布局
/frameworks/base/packages/SystemUI/res/layout/status_bar_expanded.xml
用户状态、时钟、日期等布局
/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
时钟布局
/pep/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
日期等布局
/pep/frameworks/base/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
需求说明:
当设备屏幕较小时例如穿戴手表设备,屏幕上要显示较大的钟表ui但是依然套用系统的锁屏系统,就需要给时钟ui扩展下空间,这里的核心是删除不必要的元素ui,以及缩减padding、margin。
隐藏:keyguard_status_area.xml
其他的位置的话看需求修改,这里重点关注keyguard_clock_switch.xml中的android:id="@+id/clock_view",刚开始只是单纯增加长宽大小,但是很局限只有整块屏蔽的上半部分显示,若是高度设置过大,还会出现时钟ui不显示的问题(目前大概推测是因为ui高度过大,在整个滑动逻辑中部分判断逻辑直接影藏了这个keyguard_status_view.xml,未证实)。
通过测试整个时钟刷新流程发现了,关于keyguard_status_view.xml的ui,也就是com.android.keyguard.KeyguardStatusView这个类设置了最低margin值,导致只能在屏幕上半部分展示:/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java中的getExpandedClockPosition()方法
/**
* Vertically align the clock and the shade in the available space considering only
* a percentage of the clock height defined by {@code CLOCK_HEIGHT_WEIGHT}.
* @return Clock Y in pixels.
*/
public int getExpandedClockPosition() {
final int availableHeight = mMaxShadeBottom - mMinTopMargin;
final int containerCenter = mMinTopMargin + availableHeight / 2;
float y = containerCenter - mKeyguardStatusHeight * CLOCK_HEIGHT_WEIGHT
- mClockNotificationsMargin - mNotificationStackHeight / 2;
if (y < mMinTopMargin) {
y = mMinTopMargin;
}
// Don't allow the clock base to be under half of the screen
final float maxClockY = getMaxClockY();
if (y > maxClockY) {
y = maxClockY;
}
//************重点修改部分:直接给y赋值,我这里使用的是keyguardClockTopMargin=res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);***********************************
y=keyguardClockTopMargin;
return (int) y;
}
//把最大高度修改为mHeight 而不是mHeight/2
private int getMaxClockY() {
return mHeight - mKeyguardStatusHeight - mClockNotificationsMargin;
}
修改这两个部分后,就可以去重新修改keyguard_clock_switch.xml下面id:clock_view长宽布局大小了
上述就是解决时钟ui全屏显示的方法供参考。
下面分析下系统如何进行限制KeyguardStatusView只在屏幕上半部分展示的流程:
提示:写这部分时,代码逻辑有些忘了,只说下大概设计到的逻辑,具体的话自己打log测试下吧
KeyguardStatusView在这个类中加载:/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
//该方法中设计到对KeyguardStatusView的长宽、动画一些绑定执行
private void positionClockAndNotifications() {
boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
boolean animateClock = animate || mAnimateNextPositionUpdate;
int stackScrollerPadding;
if (mBarState != StatusBarState.KEYGUARD) {
stackScrollerPadding = getUnlockedStackScrollerPadding();
} else {
int totalHeight = mView.getHeight();
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
int clockPreferredY = mKeyguardStatusView.getClockPreferredY(totalHeight);
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
final boolean
hasVisibleNotifications =
!bypassEnabled && mNotificationStackScroller.getVisibleNotificationCount() != 0;
mKeyguardStatusView.setHasVisibleNotifications(hasVisibleNotifications);
//涉及ui的长宽以及位置,相关重点第七个参数clockPreferredY数据计算
mClockPositionAlgorithm.setup(mStatusBarMinHeight, totalHeight - bottomPadding,
mNotificationStackScroller.getIntrinsicContentHeight(), getExpandedFraction(),
totalHeight, (int) (mKeyguardStatusView.getHeight() - mShelfHeight / 2.0f
- mDarkIconSize / 2.0f), clockPreferredY, hasCustomClock(),
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
bypassEnabled, getUnlockedStackScrollerPadding());
//数据赋值执行
mClockPositionAlgorithm.run(mClockPositionResult);
PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X,
mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
//Y坐标动画展示,以及在手动上滑锁屏屏幕时,上移KeyguardStatusView动画
PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y,
mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock);
updateNotificationTranslucency();
updateClock();
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
}
mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
mStackScrollerMeasuringPass++;
requestScrollerTopPaddingUpdate(animate);
mStackScrollerMeasuringPass = 0;
mAnimateNextPositionUpdate = false;
}
动画相关类/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
public static <T extends View> void setProperty(final T view,
AnimatableProperty animatableProperty, float newEndValue,
AnimationProperties properties, boolean animated) {
int animatorTag = animatableProperty.getAnimatorTag();
ValueAnimator previousAnimator = ViewState.getChildTag(view, animatorTag);
if (previousAnimator != null || animated) {
startAnimation(view, animatableProperty, newEndValue, animated ? properties : null);
} else {
//走的是这个方法
// no new animation needed, let's just apply the value
animatableProperty.getProperty().set(view, newEndValue);
}
}
。。。。。。
具体的下次一定