6AppBarLayout與scrollFlags
AppBarLayout分組
在這里說過AppBarLayout可以分為可滑出和不可滑出上下2部分,其實(shí)細(xì)致一點(diǎn)可以分三部分,如下圖所示,下滑最后出現(xiàn)(part 1),下滑立刻出現(xiàn)(part2),無法滑出(part3),其中part1和2合起來就是可以滑出的部分。
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="下滑最后出現(xiàn)"
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="下滑立刻出現(xiàn)"
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>
主要關(guān)注layout_scrollFlags,可以看到part3無scroll標(biāo)志,代表無法滾出;part2是scroll|enterAlways代表下滑立刻出現(xiàn);part1是scroll下滑的時(shí)候最后出現(xiàn)。
為什么會(huì)這樣,主要和mDownPreScrollRange、mDownScrollRange有關(guān),可以看下邊代碼。mDownPreScrollRange控制著嵌套滑動(dòng)的父view的onNestedPreScroll部分可滑距離,mDownScrollRange控制著嵌套滑動(dòng)的父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);
}
實(shí)際效果如下所示
此時(shí)
mTotalScrollRange=56dp+70dp+100dp (part1+part2,其實(shí)toolbar也是屬于part1的)
mDownPreScrollRange=100dp(part2)
mDownScrollRange=56dp+70dp+100dp
scrollFlags
-scroll代表可滾動(dòng),被標(biāo)注后算到mTotalScrollRange里,要寫其他flag必須先寫scroll才有效
-enterAlways下滑,這個(gè)view立刻跑出來,算在mDownPreScrollRange內(nèi)
-enterAlwaysCollapsed下滑的時(shí)候在onNestedPreScroll階段先滑出一個(gè)最小高度,這個(gè)參數(shù)我試了下都存在一定問題,沒找到一個(gè)合適的場(chǎng)景。用enterAlwaysCollapsed必須先寫 scroll和enterAlways
-exitUntilCollapsed 向上滾動(dòng)直到折疊,往往用于CollapsingToolbarLayout內(nèi),后邊會(huì)有介紹