標籤:move top bar smooth bin ges status scroll 可見
原文連結:https://mp.weixin.qq.com/s/L3o2i3WTmg1ScXEYDS8YCg
在上一篇文章 Android 實現錨點定位中,我們介紹了tablayout
+scrollView
實現的錨點定位,今天我們使用tablayout
+recyclerView
來實現同樣的效果。
:
實現思路
實現的思路與上一篇文章是一致的:
1、監聽recyclerView
滑動到的位置,tablayout
切換到對應標籤
2、tablayout
各標籤點擊,recyclerView
可滑動到對應地區
資料類比
資料類比,使用上一文章的AnchorView
作為recyclerView
的每個字view,同時這裡對recyclerView
的最後一個子view的高度進行修改,讓其充滿螢幕。
private LinearLayoutManager manager;private String[] tabTxt = {"客廳", "臥室", "餐廳", "書房", "陽台", "兒童房"};//判讀是否是recyclerView主動引起的滑動,true- 是,false- 否,由tablayout引起的private boolean isRecyclerScroll;//記錄上一次位置,防止在同一內容塊裡滑動 重複定位到tablayoutprivate 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));@Overridepublic 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滑動定位
當recyclerView
滑動引起的,addOnScrollListener
的onScrolled
的監聽第一個可見view的位置,直接將tablayout
定位到相應的位置。
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切換定位
點擊tablayout
進行切換,recyclerView
需要滑動到相應的位置,注意這裡需要根據跳轉位置不同,進行相應的滑動。
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地址裡。
詳細代碼見
github地址:https://github.com/taixiang/tabScroll
歡迎關注我的部落格:https://blog.manjiexiang.cn/
更多精彩歡迎關注號:春風十裡不如認識你
有個「佛系碼農圈」,歡迎大家加入暢聊,開心就好!
到期了,可加我 tx467220125 拉你入群。
Android tabLayout+recyclerView實現錨點定位