
Animation.gif
在開發(fā)項目的時候,很多時候都需要用到上圖這種功能, 章節(jié)列表。 但坑爹的是,這種控件在ios中原生自帶, 但android卻沒有自帶。這時候又不免去github里面去找一些開源庫。所以說, 開發(fā)android的同學需要做各種ios的特效。
![H$RK3[L)N}]%$RX5HK)HTG.gif
github這種開源庫灰常多,但開源庫畢竟是別人的,能自己弄出來當然是最好的。下面我就分享下我的實現(xiàn)思路。
功能需求:
1.章節(jié)標題欄需要固定在頂部。
2.固定的章節(jié)標題欄可以隨著列表的章節(jié)標題欄進行相應(yīng)的移動。
實現(xiàn):
1.固定章節(jié)欄: 采用famelayout布局, 在RecyclerView 外層添加一個章節(jié)欄標題,一直固定在頂部。
2.固定章節(jié)欄隨列表章節(jié)欄移動:當判斷下個進入頂部是列表章節(jié)標題的時候 ,對固定章節(jié)欄進行相應(yīng)的布局調(diào)整。
主要的實現(xiàn)代碼:
public class SectionRecyclerActivity extends AppCompatActivity {
..........
@Override
protected void onCreate(Bundle savedInstanceState) {
..........
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int position = (mLayoutManager.findFirstVisibleItemPosition() < 0) ? 0 : mLayoutManager.findFirstVisibleItemPosition();
int totalSize = mLayoutManager.getItemCount();
if (mAdapter.getItemViewType(position) == TITLE_TYPE) {
mTopTitle.setText(mDatas.get(position).content);
}
int nextPosition = position + 1;
if (nextPosition < totalSize) {
//獲取下個章節(jié)標題的位置, 如果小于0說明后面沒有章節(jié)標題。 如果下個章節(jié)標題位置還未顯示出來,也不用做改變。
int sectionPosition = findNextSection(nextPosition, totalSize);
if (sectionPosition < 0 || sectionPosition > (position + mRecyclerView.getChildCount() - 1)) {
refreshTopTitle();
return;
}
//獲取下一個章節(jié)標題的top, 如果top 大于 展示label的高度, 無須做改動。
int nextTopMargin = mLayoutManager.findViewByPosition(sectionPosition).getTop();
if (nextTopMargin < mMaxHeight) {
mTopTitleLayoutParams.topMargin = -(mMaxHeight - nextTopMargin);
mTopTitle.setLayoutParams(mTopTitleLayoutParams);
//如果當前第一個顯示的不是章節(jié)標題, 需要顯示上一個章節(jié)標題
if (mAdapter.getItemViewType(position) != TITLE_TYPE) {
mTopTitle.setText(findPreSectionText(position));
}
} else {
refreshTopTitle();
}
}
}
});
}
private void refreshTopTitle() {
if (mTopTitleLayoutParams.topMargin == 0) return;
mTopTitleLayoutParams.topMargin = 0;
mTopTitle.setLayoutParams(mTopTitleLayoutParams);
}
private int findNextSection(int position, int size) {
for (; position < size; position++) {
if (mAdapter.getItemViewType(position) == TITLE_TYPE) return position;
}
return -1;
}
private String findPreSectionText(int position) {
for (; position > -1; position--) {
if (mAdapter.getItemViewType(position) == TITLE_TYPE) return mDatas.get(position).content;
}
return "";
}
private boolean isInit = false;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
//當activity可以獲取焦點的時候,獲取固定標題欄的高度
if (hasFocus && !isInit) {
isInit = true;
mMaxHeight = mTopTitle.getHeight();
}
}
..........
}
這里是主要實現(xiàn)邏輯的代碼,主要是監(jiān)聽recyclerView的滾動事件對固定標題欄做相應(yīng)的操作。
這里暫且只支持recylerView的垂直的線性布局。像瀑布和網(wǎng)格布局現(xiàn)在還沒有支持。
完整的代碼:https://github.com/hu5080126/SimpleExample/tree/master/sectionRecyclerView/src
各位同學如果還有什么更好的實現(xiàn)方式,歡迎留言!