Android 9 SystemUI通知栏中“通知条目”的位置更新与NotificationShelf、FooterView重叠

Android 9 SystemUI中下拉展开时,NotificationShelf、FooterView会发生重叠。
下拉展开时,NotificationStackScrollLayout中会监听view变化,

 private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
            = new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            updateForcedScroll(); 
            updateChildren(); //更新所有子view
            mChildrenUpdateRequested = false;
            getViewTreeObserver().removeOnPreDrawListener(this);
            return true;
        }
    };
 /**
     * Updates the children views according to the stack scroll algorithm. Call this whenever
     * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
     */
    private void updateChildren() {
        updateScrollStateForAddedChildren();
        mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
                ? 0
                : mScroller.getCurrVelocity()); //获取滚动速度、设置到 mAmbientState中
        mAmbientState.setScrollY(mOwnScrollY);
        mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState); //循环更新子view位置、这里每次更新所有子view位置
        if (!isCurrentlyAnimating() && !mNeedsAnimation) {
            applyCurrentState();
        } else {
            startAnimationToState();
        }
    }
public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
        // The state of the local variables are saved in an algorithmState to easily subdivide it
        // into multiple phases.
        StackScrollAlgorithmState algorithmState = mTempAlgorithmState;

        // First we reset the view states to their default values.
        resultState.resetViewStates(); //初始化子view 信息,如何view的state是null, 则创建。数据包含height、gone、alpha等

        initAlgorithmState(resultState, algorithmState, ambientState);//Initialize the algorithm state like updating the visible children.

        updatePositionsForState(resultState, algorithmState, ambientState);

        updateZValuesForState(resultState, algorithmState, ambientState);

        updateHeadsUpStates(resultState, algorithmState, ambientState);

        handleDraggedViews(ambientState, resultState, algorithmState);
        updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
        updateClipping(resultState, algorithmState, ambientState);
        updateSpeedBumpState(resultState, algorithmState, ambientState);
        updateShelfState(resultState, ambientState);
        getNotificationChildrenStates(resultState, algorithmState, ambientState);
    }

下面是更新具体的view

/**
    * Determine the positions for the views. This is the main part of the algorithm.
    *
    * @param resultState The result state to update if a change to the properties of a child occurs
    * @param algorithmState The state in which the current pass of the algorithm is currently in
    * @param ambientState The current ambient state
    */
   private void updatePositionsForState(StackScrollState resultState,
           StackScrollAlgorithmState algorithmState, AmbientState ambientState) {

       // The y coordinate of the current child.
       float currentYPosition = -algorithmState.scrollY;
       int childCount = algorithmState.visibleChildren.size();
       for (int i = 0; i < childCount; i++) {
           currentYPosition = updateChild(i, resultState, algorithmState, ambientState,
                   currentYPosition);
       }
   }
   protected float updateChild(int i, StackScrollState resultState,
           StackScrollAlgorithmState algorithmState, AmbientState ambientState,
           float currentYPosition) {
       ExpandableView child = algorithmState.visibleChildren.get(i);
       ExpandableViewState childViewState = resultState.getViewStateForView(child);
       childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
       int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
       int childHeight = getMaxAllowedChildHeight(child);
       childViewState.yTranslation = currentYPosition;
       boolean isFooterView = child instanceof FooterView;
       boolean isEmptyShadeView = child instanceof EmptyShadeView;

       childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
       float inset = ambientState.getTopPadding() + ambientState.getStackTranslation();
       if (i <= algorithmState.getIndexOfExpandingNotification()) {
           inset += ambientState.getExpandAnimationTopChange();
       }
       if (child.mustStayOnScreen() && childViewState.yTranslation >= 0) {
           // Even if we're not scrolled away we're in view and we're also not in the
           // shelf. We can relax the constraints and let us scroll off the top!
           float end = childViewState.yTranslation + childViewState.height + inset; //inset 上面的间距
           childViewState.headsUpIsVisible = end < ambientState.getMaxHeadsUpTranslation();
       }
       if (isFooterView) {
           if(MODIFY_ON) {
               float footerY = Math.min(childViewState.yTranslation, ambientState.getInnerHeight() - childHeight);
               childViewState.yTranslation = Math.max(footerY, childHeight); //56-48
           } else {
               childViewState.yTranslation = Math.min(childViewState.yTranslation,
                       ambientState.getInnerHeight() - childHeight);
           }

       } else if (isEmptyShadeView) {
           childViewState.yTranslation = ambientState.getInnerHeight() - childHeight
                   + ambientState.getStackTranslation() * 0.25f;
       } else {
           clampPositionToShelf(child, childViewState, ambientState);
       }

       currentYPosition = childViewState.yTranslation + childHeight + paddingAfterChild;
       if (currentYPosition <= 0) {
           childViewState.location = ExpandableViewState.LOCATION_HIDDEN_TOP;
       }
       if (childViewState.location == ExpandableViewState.LOCATION_UNKNOWN) {
           Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
       }

       childViewState.yTranslation += inset;  //childViewState.yTranslation 决定最终显示位置
       return currentYPosition;
   }

这里MODIFY_ON修改的内容, childViewState.yTranslation 这是赋值,真正启作用是这个 applyCurrentState()
会调用到NotificationShelf、FooterView、ExpandableNotificationRow view的 applyToView()函数。位置才会变化

 /**
  * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
  * The properties are only applied if they effectively changed.
  */
 public void apply() {
     int numChildren = mHostView.getChildCount();
     for (int i = 0; i < numChildren; i++) {
         ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
         ExpandableViewState state = mStateMap.get(child);
         if (state == null) {
             Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
                     "to the hostView");
             continue;
         }
         if (state.gone) {
             continue;
         }
         state.applyToView(child); 
     }
 }

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值