怎麼讓android系統中隱藏的menu按鈕顯示出來
阿新 • • 發佈:2019-02-14
問題?
在將專案工程最小sdk版本和target版本提高的14之後,也就是最低支援4.0之後,menu按鍵在系統上顯示不出來了,對於某些資深android玩家來說這點是比較坑爹的。
那麼下面就是解決問題的過程了。
如需轉載 註明轉自http://blog.csdn.net/luoxiaozhuo/article/details/50592567
查詢phonewindow的原始碼可以看到這樣一段程式碼
明顯看出來,是需要滿足某些條件這個menu按鈕才會顯示出來的。比如targetsdk等,當然也可以通過反射直接呼叫這個顯示menu按鍵的方法來實現這個功能。這個也是網上一大堆資料告訴我們的解決辦法。
當然,這個解決了一大部分4.0之後的問題,但是我手機升級到 了5.1.1之後,這個方法失效了。安卓就是個坑。。。。。try { getWindow().addFlags(WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null)); }catch (NoSuchFieldException e) { // Ignore since this field won't exist in most versions of Android }catch (IllegalAccessException e) { Log.w("lxz", "Could not access FLAG_NEEDS_MENU_KEY in addLegacyOverflowButton()", e); }
然後這個時候又想到去閱讀原始碼,只能每個版本的原始碼去對比,看這個之間具體發生了什麼變化。
發現從5.1.0版本之後。這塊的原始碼變成了這樣
看這個對比一下,我了個去,谷歌這麼幹是有道理的。本來一個方法能幹到的事情,不需要兩個方法,只需要一個方法不同的兩個引數就ok,也是谷歌在規範程式碼吧~
但是苦了我們這些碼農。。。。
然後後面其實就簡單了,只需要仿照那個反射來找方法來實現這個功能就ok了。
Method m = Window.class.getDeclaredMethod("setNeedsMenuKey", int.class); m.setAccessible(true); m.invoke(getWindow(), new Object[]{WindowManager.LayoutParams.class.getField( "NEEDS_MENU_SET_TRUE").getInt(null)});
注意一點這裡需要呼叫的反射是
getDeclaredMethod();// 而不是 <span style="font-family: Arial, Helvetica, sans-serif;">getMethod();</span>
getMethod();
Returns a <code>Method</code> object which represents the public method with the specified name and parameter types. <code>(Class[]) null</code> is equivalent to the empty array. This method first searches the class C represented by this <code>Class</code>, then the superclasses of C and finally the interfaces implemented by C and finally the superclasses of C for a method with matching name.
<pre code_snippet_id="1566952" snippet_file_name="blog_20160127_2_9556582" name="code" class="java">getDeclaredMethod()
Returns a <code>Method</code> object which represents the method matching the specified name and parameter types that is declared by the class represented by this <code>Class</code>.
當然完整程式碼可能就需要加上一個版本判斷來做不同的處理了。
通過這個Build.VERSION.SDK_INT來判斷是否滿足條件,去反射不同的方法來實現。
Build.VERSION.SDK_INT 21 android 5.0.1
Build.VERSION.SDK_INT 22 android 5.1.1
這覺B是坑爹。。。。
我只能再通過下載下來的原始碼再跟進去查一次了
發現這個是從sdk 22開始才有的特性
故此具體程式碼就變成了
if (Build.VERSION.SDK_INT < 22) {
getWindow().addFlags(
WindowManager.LayoutParams.class.getField(
"FLAG_NEEDS_MENU_KEY").getInt(null));
} else {
Method m = Window.class.getDeclaredMethod("setNeedsMenuKey",
int.class);
m.setAccessible(true);
m.invoke(getWindow(),
new Object[] { WindowManager.LayoutParams.class
.getField("NEEDS_MENU_SET_TRUE").getInt(null) });
}
具體的try catch 直接用ide處理下就ok了。