原文連接:mp.weixin.qq.com/s/L3o2i3WTm…git
在上一篇文章 Android 實現錨點定位 中,咱們介紹了tablayout
+scrollView
實現的錨點定位,今天咱們使用tablayout
+recyclerView
來實現一樣的效果。
效果圖:github
實現的思路與上一篇文章是一致的:
一、監聽recyclerView
滑動到的位置,tablayout
切換到對應標籤
二、tablayout
各標籤點擊,recyclerView
可滑動到對應區域bash
數據模擬,使用上一文章的AnchorView
做爲recyclerView
的每一個字view,同時這裏對recyclerView
的最後一個子view的高度進行修改,讓其充滿屏幕。微信
private LinearLayoutManager manager;
private String[] tabTxt = {"客廳", "臥室", "餐廳", "書房", "陽臺", "兒童房"};
//判讀是不是recyclerView主動引發的滑動,true- 是,false- 否,由tablayout引發的
private boolean isRecyclerScroll;
//記錄上一次位置,防止在同一內容塊裏滑動 重複定位到tablayout
private int lastPos;
//用於recyclerView滑動到指定的位置
private boolean canScroll;
private int scrollToPosition;
//tablayout設置標籤
for (int i = 0; i < tabTxt.length; i++) {
tabLayout.addTab(tabLayout.newTab().setText(tabTxt[i]));
}
//計算內容塊所在的高度,全屏高度-狀態欄高度-tablayout的高度(這裏固定高度50dp),用於recyclerView的最後一個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]);
//判斷最後一個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
滑動引發的,addOnScrollListener
的onScrolled
的監聽第一個可見view的位置,直接將tablayout
定位到相應的位置。ide
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//當滑動由recyclerView觸發時,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) {
//第一個可見的view的位置,即tablayou需定位的位置
int position = manager.findFirstVisibleItemPosition();
if (lastPos != position) {
tabLayout.setScrollPosition(position, 0, true);
}
lastPos = position;
}
}
});
複製代碼
點擊tablayout
進行切換,recyclerView
須要滑動到相應的位置,注意這裏須要根據跳轉位置不一樣,進行相應的滑動。ui
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
//點擊標籤,使recyclerView滑動,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) {
// 第一個可見的view的位置
int firstItem = manager.findFirstVisibleItemPosition();
// 最後一個可見的view的位置
int lastItem = manager.findLastVisibleItemPosition();
if (position <= firstItem) {
// 若是跳轉位置firstItem 以前(滑出屏幕的狀況),就smoothScrollToPosition能夠直接跳轉,
mRecyclerView.smoothScrollToPosition(position);
} else if (position <= lastItem) {
// 跳轉位置在firstItem 以後,lastItem 之間(顯示在當前屏幕),smoothScrollBy來滑動到指定位置
int top = mRecyclerView.getChildAt(position - firstItem).getTop();
mRecyclerView.smoothScrollBy(0, top);
} else {
// 若是要跳轉的位置在lastItem 以後,則先調用smoothScrollToPosition將要跳轉的位置滾動到可見位置
// 再經過onScrollStateChanged控制再次調用當前moveToPosition方法,執行上一個判斷中的方法
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);
}
}
});
複製代碼
至此,兩種實現錨點定位的方法就介紹到這裏,但願能幫助到讀者在實際項目中的使用。
代碼與上一篇文章的在同一個git地址裏。this
詳細代碼見
github地址:github.com/taixiang/ta…spa
歡迎關注個人博客:blog.manjiexiang.cn/
更多精彩歡迎關注微信號:春風十里不如認識你
code
有個「佛系碼農圈」,歡迎你們加入暢聊,開心就好!
cdn