Android获取手机底部虚拟按键高度
获取手机底部虚拟键盘的高度 魅族手机底部SmartBar高度 import android.content.Context; import android.content.res.Resources; import android.graphics.Point; import android.os.Build; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.view.ViewConfiguration; import android.view.WindowManager; import java.lang.reflect.Field; import java.lang.reflect.Method; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); Log.e(MainActivity.class.getName(), "hasNavBar1 = " + hasNavBar(MainActivity.this)); } }); Log.e(MainActivity.class.getName(),"ScreenHeight = "+getScreenHight()); Log.e(MainActivity.class.getName(),"SmartBarHeight = "+getSmartBarHeight(this)); Log.e(MainActivity.class.getName(),"hasNavBar = "+hasNavBar(this)); Log.e(MainActivity.class.getName(),"getNavigationBarHeight = "+getNavigationBarHeight(this)); } private int getScreenHight(){ // 获取屏幕高 Point point = new Point(); getWindowManager().getDefaultDisplay().getSize(point); int screenHeight = point.y + (isMeizu() ? 0 : getNavigationBarHeight(this)); return screenHeight; } /** * 获取虚拟按键栏高度 * @param context * @return */ public static int getNavigationBarHeight(Context context) { int result = 0; if (hasNavBar(context)){ Resources res = context.getResources(); int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { result = res.getDimensionPixelSize(resourceId); } } return result; } /** * 检查是否存在虚拟按键栏 * @param context * @return */ private static boolean hasNavBar(Context context) { Resources res = context.getResources(); int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android"); if (resourceId != 0) { boolean hasNav = res.getBoolean(resourceId); // check override flag String sNavBarOverride = getNavBarOverride(); if ("1".equals(sNavBarOverride)) { hasNav = false; } else if ("0".equals(sNavBarOverride)) { hasNav = true; } return hasNav; } else { // fallback return !ViewConfiguration.get(context).hasPermanentMenuKey(); } } /** * 判断虚拟按键栏是否重写 * @return */ private static String getNavBarOverride() { String sNavBarOverride = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { try { Class c = Class.forName("android.os.SystemProperties"); Method m = c.getDeclaredMethod("get", String.class); m.setAccessible(true); sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); } catch (Throwable e) { } } return sNavBarOverride; } /** * 判断是否meizu手机 * @return */ public static boolean isMeizu() { return Build.BRAND.equals("Meizu"); } /** * 获取魅族手机底部虚拟键盘高度 * @param context * @return */ public static int getSmartBarHeight(Context context) { try { Class c = Class.forName("com.android.internal.R$dimen"); Object obj = c.newInstance(); Field field = c.getField("mz_action_button_min_height"); int height = Integer.parseInt(field.get(obj).toString()); return context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return 0; } }
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import android.app.ActionBar; | |
import android.content.Context; | |
import android.content.res.Configuration; | |
import android.os.Build; | |
import android.support.v4.app.FragmentActivity; | |
import android.view.View; | |
import android.view.Window; | |
import android.view.WindowManager; | |
public class SmartBarUtils { | |
public static final int SMART_BAR_HEIGH = 96; | |
/** | |
* 调用 ActionBar.setTabsShowAtBottom(boolean) 方法。 如果 | |
* android:uiOptions=”splitActionBarWhenNarrow”,则可设置ActionBar Tabs显示在底栏。 | |
* | |
* 示例: public class MyActivity extends Activity implements | |
* ActionBar.TabListener { protected void onCreate(Bundle | |
* savedInstanceState) { super.onCreate(savedInstanceState); … | |
* | |
* final ActionBar bar = getActionBar(); | |
* bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); | |
* SmartBarUtils.setActionBarTabsShowAtBottom(bar, true); | |
* | |
* bar.addTab(bar.newTab().setText("tab1").setTabListener(this)); | |
* … } } | |
* | |
*/ | |
public static void setActionBarTabsShowAtBottom(ActionBar actionbar, | |
boolean showAtBottom) { | |
try { | |
Method method = Class.forName(“android.app.ActionBar“).getMethod( | |
“setTabsShowAtBottom“, new Class[] { boolean.class }); | |
try { | |
method.invoke(actionbar, showAtBottom); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} | |
} catch (SecurityException e) { | |
e.printStackTrace(); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* 调用 ActionBar.setActionBarViewCollapsable(boolean) 方法。 | |
* 设置ActionBar顶栏无显示内容时是否隐藏。 | |
* | |
* 示例: | |
* | |
* public class MyActivity extends Activity { | |
* | |
* protected void onCreate(Bundle savedInstanceState) { | |
* super.onCreate(savedInstanceState); … | |
* | |
* final ActionBar bar = getActionBar(); | |
* | |
* // 调用setActionBarViewCollapsable,并设置ActionBar没有显示内容,则ActionBar顶栏不显示 | |
* SmartBarUtils.setActionBarViewCollapsable(bar, true); | |
* bar.setDisplayOptions(0); } } | |
*/ | |
public static void setActionBarViewCollapsable(ActionBar actionbar, | |
boolean collapsable) { | |
try { | |
Method method = Class.forName(“android.app.ActionBar“).getMethod( | |
“setActionBarViewCollapsable“, | |
new Class[] { boolean.class }); | |
try { | |
method.invoke(actionbar, collapsable); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} | |
} catch (SecurityException e) { | |
e.printStackTrace(); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* 调用 ActionBar.setActionModeHeaderHidden(boolean) 方法。 设置ActionMode顶栏是否隐藏。 | |
* | |
* public class MyActivity extends Activity { | |
* | |
* protected void onCreate(Bundle savedInstanceState) { | |
* super.onCreate(savedInstanceState); … | |
* | |
* final ActionBar bar = getActionBar(); | |
* | |
* // ActionBar转为ActionMode时,不显示ActionMode顶栏 | |
* SmartBarUtils.setActionModeHeaderHidden(bar, true); } } | |
*/ | |
public static void setActionModeHeaderHidden(ActionBar actionbar, | |
boolean hidden) { | |
try { | |
Method method = Class.forName(“android.app.ActionBar“).getMethod( | |
“setActionModeHeaderHidden“, new Class[] { boolean.class }); | |
try { | |
method.invoke(actionbar, hidden); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} | |
} catch (SecurityException e) { | |
e.printStackTrace(); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (ClassNotFoundException e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* 原隐藏SmartBar的方法 | |
* 此方法已从Flyme2.4.1开始失效 示例: | |
* | |
* final ActionBar actionBar = getActionBar(); SmartBarUtils.hide(this); | |
* | |
*/ | |
@Deprecated | |
public static final void hide(FragmentActivity activity) { | |
ActionBar actionBar = activity.getActionBar(); | |
if (actionBar == null) { | |
return; | |
} | |
Class<? extends ActionBar> ActionBarClass = actionBar.getClass(); | |
Method setTabsShowAtBottom; | |
try { | |
setTabsShowAtBottom = ActionBarClass.getMethod( | |
“setTabsShowAtBottom“, Boolean.TYPE); | |
setTabsShowAtBottom.invoke(activity.getActionBar(), true); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (IllegalArgumentException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* 以下三个方法原作者为c跳跳(http://weibo.com/u/1698085875), | |
* 由Shawn(http://weibo.com/linshen2011)在其基础上改进了一种判断SmartBar是否存在的方法, | |
* 注意该方法反射的接口只存在于2013年6月之后魅族的flyme固件中 | |
*/ | |
/** | |
* 方法一:uc等在使用的方法(新旧版flyme均有效), | |
* 此方法需要配合requestWindowFeature(Window.FEATURE_NO_TITLE | |
* )使用,缺点是程序无法使用系统actionbar | |
* | |
* @param decorView | |
* window.getDecorView | |
*/ | |
public static void hide(View decorView) { | |
if (!hasSmartBar()) | |
return; | |
try { | |
@SuppressWarnings(“rawtypes“) | |
Class[] arrayOfClass = new Class[1]; | |
arrayOfClass[0] = Integer.TYPE; | |
Method localMethod = View.class.getMethod(“setSystemUiVisibility“, | |
arrayOfClass); | |
Field localField = View.class | |
.getField(“SYSTEM_UI_FLAG_HIDE_NAVIGATION“); | |
Object[] arrayOfObject = new Object[1]; | |
try { | |
arrayOfObject[0] = localField.get(null); | |
} catch (Exception e) { | |
} | |
localMethod.invoke(decorView, arrayOfObject); | |
return; | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* 方法二:此方法需要配合requestWindowFeature(Window.FEATURE_NO_TITLE)使用 | |
* ,缺点是程序无法使用系统actionbar | |
* | |
* @param context | |
* @param window | |
*/ | |
public static void hide(Context context, Window window) { | |
hide(context, window, 0); | |
} | |
private static int getStatusBarHeight(Context context) { | |
int result = 0; | |
int resourceId = context.getResources().getIdentifier( | |
“status_bar_height“, “dimen“, “android“); | |
if (resourceId > 0) { | |
result = context.getResources().getDimensionPixelSize(resourceId); | |
} | |
return result; | |
} | |
/** | |
* 方法三:需要使用顶部actionbar的应用请使用此方法 | |
* | |
* @param context | |
* @param window | |
* @param smartBarHeight | |
* set SmartBarUtils.SMART_BAR_HEIGHT_PIXEL | |
*/ | |
public static void hide(Context context, Window window, int smartBarHeight) { | |
if (!hasSmartBar()) { | |
return; | |
} | |
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { | |
return; | |
} | |
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, | |
WindowManager.LayoutParams.FLAG_FULLSCREEN); | |
window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); | |
int statusBarHeight = getStatusBarHeight(context); | |
window.getDecorView() | |
.setPadding(0, statusBarHeight, 0, –smartBarHeight); | |
} | |
/** | |
* 新型号可用反射调用Build.hasSmartBar()来判断有无SmartBar | |
* @return | |
*/ | |
public static boolean hasSmartBar() { | |
try { | |
Method method = Class.forName(“android.os.Build“).getMethod( | |
“hasSmartBar“); | |
return ((Boolean) method.invoke(null)).booleanValue(); | |
} catch (Exception e) { | |
} | |
if (Build.DEVICE.equals(“mx2“)) { | |
return true; | |
} else if (Build.DEVICE.equals(“mx“) || Build.DEVICE.equals(“m9“)) { | |
return false; | |
} | |
return false; | |
} | |
} |
Share this:
码字很辛苦,转载请注明来自技术联盟的《Android获取手机底部虚拟按键高度》
2016-01-15
Android
评论