通话过程中,因未完全遮挡距离传感器导致屏幕亮屏,屏幕亮屏后耳朵附近误触状态栏导致状态栏下拉
状态栏下拉的情况有两种:一种为拖动状态栏下拉,另一种为在非锁屏下点击两次状态栏使状态栏下拉(第一次点击状态栏时,状态栏下拉为展开动画此时动画展示完成后会完全收回状态栏,在动画展示时进行第二次点击,则此时状态栏会完全展开)
由于在通话过程中大概率还是点击导致状态栏下拉,拖动导致下拉的概率较低,所以在状态栏点击功能方面解决该问题,在点击情况下由于完整的下拉的前提是状态栏处于展开动画,所以不显示状态栏的展开展示动画即可删除状态栏的点击下拉功能
2. 状态栏点击事件分发点击导致状态栏下拉,其处理逻辑必然是从Down事件及Up事件的处理逻辑开始,所以可以先查看状态栏点击事件的分发过程
从View层面开始描述点击事件的分发过程
点击事件由ViewGroup传递到View,状态栏的View则是PhoneStatusBarView,因此查看PhoneStatusBarView的点击事件分发
public boolean onTouchEvent(MotionEvent event) {
boolean barConsumedEvent = mBar.interceptTouchEvent(event);
if (DEBUG_GESTURES) {
if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH,
event.getActionMasked(), (int) event.getX(), (int) event.getY(),
barConsumedEvent ? 1 : 0);
}
}
return barConsumedEvent || super.onTouchEvent(event);
}
此处并没有进行事件的处理,继续向下调用super.onTouchEvent
PhoneStatusBarView的父类是PanelBar,则调用到PanelBar的onTouchEvent方法
public boolean onTouchEvent(MotionEvent event) {
// Allow subclasses to implement enable/disable semantics
if (!panelEnabled()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
}
return false;
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
final PanelViewController panel = mPanel;
if (panel == null) {
// panel is not there, so we'll eat the gesture
Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
return true;
}
boolean enabled = panel.isEnabled();
if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
(enabled ? "" : " (disabled)"));
if (!enabled) {
// panel is disabled, so we'll eat the gesture
Log.v(TAG, String.format(
"onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
panel, (int) event.getX(), (int) event.getY()));
return true;
}
}
return mPanel == null || mPanel.getView().dispatchTouchEvent(event);
}
此时有做Down手势的判断但是由于 panel 不等于 null,且panel.isEnabled等于true,所以无法进入if判断,不会返回true,返回true时即事件被消费掉,不会再向下传递了,但是此时继续向下传递至mPanel.getView().dispatchTouchEvent(event);
事件继续进行分发,dispatchTouchEvent过程中若事件没有被拦截,则会走onInterceptTouchEvent(ViewGroup的特有方法),后面走onTouch,最后则是onTouchEvent
事件最终被传递到NotificationPanelViewController的onTouch方法
public boolean onTouch(View v, MotionEvent event) {
//......
handled |= super.onTouch(v, event);
return !mDozing || mPulsing || handled;
}
前面经过很多判断,最终到super.onTouch, 其父类为PanelViewController
public boolean onTouch(View v, MotionEvent event) {
//......
//......
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
startExpandMotion(x, y, false , mExpandedHeight);
mJustPeeked = false;
mMinExpandHeight = 0.0f;
mPanelClosedOnDown = isFullyCollapsed();
mHasLayoutedSinceDown = false;
mUpdateFlingOnLayout = false;
mMotionAborted = false;
mPeekTouching = mPanelClosedOnDown;
mDownTime = SystemClock.uptimeMillis();
mTouchAboveFalsingThreshold = false;
mCollapsedAndHeadsUpOnDown =
isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
addMovement(event);
//......
//锁屏界面无法点击下拉状态栏
if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()
&& !mStatusBar.isBouncerShowing()) {
startOpening(event);
}
break;
//......
case MotionEvent.ACTION_UP:
addMovement(event);
endMotionEvent(event, x, y, false );
break;
}
return !mGestureWaitForTouchSlop || mTracking;
}
这里就是真正的Down Up事件的处理逻辑,原生注释显示,如果用户只是简单的点击一下会快速看到shade,在收到Down事件的时候判断,如果此时处于完全收起状态,并且没在点按状态,并且不是锁屏界面,则此时会走startOpening()
private void startOpening(MotionEvent event) {
runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
false );
//......
}
在startOpening()中主要调用了runPeekAnimation,这也就是点按时快速展开shade的动画,在调用的时候会传入此动画的高度
如果是按下状态时,因为展开的动画只有状态栏那么高,所以高度仅仅是45, 在Up时间的处理过程中会判断如果Down和Up的时间不超过400ms ,则依旧会调用该动画并重新设置较高的高度
private void runPeekAnimation(long duration, float peekHeight, boolean collapseWhenFinished) {
mPeekHeight = peekHeight;
if (mHeightAnimator != null) {
return;
}
if (mPeekAnimator != null) {
mPeekAnimator.cancel();
}
mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight).setDuration(
duration);
mPeekAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
mPeekAnimator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@Override
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mPeekAnimator = null;
if (!mCancelled && collapseWhenFinished) {
mView.postonAnimation(mPostCollapseRunnable);
}
}
});
notifyExpandingStarted();
mPeekAnimator.start();
mJustPeeked = true;
}
mPeekAnimator 即快速展开Shade的动画,如果要删除该动画方法较多,但是最终使用如下方法
mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", 0f).setDuration(
duration);
仅调整动画高度,将Down时间及Up时间时的动画高度都调为0f,所以动画也就不会显示出来,动画不显示,第二次的点击事件也不会造成状态栏完整下拉


