基于界面適配華為手機的虛擬按鍵的解決方法
一、概述
在項目中,測試發(fā)現(xiàn)在一些華為手機的屏幕適配上出現(xiàn)了問題,主要是因為華為Mate等一些系列的手機有一個虛擬按鍵的設(shè)計。當(dāng)這些虛擬按鍵由用戶手勢滑出,或默認顯示的話,就會遮擋我們本身的應(yīng)用布局。比如歡迎界面過后是四個Fragment,那么底部的四個tab就會被虛擬的導(dǎo)航欄遮住,非常難看。
當(dāng)然,歡迎頁的圖片適配也同樣會出現(xiàn)問題。
Google后得出第一個問題的解決方案。第二個圖片的問題則用自己摸索的方式解決,當(dāng)然也非常簡單。
二、布局由于虛擬按鍵導(dǎo)致導(dǎo)航欄頂上去的解決方法
在我們的項目中加載Fragment的MainActivity,以及其他一般的Activity繼承的BaseActivity中的onCreate方法中添加如下代碼:
if (AndroidWorkaround.checkDeviceHasNavigationBar(this)) { AndroidWorkaround.assistActivity(findViewById(android.R.id.content)); }
其中AndroidWorkaround使我們?yōu)榱私鉀Q該問題而封裝的類,也可以看作是一個特定的工具類:
/** * 解決底部屏幕按鍵適配 * Created by Mercury on 2016/10/25. */ public class AndroidWorkaround { public static void assistActivity(View content) { new AndroidWorkaround(content); } private View mChildOfContent; private int usableHeightPrevious; private ViewGroup.LayoutParams frameLayoutParams; private AndroidWorkaround(View content) { mChildOfContent = content; mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { frameLayoutParams.height = usableHeightNow; mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom); } public static boolean checkDeviceHasNavigationBar(Context context) { boolean hasNavigationBar = false; Resources rs = context.getResources(); int id = rs.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { hasNavigationBar = rs.getBoolean(id); } try { Class systemPropertiesClass = Class.forName("android.os.SystemProperties"); Method m = systemPropertiesClass.getMethod("get", String.class); String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys"); if ("1".equals(navBarOverride)) { hasNavigationBar = false; } else if ("0".equals(navBarOverride)) { hasNavigationBar = true; } } catch (Exception e) { } return hasNavigationBar; } }
重新測試,發(fā)現(xiàn)無論是否彈出虛擬按鍵,都不會再次遮擋tab按鈕。
三、原理
上面的代碼需要在setContentView后面執(zhí)行。其最初的解決方案是stackoverflow上有人為了適配軟鍵盤在全屏下的布局問題。
開始先判斷該設(shè)備上是否存在導(dǎo)航欄。為什么用findViewById(android.R.id.content)呢?因為android.R.id.content這個id代表的就是所在頁面的根布局,而并不需要特別指定一個id給該布局??梢酝ㄟ^調(diào)用系統(tǒng)API返回的結(jié)果,也可以通過判斷該手機是否為華為手機,操作系統(tǒng)屬于哪種類型來來判斷。
一旦確定該設(shè)備存在導(dǎo)航欄,將對該布局進行重新測量。首先mChildOfContent得到其視圖樹,對全局高度實現(xiàn)監(jiān)聽。
OnGlobalLayoutListener 是ViewTreeObserver的內(nèi)部類,當(dāng)一個視圖樹的布局發(fā)生改變時,可以被ViewTreeObserver監(jiān)聽到,這是一個注冊監(jiān)聽視圖樹的觀察者(observer),在視圖樹的全局事件改變時得到通知。ViewTreeObserver不能直接實例化,而是通過getViewTreeObserver()獲得。
接著得到視圖目前可用的總高度,將其賦值給mChildOfContent的布局高度。調(diào)用requestLayout,讓mChildOfContent要求自己的parent view對自己重新設(shè)置位置。
四、全屏圖片的適配
解決了布局的問題,再來看歡迎頁啟動時候全屏圖片的適配問題。發(fā)現(xiàn)該方法對于圖片不適用。如下圖,當(dāng)虛擬按鍵彈出時,圖片照樣被遮擋了底部的一小部分。
如果隱藏虛擬按鍵,圖片大小恢復(fù)正常
仔細想想,對于一個ImageView直接占據(jù)一個layout的情況,是沒有必要再去寫一些代碼進行適配的。到布局里一看,發(fā)現(xiàn)ImageView的屬性 android:scaleType=”centerCrop”
將其改為 android:scaleType=”fitXY”就可以解決了。這樣圖片可能高度會隨著虛擬鍵的彈出而壓縮,但是很好的適配了布局高度的變化而不會被遮擋。
關(guān)于scaleType的詳細介紹,留待其他文章里再探討。
以上這篇基于界面適配華為手機的虛擬按鍵的解決方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android自定義TextView仿微信朋友圈文字展開全文功能
這篇文章主要為大家詳細介紹了Android自定義TextView仿微信朋友圈文字展開全文功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06Android序列化接口Parcelable與Serializable接口對比
我們使用 Intent 傳遞數(shù)據(jù)的時候,putExtra() 所支持的數(shù)據(jù)類型事有限的,當(dāng)需要傳遞自定義對象的時候就需要序列化。Serializable更簡單但是會把整個對象進行序列化因此效率比Parcelable低一些2023-02-02Android實現(xiàn)圖片在屏幕內(nèi)縮放和移動效果
這篇文章主要為大家詳細介紹了Android控制圖片在屏幕內(nèi)縮放和移動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-02-02android開發(fā)環(huán)境遇到adt無法啟動的問題分析及解決方法
開始研究android開發(fā),搭建開發(fā)環(huán)境的時候就出了問題,真是束手無策2013-02-02Android中TextView文本高亮和點擊行為的封裝方法
這篇文章主要介紹了Android中TextView文本高亮和點擊行為的封裝方法,文中介紹的非常詳細,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03