1:代码核心类
SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
SystemUI/src/com/android/systemui/statusbar/DismissView.java
SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
SystemUI/src/com/android/systemui/SwipeHelper.java
SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
2:通知显示的类(NotificationStackScrollLayout)
有通知时,会添加到这个类上,并显示
3:删除所有按钮的显示流程(DismissView.java)
这个控件是动态添加到NotificationStackScrollLayout中的,其代码流程如下:
PhoneStatusBar.java
@Override
public void createAndAddWindows() {
addStatusBarWindow();
}
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = new StatusBarWindowManager(mContext);
mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,
mHeadsUpManager);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
protected PhoneStatusBarView makeStatusBarView() {
...
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setPhoneStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setHeadsUpManager(mHeadsUpManager);
mGroupManager.setOnGroupChangeListener(mStackScroller);
inflateOverflowContainer();
inflateEmptyShadeView();
inflateDismissView();
mExpandedContents = mStackScroller;
....
}
private void inflateDismissView() {
mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
mDismissView.setOnButtonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_DISMISS_ALL_NOTES);
clearAllNotifications();
}
});
mStackScroller.setDismissView(mDismissView);
}
其上的makeStatusBarView()函数很长,只贴了关键代码。在inflateDismissView()的函数中初始化了DismissView的对象并设置到mStackScroller(NotificationStackScrollLayout.java类)中。
mDismissView.setOnButtonClickListener(...)设置了点击事件的监听。
DismissView.java :
public void setOnButtonClickListener(OnClickListener listener) {
mContent.setOnClickListener(listener);
}
4:删除所有按钮的显示与隐藏
DismissView 删除控件是随着有无通知消息和消息属性显示或隐藏的,代码流程如下:
PhoneStatusBar.java的代码:
@Override
protected void updateNotifications() {
Log.d("kaymediashot2", "updateNotifications:" );
mNotificationData.filterAndSort();
updateNotificationShade();
mIconController.updateNotificationIcons(mNotificationData);
}
private void updateNotificationShade() {
...
updateRowStates();
updateSpeedbump();
updateClearAll(); ///这里
updateEmptyShadeView();
updateQsExpansionEnabled();
mShadeUpdates.check();
}
private void updateClearAll() {
boolean showDismissView =
mState != StatusBarState.KEYGUARD &&
mNotificationData.hasActiveClearableNotifications();
mStackScroller.updateDismissView(showDismissView);
}
之后通过mStackScroller.updateDismissView(showDismissView)跳转到NotificationStackScrollLayout.java中进行判断显示还是隐藏。
public void updateDismissView(boolean visible) {
int oldVisibility = mDismissView.willBeGone() ? GONE : mDismissView.getVisibility();
int newVisibility = visible ? VISIBLE : GONE;
if (oldVisibility != newVisibility) {
if (newVisibility != GONE) {
if (mDismissView.willBeGone()) {
mDismissView.cancelAnimation();
} else {
mDismissView.setInvisible();
}
mDismissView.setVisibility(newVisibility);
mDismissView.setWillBeGone(false);
updateContentHeight();
notifyHeightChangeListener(mDismissView);
} else {
Runnable dimissHideFinishRunnable = new Runnable() {
@Override
public void run() {
mDismissView.setVisibility(GONE);
mDismissView.setWillBeGone(false);
updateContentHeight();
notifyHeightChangeListener(mDismissView);
}
};
if (mDismissView.isButtonVisible() && mIsExpanded && mAnimationsEnabled) {
mDismissView.setWillBeGone(true);
mDismissView.performVisibilityAnimation(false, dimissHideFinishRunnable);
} else {
dimissHideFinishRunnable.run();
}
}
}
}
5:滑动通知消息显示设置图标的流程
NotificationStackScrollLayout.java中,代码如下:
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
|| ev.getActionMasked()== MotionEvent.ACTION_UP;
handleEmptySpaceClick(ev);
boolean expandWantsIt = false;
if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion) {
if (isCancelOrUp) {
mExpandHelper.onlyObserveMovements(false);
}
boolean wasExpandingBefore = mExpandingNotification;
expandWantsIt = mExpandHelper.onTouchEvent(ev);
if (mExpandedInThisMotion && !mExpandingNotification && wasExpandingBefore
&& !mDisallowScrollingInThisMotion) {
dispatchDownEventToScroller(ev);
}
}
boolean scrollerWantsIt = false;
if (mIsExpanded && !mSwipingInProgress && !mExpandingNotification
&& !mDisallowScrollingInThisMotion) {
scrollerWantsIt = onScrollTouch(ev);
}
boolean horizontalSwipeWantsIt = false;
if (!mIsBeingDragged
&& !mExpandingNotification
&& !mExpandedInThisMotion
&& !mOnlyScrollingInThisMotion
&& !mDisallowDismissInThisMotion) {
horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);//这里显示通知的设置图标
}
return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev);
}
mSwipeHelper.onTouchEvent(ev);这里进入SwipeHelper进行处。
SwipeHelper.java:
public boolean onTouchEvent(MotionEvent ev) {
if (mLongPressSent) {
return true;
}
if (!mDragging) {
if (mCallback.getChildAtPosition(ev) != null) {
// We are dragging directly over a card, make sure that we also catch the gesture
// even if nobody else wants the touch event.
onInterceptTouchEvent(ev);
return true;
} else {
// We are not doing anything, make sure the long press callback
// is not still ticking like a bomb waiting to go off.
removeLongPressCallback();
return false;
}
}
mVelocityTracker.addMovement(ev);
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_MOVE:
if (mCurrView != null) {
float delta = getPos(ev) - mInitialTouchPos;
float absDelta = Math.abs(delta);
if (absDelta >= getFalsingThreshold()) {
mTouchAboveFalsingThreshold = true;
}
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
float size = getSize(mCurrView);
float maxScrollDistance = 0.25f * size;
if (absDelta >= size) {
delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
} else {
delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
}
}
setTranslation(mCurrView, mTranslation + delta);//这里
updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed);
onMoveUpdate(mCurrView, mTranslation + delta, delta);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mCurrView == null) {
break;
}
mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, getMaxVelocity());
float velocity = getVelocity(mVelocityTracker);
if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
if (isDismissGesture(ev)) {
// flingadingy
dismissChild(mCurrView, velocity,
!swipedFastEnough() /* useAccelerateInterpolator */);
} else {
// snappity
mCallback.onDragCancelled(mCurrView);
snapChild(mCurrView, 0 /* leftTarget */, velocity);
}
mCurrView = null;
}
mDragging = false;
break;
}
return true;
}
setTranslation(mCurrView, mTranslation + delta);;继续处理滑动,其的具体执行位置在NotificationStackScrollLayout.java中的NotificationSwipeHelper中;
,代码如下:
@Override
public void setTranslation(View v, float translate) {
((ExpandableView) v).setTranslation(translate);
}
((ExpandableView) v).setTranslation(translate);
ExpandableView.java
/**
* Sets the translation of the view.
*/
public void setTranslation(float translation) {
setTranslationX(translation);
}
setTranslationX(translation);的运行位置在ExpandableNotificationRow.java文件中:
@Override
public void setTranslation(float translationX) {
if (areGutsExposed()) {
// Don't translate if guts are showing.
return;
}
// Translate the group of views
for (int i = 0; i < mTranslateableViews.size(); i++) {
if (mTranslateableViews.get(i) != null) {
mTranslateableViews.get(i).setTranslationX(translationX);
}
}
invalidateOutline();
if (mSettingsIconRow != null) {
mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
}
}
mSettingsIconRow是NotificationSettingsIconRow.java类:
public void updateSettingsIcons(final float transX, final float size) {
if (mAnimating || !mSettingsFadedIn) {
// Don't adjust when animating, or if the gear hasn't been shown yet.
return;
}
final float fadeThreshold = size * 0.3f;
final float absTrans = Math.abs(transX);
float desiredAlpha = 0;
if (absTrans == 0) {
desiredAlpha = 0;
} else if (absTrans <= fadeThreshold) {
desiredAlpha = 1;
} else {
desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
}
setGearAlpha(desiredAlpha);
}
public void setGearAlpha(float alpha) {
if (alpha == 0) {
mSettingsFadedIn = false; // Can fade in again once it's gone.
setVisibility(View.INVISIBLE);
} else {
setVisibility(View.VISIBLE);
}
mGearIcon.setAlpha(alpha);
}
这里通过透明值来设置mGearIcon(按钮控件变量)的父类的显示与隐藏,并设置其本身的透明值.