Android tabLayout+recyclerView實(shí)現(xiàn)錨點(diǎn)定位的示例
在上一篇文章Android 實(shí)現(xiàn)錨點(diǎn)定位中,我們介紹了tablayout+scrollView實(shí)現(xiàn)的錨點(diǎn)定位,今天我們使用tablayout+recyclerView 來實(shí)現(xiàn)同樣的效果。
效果圖:

實(shí)現(xiàn)思路
實(shí)現(xiàn)的思路與上一篇文章是一致的:
1、監(jiān)聽recyclerView滑動(dòng)到的位置,tablayout切換到對(duì)應(yīng)標(biāo)簽
2、tablayout各標(biāo)簽點(diǎn)擊,recyclerView可滑動(dòng)到對(duì)應(yīng)區(qū)域
數(shù)據(jù)模擬
數(shù)據(jù)模擬,使用上一文章的AnchorView作為recyclerView的每個(gè)字view,同時(shí)這里對(duì)recyclerView的最后一個(gè)子view的高度進(jìn)行修改,讓其充滿屏幕。
private LinearLayoutManager manager;
private String[] tabTxt = {"客廳", "臥室", "餐廳", "書房", "陽臺(tái)", "兒童房"};
//判讀是否是recyclerView主動(dòng)引起的滑動(dòng),true- 是,false- 否,由tablayout引起的
private boolean isRecyclerScroll;
//記錄上一次位置,防止在同一內(nèi)容塊里滑動(dòng) 重復(fù)定位到tablayout
private int lastPos;
//用于recyclerView滑動(dòng)到指定的位置
private boolean canScroll;
private int scrollToPosition;
//tablayout設(shè)置標(biāo)簽
for (int i = 0; i < tabTxt.length; i++) {
tabLayout.addTab(tabLayout.newTab().setText(tabTxt[i]));
}
//計(jì)算內(nèi)容塊所在的高度,全屏高度-狀態(tài)欄高度-tablayout的高度(這里固定高度50dp),用于recyclerView的最后一個(gè)item view填充高度
int screenH = getScreenHeight();
int statusBarH = getStatusBarHeight(this);
int tabH = 50 * 3;
int lastH = screenH - statusBarH - tabH;
manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(new MyAdapter(this, tabTxt, lastH));
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.anchorView.setContentTxt(tabTxt[position]);
holder.anchorView.setAnchorTxt(tabTxt[position]);
//判斷最后一個(gè)view
if (position == tabTxt.length - 1) {
if (holder.anchorView.getHeight() < lastH) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.height = lastH;
holder.anchorView.setLayoutParams(params);
}
}
}
recyclerView滑動(dòng)定位
當(dāng)recyclerView滑動(dòng)引起的,addOnScrollListener的onScrolled的監(jiān)聽第一個(gè)可見view的位置,直接將tablayout定位到相應(yīng)的位置。
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//當(dāng)滑動(dòng)由recyclerView觸發(fā)時(shí),isRecyclerScroll 置true
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isRecyclerScroll = true;
}
return false;
}
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (isRecyclerScroll) {
//第一個(gè)可見的view的位置,即tablayou需定位的位置
int position = manager.findFirstVisibleItemPosition();
if (lastPos != position) {
tabLayout.setScrollPosition(position, 0, true);
}
lastPos = position;
}
}
});
tablayout切換定位
點(diǎn)擊tablayout進(jìn)行切換,recyclerView需要滑動(dòng)到相應(yīng)的位置,注意這里需要根據(jù)跳轉(zhuǎn)位置不同,進(jìn)行相應(yīng)的滑動(dòng)。
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//點(diǎn)擊標(biāo)簽,使recyclerView滑動(dòng),isRecyclerScroll置false
int pos = tab.getPosition();
isRecyclerScroll = false;
moveToPosition(manager, recyclerView, pos);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
public void moveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int position) {
// 第一個(gè)可見的view的位置
int firstItem = manager.findFirstVisibleItemPosition();
// 最后一個(gè)可見的view的位置
int lastItem = manager.findLastVisibleItemPosition();
if (position <= firstItem) {
// 如果跳轉(zhuǎn)位置firstItem 之前(滑出屏幕的情況),就smoothScrollToPosition可以直接跳轉(zhuǎn),
mRecyclerView.smoothScrollToPosition(position);
} else if (position <= lastItem) {
// 跳轉(zhuǎn)位置在firstItem 之后,lastItem 之間(顯示在當(dāng)前屏幕),smoothScrollBy來滑動(dòng)到指定位置
int top = mRecyclerView.getChildAt(position - firstItem).getTop();
mRecyclerView.smoothScrollBy(0, top);
} else {
// 如果要跳轉(zhuǎn)的位置在lastItem 之后,則先調(diào)用smoothScrollToPosition將要跳轉(zhuǎn)的位置滾動(dòng)到可見位置
// 再通過onScrollStateChanged控制再次調(diào)用當(dāng)前moveToPosition方法,執(zhí)行上一個(gè)判斷中的方法
mRecyclerView.smoothScrollToPosition(position);
scrollToPosition = position;
canScroll = true;
}
}
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (canScroll) {
canScroll = false;
moveToPosition(manager, recyclerView, scrollToPosition);
}
}
});
至此,兩種實(shí)現(xiàn)錨點(diǎn)定位的方法就介紹到這里,希望能幫助到讀者在實(shí)際項(xiàng)目中的使用。
代碼與上一篇文章的在同一個(gè)git地址里。
詳細(xì)代碼見
github地址:https://github.com/taixiang/tabScroll
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android WebView自定義長(zhǎng)按選擇實(shí)現(xiàn)收藏/分享選中文本功能
這篇文章主要介紹了Android WebView自定義長(zhǎng)按選擇實(shí)現(xiàn)收藏/分享選中文本功能,需要的朋友可以參考下2017-06-06
Android中解決WebView上下滑動(dòng)監(jiān)聽問題
本篇文章主要介紹了Android中解決WebView滑動(dòng)監(jiān)聽問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04
Android 狀態(tài)欄虛擬導(dǎo)航鍵透明效果的實(shí)現(xiàn)方法
這篇文章主要介紹了Android 狀態(tài)欄虛擬導(dǎo)航鍵透明效果的實(shí)現(xiàn)方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03
android開機(jī)自啟動(dòng)原理與實(shí)現(xiàn)案例(附源碼)
完成一下步驟后,啟動(dòng)一次程序,完成注冊(cè)。等下次手機(jī)開機(jī)時(shí),該軟件即會(huì)自動(dòng)啟動(dòng),具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06
Kotlin構(gòu)造函數(shù)與成員變量和init代碼塊執(zhí)行順序詳細(xì)講解
這篇文章主要介紹了Kotlin構(gòu)造函數(shù)與成員變量和init代碼塊執(zhí)行順序,kotlin里面的構(gòu)造函數(shù)分為主構(gòu)造函數(shù)和次構(gòu)造函數(shù)。主構(gòu)造函數(shù)只能有一個(gè),次構(gòu)造函數(shù)個(gè)數(shù)不限制,可以有一個(gè)或者多個(gè)2022-11-11
Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用詳解
這篇文章主要給大家介紹了關(guān)于Android開發(fā)中l(wèi)ibs和jinLibs文件夾的作用的相關(guān)資料,文中通過圖文及示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-09-09
一文詳解Android IntentService的開發(fā)技巧
Android應(yīng)用開發(fā)中,執(zhí)行后臺(tái)任務(wù)是常見需求之一,其中,IntentService是一種強(qiáng)大的工具,可以輕松管理異步任務(wù),而無需擔(dān)心線程管理和生命周期問題,本文將深入探討 IntentService 的各個(gè)方面,需要的朋友可以參考下2023-11-11
Android編程設(shè)計(jì)模式之單例模式實(shí)例詳解
這篇文章主要介紹了Android編程設(shè)計(jì)模式之單例模式,結(jié)合實(shí)例形式詳細(xì)分析了Android開發(fā)設(shè)計(jì)模式中單例模式的概念、功能、實(shí)現(xiàn)、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-12-12

