android 软键盘显示和隐藏造成页面跳闪问题的解决方案
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
一、分析問(wèn)題
1.為什么會(huì)閃?
首先圖像切換主要用的無(wú)非就是ViewA.setVisibility(GONE) 和?ViewB.setVisbility(VISIBLE),如果不涉及到軟鍵盤,正常狀況下本就應(yīng)該會(huì)閃,也就是說(shuō),只要有圖像切換,必會(huì)閃,這是正常的。
2.為什么會(huì)跳?
安卓的軟鍵盤SoftInput其實(shí)是一個(gè)dalog,它的彈出和縮回這兩個(gè)動(dòng)畫是有持續(xù)時(shí)間的。當(dāng)你切換界面的指令與顯隱鍵盤的指令操作過(guò)于接近時(shí)(也就是調(diào)了切換界面的方法后緊接著調(diào)了隱藏鍵盤的方法),會(huì)導(dǎo)致鍵盤還沒(méi)完成顯隱的操作時(shí),切換頁(yè)面的操作缺已經(jīng)執(zhí)行完了。所以不管你先切換頁(yè)面還是先顯隱鍵盤,切換頁(yè)面的操作總是要比顯隱鍵盤先完成!
那么就造成了鍵盤還沒(méi)縮回,但頁(yè)面上會(huì)突然亂入一個(gè)View(View:你想切換到的頁(yè)面,或者你setVisibity(VISIBLE)的那個(gè)view),然后鍵盤才慢慢縮回,這樣從視覺(jué)效果上,就會(huì)錯(cuò)覺(jué)View向上方閃一下,然后才出現(xiàn)在它該出現(xiàn)的位置。
二、解決方案:
1.非主流但很有意義的方案:
一開(kāi)始我也在想,為啥手Q、微信、釘訂這些玩意的聊天切面就沒(méi)這個(gè)問(wèn)題?在網(wǎng)上找方案,都是抄襲和轉(zhuǎn)載,還有很多所謂“高仿微信聊天鍵盤”等等的東西,都圍繞著ViewTreeObserver和GlobalLayoutListener,然后通過(guò)頁(yè)面板塊高度的減差計(jì)算得出鍵盤的高度,最后動(dòng)態(tài)地設(shè)置顯示的頁(yè)面高度等于鍵盤高度,還要定死輸入框的高度。這種方案一看就是大牛寫出來(lái),然后被各種轉(zhuǎn)載和抄襲的。此方案的好處很多,可以讓像我這樣的菜鳥(niǎo)深入到安卓底層,學(xué)到很多東西,而且符合觀察者模式。但是缺點(diǎn)也很明顯,就是邏輯復(fù)雜,代碼量大,效率低。
該方案教程:
https://my.oschina.net/JiangTun/blog/916027
2.微信、手Q這些玩意的主流解決方案:
有沒(méi)有更簡(jiǎn)潔的方法呢?想到這,學(xué)院派應(yīng)該會(huì)去找第三方包了吧。。但是作為一個(gè)野路子(苦逼完全自學(xué)派),為了理解里面的邏輯,為了減少包體積,為了提高效率增強(qiáng)動(dòng)效,想到了去看環(huán)信的EaseUI源碼?
先看代碼,發(fā)現(xiàn)代碼寫的很有美感,很整齊清晰,邏輯也非常的清晰,這里給環(huán)信贊一個(gè),但為啥文檔寫的那么屎?@環(huán)信?
對(duì)于鍵盤的處理,環(huán)信并沒(méi)有用ViewTreeObserver!
再看布局:
?
同樣只是用了android:layout_alignParentBottom="true"這個(gè)屬性而已,跟我沒(méi)有一點(diǎn)不同。
最后,順著event去找,終于發(fā)現(xiàn)了小秘密:
/*** show or hide emojicon*/ protected void toggleEmojicon() {if (chatExtendMenuContainer.getVisibility() == View.GONE) {hideKeyboard();handler.postDelayed(new Runnable() {public void run() {chatExtendMenuContainer.setVisibility(View.VISIBLE);chatExtendMenu.setVisibility(View.GONE);emojiconMenu.setVisibility(View.VISIBLE);}}, 50);} else {if (emojiconMenu.getVisibility() == View.VISIBLE) {chatExtendMenuContainer.setVisibility(View.GONE);emojiconMenu.setVisibility(View.GONE);} else {chatExtendMenu.setVisibility(View.GONE);emojiconMenu.setVisibility(View.VISIBLE);}} }可以看到,環(huán)信只是簡(jiǎn)單的先隱藏了鍵盤,然后在50毫秒后才執(zhí)行了切換頁(yè)面的操作,就是如此簡(jiǎn)單!此時(shí)你再去看看我們前面分析的問(wèn)題,會(huì)驚訝的發(fā)現(xiàn)這延后的50毫秒完美的解決了問(wèn)題2!
拿起手機(jī),觀察環(huán)信、微信、手Q,你還會(huì)發(fā)現(xiàn)另外一個(gè)共同的現(xiàn)象,就是它們的emoj區(qū)域和獲取媒體區(qū)域的高度都比系統(tǒng)軟鍵盤的高度要低!
那么最后總結(jié)一下就是:1.先隱藏軟鍵盤;2.隔上個(gè)幾十毫秒再切換頁(yè)面;3.頁(yè)面不要高于軟件盤的高度(一般在600以下)完活!
野路子精神萬(wàn)歲!
3.最理想化的解決方案(未嘗試):
此方案應(yīng)該是效率最高,頁(yè)面效果最為順滑的。不過(guò)我雖然想通了,但是最近項(xiàng)目時(shí)限緊,沒(méi)有時(shí)間去實(shí)現(xiàn)了,備注一下,以后試試!
經(jīng)過(guò)觀察和調(diào)適,我發(fā)現(xiàn),顯隱軟鍵盤會(huì)造成整個(gè)頁(yè)面重繪,并且切換布局會(huì)造成頁(yè)面重繪兩次(隱藏ViewA重繪一次,顯示ViewB再重繪一次),那么跳閃就可以理解為:在Activity前兩次重繪時(shí),只是完成了view的切換,而第三次重繪才是改變鍵盤(第三次重繪時(shí),給鍵盤施加了動(dòng)畫)。
那么我們很容易就可以想到,如果把切換頁(yè)面和隱藏鍵盤放在同一個(gè)Acitity重繪中,不就看不到閃爍了嘛!!
順著這個(gè)思路想,我先想到了Activity,但是明顯dalog應(yīng)該與activity同級(jí),而鍵盤就是個(gè)dalog,那么目標(biāo)就應(yīng)該是activity的父級(jí)window對(duì)象了!
如果能找到鍵盤縮回的動(dòng)畫,是不是就可以借用給界面?是不是就能時(shí)時(shí)監(jiān)聽(tīng)鍵盤高度變化?最后讓輸入框做個(gè)跟隨就行了!
想法很好,可惜沒(méi)空實(shí)現(xiàn),先mark一下吧。
轉(zhuǎn)載于:https://my.oschina.net/JiangTun/blog/916955
總結(jié)
以上是生活随笔為你收集整理的android 软键盘显示和隐藏造成页面跳闪问题的解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [LeetCode]Count of R
- 下一篇: 移动html特殊链接【打电话_发短信_发