神刀安全网

6AppBarLayout与scrollFlags

6AppBarLayout与scrollFlags

AppBarLayout分组

这里说过AppBarLayout可以分为可滑出和不可滑出上下2部分,其实细致一点可以分三部分,如下图所示,下滑最后出现(part 1),下滑立刻出现(part2),无法滑出(part3),其中part1和2合起来就是可以滑出的部分。

6AppBarLayout与scrollFlags

xml代码如下

   <android.support.design.widget.AppBarLayout         android:layout_width="match_parent"         android:theme="@style/AppTheme.AppBarOverlay"         android:layout_height="wrap_content">           <TextView             android:gravity="center"             app:layout_scrollFlags="scroll"             android:textSize="20sp"             android:text="下滑最后出现"             android:background="#447700"             android:layout_width="match_parent"             android:layout_height="70dp" />           <TextView             android:gravity="center"             app:layout_scrollFlags="scroll|enterAlways"             android:textSize="20sp"             android:text="下滑立刻出现"             android:background="#004477"             android:layout_width="match_parent"             android:layout_height="100dp" />           <TextView             android:gravity="center"             android:textSize="20sp"             android:text="无法滑出去"             android:background="#ff0000"             android:layout_width="match_parent"             android:layout_height="100dp" />      </android.support.design.widget.AppBarLayout>

主要关注layout_scrollFlags,可以看到part3无scroll标志,代表无法滚出;part2是scroll|enterAlways代表下滑立刻出现;part1是scroll下滑的时候最后出现。
为什么会这样,主要和mDownPreScrollRange、mDownScrollRange有关,可以看下边代码。mDownPreScrollRange控制着嵌套滑动的父view的onNestedPreScroll部分可滑距离,mDownScrollRange控制着嵌套滑动的父view的onNestedScroll部分。

//AppBarLayout     /**      * Return the scroll range when scrolling down from a nested pre-scroll.      */     private int getDownNestedPreScrollRange() {         if (mDownPreScrollRange != INVALID_SCROLL_RANGE) {             // If we already have a valid value, return it             return mDownPreScrollRange;         }          int range = 0;         for (int i = getChildCount() - 1; i >= 0; i--) {             final View child = getChildAt(i);             final LayoutParams lp = (LayoutParams) child.getLayoutParams();             final int childHeight = child.getMeasuredHeight();             final int flags = lp.mScrollFlags;              if ((flags & LayoutParams.FLAG_QUICK_RETURN) == LayoutParams.FLAG_QUICK_RETURN) {                 // First take the margin into account                 range += lp.topMargin + lp.bottomMargin;                 // The view has the quick return flag combination...                 if ((flags & LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED) != 0) {                     // If they're set to enter collapsed, use the minimum height                     range += ViewCompat.getMinimumHeight(child);                 } else if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {                     // Only enter by the amount of the collapsed height                     range += childHeight - ViewCompat.getMinimumHeight(child);                 } else {                     // Else use the full height                     range += childHeight;                 }             } else if (range > 0) {                 // If we've hit an non-quick return scrollable view, and we've already hit a                 // quick return view, return now                 break;             }         }         return mDownPreScrollRange = Math.max(0, range - getTopInset());     }      /**      * Return the scroll range when scrolling down from a nested scroll.      */     private int getDownNestedScrollRange() {         if (mDownScrollRange != INVALID_SCROLL_RANGE) {             // If we already have a valid value, return it             return mDownScrollRange;         }          int range = 0;         for (int i = 0, z = getChildCount(); i < z; i++) {             final View child = getChildAt(i);             final LayoutParams lp = (LayoutParams) child.getLayoutParams();             int childHeight = child.getMeasuredHeight();             childHeight += lp.topMargin + lp.bottomMargin;              final int flags = lp.mScrollFlags;              if ((flags & LayoutParams.SCROLL_FLAG_SCROLL) != 0) {                 // We're set to scroll so add the child's height                 range += childHeight;                  if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {                     // For a collapsing exit scroll, we to take the collapsed height into account.                     // We also break the range straight away since later views can't scroll                     // beneath us                     range -= ViewCompat.getMinimumHeight(child) + getTopInset();                     break;                 }             } else {                 // As soon as a view doesn't have the scroll flag, we end the range calculation.                 // This is because views below can not scroll under a fixed view.                 break;             }         }         return mDownScrollRange = Math.max(0, range);     }

实际效果如下所示

6AppBarLayout与scrollFlags

此时
mTotalScrollRange=56dp+70dp+100dp (part1+part2,其实toolbar也是属于part1的)
mDownPreScrollRange=100dp(part2)
mDownScrollRange=56dp+70dp+100dp

scrollFlags

-scroll代表可滚动,被标注后算到mTotalScrollRange里,要写其他flag必须先写scroll才有效
-enterAlways下滑,这个view立刻跑出来,算在mDownPreScrollRange内
-enterAlwaysCollapsed下滑的时候在onNestedPreScroll阶段先滑出一个最小高度,这个参数我试了下都存在一定问题,没找到一个合适的场景。用enterAlwaysCollapsed必须先写 scroll和enterAlways
-exitUntilCollapsed 向上滚动直到折叠,往往用于CollapsingToolbarLayout内,后边会有介绍

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » 6AppBarLayout与scrollFlags

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址