前言
在開(kāi)發(fā)中我們經(jīng)常會(huì)用到 NestedScrollView 和 RecycleView斋日,一般情況下這兩種布局是不需要進(jìn)行嵌套的,很多情況下 RecycleView 就可以自行解決墓陈,但是畢竟是一般情況恶守,因此超出一般情況外的,我們可能就需要進(jìn)行嵌套了贡必,雖然 Google 大大也不鼓勵(lì)我們這樣使用兔港。
這樣使用可能會(huì)帶來(lái)一些問(wèn)題,一如當(dāng)年的 ScrollView 和 ListView 的矛盾一樣仔拟。這里就出現(xiàn)的一些情況進(jìn)行總結(jié)和解決衫樊。
開(kāi)發(fā)中碰到的類(lèi)似的問(wèn)題,都會(huì)放在這里利花,持續(xù)更新中……
出現(xiàn)的問(wèn)題
問(wèn)題一:
NestedScrollView 和 RecycleView 嵌套時(shí)出現(xiàn)滑動(dòng)卡頓的情況
解決方法:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setSmoothScrollbarEnabled(true);
linearLayoutManager.setAutoMeasureEnabled(true);
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setLayoutManager(linearLayoutManager);
這個(gè)是 LinearLayoutManager 實(shí)現(xiàn) GridView 的效果橡伞,是一樣的設(shè)置盒揉,只是換成了 GridLayoutManager 即可。
其中 recyclerView.setNestedScrollingEnabled(false); 設(shè)置可以在 xml 文件中間進(jìn)行設(shè)置:android:nestedScrollingEnabled="false"
同樣我使用這種方法兑徘,一般可以解決滑動(dòng)沖突的問(wèn)題刚盈,也有一些網(wǎng)上重寫(xiě) LinearLayoutManager 的方式,根據(jù)需要進(jìn)行選擇吧挂脑,如果以上方法無(wú)法滿足藕漱,則可以選擇重寫(xiě)的方式,這個(gè)網(wǎng)上的資料很多崭闲,這里就不再重復(fù)肋联。
問(wèn)題二:
在 NestedScrollView 嵌套 RecycleView 時(shí),可能會(huì)出現(xiàn)首次進(jìn)入頁(yè)面刁俭,頁(yè)面的位置不在最頂部的問(wèn)題橄仍。有可能是停在了 RecycleView 的部位。
解決方法:
在 NestedScrollView 唯一子布局中加入
android:descendantFocusability=“blocksDescendants”
android:descendantFocusability 有三個(gè)屬性
beforeDescendants:優(yōu)先于子控件獲取焦點(diǎn)
afterDescendants:當(dāng)子控件不需要焦點(diǎn)時(shí)牍戚,獲取焦點(diǎn)
blocksDescendants:覆蓋所有子控件獲取焦點(diǎn)
問(wèn)題三:
在使用 NestedScrollView 作為父布局的時(shí)候侮繁,子布局的嵌套問(wèn)題
解決方法:
使用 NestedScrollView 和 ScrollView 是一樣的,其子布局是唯一的如孝,不然在運(yùn)行時(shí)會(huì)報(bào)錯(cuò)宪哩。因此在使用的時(shí)候要設(shè)置唯一的子布局進(jìn)行展示。
問(wèn)題四:
NestedScrollView 嵌套 ViewPager 導(dǎo)致 ViewPager 顯示不出來(lái)的問(wèn)題
解決方法:
在 NestedScrollView 的布局中加入下面代碼
android:fillViewport="true"
問(wèn)題五:
使用 ViewPager 嵌套 Fragment 時(shí)默認(rèn)的我們使用 PagerAdapter/FragmentPagerAdapter/FragmentStatePagerAdapter 來(lái)管理 Fragment第晰,這時(shí)會(huì)默認(rèn)加載的 Fragment 的個(gè)數(shù)時(shí)系統(tǒng)默認(rèn)的 DEFAULT_OFFSCREEN_PAGES = 1锁孟,即顯示一個(gè),預(yù)加載一個(gè)茁瘦,如果我們想控制加載的 Fragment 的個(gè)數(shù)需要如何處理品抽?
解決方法:
可以通過(guò)設(shè)置 ViewPager 來(lái)進(jìn)行管理
mViewPager.setOffscreenPageLimit(num);
設(shè)置這個(gè)屬性后,系統(tǒng)會(huì)加載相應(yīng)的 Fragment 的個(gè)數(shù)甜熔,但是運(yùn)行時(shí)會(huì) Crash 掉桑包,提示的下面的錯(cuò)誤:
java.lang.IllegalStateException: FragmentManager is already executing transactions
解決方法:
mViewPager = new MyViewPager(getFragmentManager());
將 getFragmentManager() 替換為 getChildFragmentManager();
FragmentManager is already executing transactions.
問(wèn)題六:
場(chǎng)景:當(dāng) ViewPager1 嵌套 Fragment0、Fragment0纺非、Fragment1、Fragment0赘方,在其中的 Fragment1 中又有一個(gè) ViewPager2烧颖,在 ViewPager2 中嵌套 Fragment2,這時(shí)當(dāng)我們滑倒 Fragment1 的時(shí)候窄陡,由于是第一次滑動(dòng)到這個(gè)位置炕淮,F(xiàn)ragment2 正常顯示,但是當(dāng)我們滑動(dòng)到其他位置跳夭,再返回到 Fragment1 時(shí)涂圆,就會(huì)出現(xiàn) Fragment1 顯示空白的問(wèn)題们镜,日志顯示,正常加載润歉。
解決方法:
1模狭、跟產(chǎn)品提出將第二層的 Fragment 提到與第一層同級(jí)上去(如果產(chǎn)品同意的話)。
2踩衩、按照下面設(shè)置:
mViewPager = new MyViewPager(getFragmentManager());
將 getFragmentManager() 替換為 getChildFragmentManager();
問(wèn)題七:
getFragmentManager()嚼鹉、getChildFragmentManager()、getSupportFragmentManager() 的區(qū)別:
解決方法:
getSupportFragmentManager(): 主要用于支持 3.0以下 android 系統(tǒng)
API 版本驱富,3.0以上系統(tǒng)可以直接調(diào)用 getFragmentManager() 锚赤,因?yàn)?br>
fragment是3.0以后才出現(xiàn)的組件,為了這之前的系統(tǒng)版本也能使用
fragment,借助V4包里面的 getSupportFragmentManager() 方法來(lái)間接獲取 FragmentManager() 對(duì)象褐鸥,3.0版本之后线脚,有了 Fragment 的 api,就可以直接使用 getFragmentManager() 這個(gè)方法來(lái)獲取對(duì)象叫榕。
getFragmentManager(): 所得到的是所在 fragment 的父容器的管理器
getChildFragmentManager(): 所得到的是在 fragment 里面子容器的管理器
因此當(dāng)我們使用 Fragment 嵌套 Fragment 時(shí)浑侥,應(yīng)該使用 getChildFragmentManager()
可能會(huì)出現(xiàn)的類(lèi)似的問(wèn)題又:
1、Fragment低頻率點(diǎn)擊切換不會(huì)發(fā)生問(wèn)題翠霍,過(guò)快點(diǎn)擊馬上崩潰
2锭吨、錯(cuò)誤:Java.lang.IllegalArgumentException:No view found for id for fragment
3、調(diào)用fragment的replace方法不走onDestroy()寒匙、onDestroyView()方法零如,無(wú)法銷(xiāo)毀fragment
4、在fragment中寫(xiě)倒計(jì)時(shí)锄弱,每次切換后倒計(jì)時(shí)越來(lái)越快的問(wèn)題
問(wèn)題八:
當(dāng)點(diǎn)擊上層布局結(jié)果下面的布局同時(shí)響應(yīng)點(diǎn)擊事件
解決方法:
在上層根布局中添加下面代碼:
android:clickable="true"
這樣可以使上層布局?jǐn)r截點(diǎn)擊事件考蕾,不會(huì)讓下面的布局獲取到。
問(wèn)題九:
鍵盤(pán)問(wèn)題
解決方法:
關(guān)于軟鍵盤(pán)彈出的各個(gè)屬性簡(jiǎn)介:
在manifest文件中可以設(shè)置Activity的android:windowSoftInputMode屬性会宪,這個(gè)屬性值常見(jiàn)的設(shè)置如下:
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
那么這里值的含義列表如下:
【A】stateUnspecified:軟鍵盤(pán)的狀態(tài)并沒(méi)有指定肖卧,系統(tǒng)將選擇一個(gè)合適的狀態(tài)或依賴于主題的設(shè)置
【B】stateUnchanged:當(dāng)這個(gè)activity出現(xiàn)時(shí),軟鍵盤(pán)將一直保持在上一個(gè)activity里的狀態(tài)掸鹅,無(wú)論是隱藏還是顯示
【C】stateHidden:用戶選擇activity時(shí)塞帐,軟鍵盤(pán)總是被隱藏
【D】stateAlwaysHidden:當(dāng)該Activity主窗口獲取焦點(diǎn)時(shí),軟鍵盤(pán)也總是被隱藏的
【E】stateVisible:軟鍵盤(pán)通常是可見(jiàn)的
【F】stateAlwaysVisible:用戶選擇activity時(shí)巍沙,軟鍵盤(pán)總是顯示的狀態(tài)
【G】adjustUnspecified:默認(rèn)設(shè)置葵姥,通常由系統(tǒng)自行決定是隱藏還是顯示
【H】adjustResize:該Activity總是調(diào)整屏幕的大小以便留出軟鍵盤(pán)的空間
【I】adjustPan:當(dāng)前窗口的內(nèi)容將自動(dòng)移動(dòng)以便當(dāng)前焦點(diǎn)從不被鍵盤(pán)覆蓋和用戶能總是看到輸入內(nèi)容的部分
后記
這里只是記錄了幾種自己開(kāi)發(fā)中碰到的問(wèn)題,會(huì)持續(xù)更新這篇帖子句携,如果有人遇到過(guò)其他問(wèn)題榔幸,歡迎提問(wèn)。