FormLayoutManager首頁,裏面有github地址
目錄
前言
認真看過FormLayoutManager完整的代碼的朋友們,應該發現有一個startShow的方法。我們的表格默認起始顯示左上角的位置,而這個方法就是提供讓大家設置默認起始顯示位置最右邊或最底部或最右底部。
public void startShow(@StartShowType int type){
mStartShowType = type;
}
看代碼就知道我們只能傳StartShowType的值,這個FormLayoutManager內部的一個接口,可以看到,我只提供右邊和底部的值。
public @interface StartShowType {
// 右邊
int RIGHT = 1 << 1;
// 底部
int BOTTOM = 1 << 2;
}
使用
打開demo的TestFormActivity,找到startShow的代碼
// 起始位置滾動到右底部
mLayoutManager.startShow(FormLayoutManager.StartShowType.RIGHT | FormLayoutManager.StartShowType.BOTTOM);
要滾到右下角,就如上代碼設置就ok了。要滾到右上角就直接設置右邊,要滾到左下角就只設置底部就ok了。
代碼
那是怎麼實現讓RecyclerView默認起始顯示的時候是滾到右或底部的呢?在FormLayoutManager的第一篇解說裏面有提過這樣一個方法handleLayoutChildren,而RecyclerView第一次顯示數據的時候,這個方法裏面的一段代碼會把itemview插進RecyclerView
here:
for (int row = firstShowRow; row < visibleRowCount + firstShowRow; row++) {
for (int column = firstShowCol; column < visibleColumnCount + firstShowCol; column++) {
int itemPosition = row * mColumnCount + column;
if (itemPosition >= mItemRects.size()){
break here;
}
Rect rect = mItemRects.get(itemPosition);
if (!Rect.intersects(getVisibleArea(), rect)){
continue;
}
View view = recycler.getViewForPosition(itemPosition);
addView(view);
//addView後一定要measure,先measure再layout
measureChildWithMargins(view, 0, 0);
layoutDecorated(view, rect.left - mSumDx, rect.top - mSumDy, rect.right - mSumDx, rect.bottom - mSumDy);
}
}
關鍵是我們佈局這個itemview的位置的layoutDecorated方法,可以看到裏面有用到mSumDx和mSumDy,這兩個值正是記錄表格滾動過的水平距離和垂直距離。那如果默認mSumDx和mSumDy是0的話,那當然就是默認沒滾動過,就是左上角的位置了。歸根到底,想RecyclerView起始的顯示位置發生變化,就一開始修改mSumDx或mSumDy的值。
那我是怎樣算出mSumDx和mSumDy的值並修改的呢,有請下面分解。
目光來到handleLayoutChildren裏面,會發現有一段這樣的代碼
if ((mStartShowType & RIGHT) > 0 && mDefaultStartDx == 0){
mDefaultStartDx = mTotalWidth - getHorizontalSpace();
mSumDx = mDefaultStartDx;
}
if ((mStartShowType & BOTTOM) > 0 && mDefaultStartDy == 0){
mDefaultStartDy = mTotalHeight - getVerticalSpace();
mSumDy = mDefaultStartDy;
}
這兩個判斷,一個就是判斷startShow方法是否有設置了RIGHT,一個就是判斷是否有設置了BOTTOM,我就抽一個來說。
當我們知道用戶設置了默認起始顯示到最右邊時,那就要算出表格從最左邊滾到最右邊要滑動多少距離。其實就是用表格整個的寬減去RecyclerView可視區域的寬,然後設置到mDefaultStartDx,再設置到mSumDx,沒錯有個mDefaultStartDx。由於表格在滑動的時候mSumDx的值會發生變化的,所以我們找另外一個變量mDefaultStartDx來記錄默認要滾的距離,那記錄下來幹什麼呢?
// 刷新數據後想到回到起始位置,刷新數據前調用reset
public void reset(){
mSumDx = mDefaultStartDx;
mSumDy = mDefaultStartDy;
mItemCount = 0;
}
沒錯,我提供了一個重置的方法。只要在FormLayoutManager執行onLayoutChildren之前調用reset方法,表格就會重置到默認的起始位置。那什麼時候FormLayoutManager會進入onLayoutChildren的方法呢,在第一篇文章我也提過,就是當adapter刷新數據或者RecyclerView從gone到可視的時候都會進。
擴展
我只提供滾到四個角邊緣的方法,因爲這種比較常見。如果你是想讓表格默認起始位置滾到任意地方的話,我建議的做法是繼承FormLayoutManager寫一個新的類。mSumDx,mSumdy,mDefaultStartDx,mDefaultStartDy這個四個值的關鍵字我寫的都是protected,所以在你新的類那裏提供方法自己去修改這四個值就行了。自己把應該要滾的距離算準了,然後調用你提供的方法就OK了。