Android tabLayout+recyclerView實(shí)現(xiàn)錨點(diǎn)定位的示例
在上一篇文章Android 實(shí)現(xiàn)錨點(diǎn)定位中,我們介紹了tablayout+scrollView實(shí)現(xiàn)的錨點(diǎn)定位,今天我們使用tablayout+recyclerView 來(lái)實(shí)現(xiàn)同樣的效果。
效果圖:
實(shí)現(xiàn)思路
實(shí)現(xiàn)的思路與上一篇文章是一致的:
1、監(jiān)聽(tīng)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)行修改,讓其充滿(mǎn)屏幕。
private LinearLayoutManager manager; private String[] tabTxt = {"客廳", "臥室", "餐廳", "書(shū)房", "陽(yáng)臺(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)聽(tīng)第一個(gè)可見(jiàn)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è)可見(jiàn)的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è)可見(jiàn)的view的位置 int firstItem = manager.findFirstVisibleItemPosition(); // 最后一個(gè)可見(jiàn)的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來(lái)滑動(dòng)到指定位置 int top = mRecyclerView.getChildAt(position - firstItem).getTop(); mRecyclerView.smoothScrollBy(0, top); } else { // 如果要跳轉(zhuǎn)的位置在lastItem 之后,則先調(diào)用smoothScrollToPosition將要跳轉(zhuǎn)的位置滾動(dòng)到可見(jiàn)位置 // 再通過(guò)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ì)代碼見(jiàn)
github地址:https://github.com/taixiang/tabScroll
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Binder入門(mén)學(xué)習(xí)筆記
這篇文章主要給大家介紹了關(guān)于Android Binder入門(mén)學(xué)習(xí)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02Android EditText被軟鍵盤(pán)遮蓋的處理方法
android app新增了透明欄效果,結(jié)果發(fā)現(xiàn)鍵盤(pán)彈起后會(huì)遮蓋屏幕底部的EditText,沒(méi)有像想象中的調(diào)整窗口大小,并滾動(dòng)ScrollView,將EditText顯示在鍵盤(pán)上方。下面小編把解決方法記錄一下,特此分享到腳本之家平臺(tái),感興趣的朋友一起看看吧2016-10-10Android UI 實(shí)現(xiàn)老虎機(jī)詳解及實(shí)例代碼
這篇文章主要介紹了Android UI 實(shí)現(xiàn)老虎機(jī)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03Android自定義view實(shí)現(xiàn)輸入框效果
這篇文章主要為大家詳細(xì)介紹了Android自定義view實(shí)現(xiàn)輸入框效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03android 完全退出應(yīng)用程序?qū)崿F(xiàn)代碼
這篇文章主要介紹了在android中完全退出應(yīng)用的實(shí)現(xiàn)代碼,多種實(shí)現(xiàn)方法,大家可以根據(jù)需求選擇2013-06-06Notification與NotificationManager詳細(xì)介紹
在Android系統(tǒng)中,發(fā)一個(gè)狀態(tài)欄通知還是很方便的。下面我們就來(lái)看一下,怎么發(fā)送狀態(tài)欄通知,狀態(tài)欄通知又有哪些參數(shù)可以設(shè)置2012-11-11