版权声明:本文为HaiyuKing原创文章,转载请注明出处!
前言
获取底部虚拟导航栏的高度值
效果图
代码分析
checkDeviceHasNavigationBar(Context context): 检测是否存在底部虚拟导航栏
getNavigationBarHeight(Context activity): 获取底部虚拟导航栏高度
使用步骤
一、项目组织结构图
注意事项:
1、导入类文件后需要change包名以及重新import R文件路径
2、Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖
二、导入步骤
将NavUtils复制到项目中
package com.why.project.navutilsdemo.utils; import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.os.Build;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager; import java.lang.reflect.Method; /**
* Created by HaiyuKing
* Used 底部虚拟导航栏工具类
*/ public class NavUtils {
private static final String TAG = NavUtils.class.getSimpleName(); private NavUtils() {
throw new RuntimeException("NavUtils cannot be initialized!");
} /**
* 获取状态栏的高度
*/
public static int getStatusBarHeight(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return resourceId > 0 ? context.getResources().getDimensionPixelSize(resourceId) : 0;
} else {
return 0;
}
} /**
* 获取底部虚拟导航栏高度
* @param activity
* @return
*/
public static int getNavigationBarHeight(Context activity) {
//方法2:有问题
/*if (!checkDeviceHasNavigationBar(activity)) {
return 0;
}
Resources resources = activity.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height",
"dimen", "android");
//获取NavigationBar的高度
int height = resources.getDimensionPixelSize(resourceId);
return height;*/ //方法1
boolean hasNavigationBar = navigationBarExist(scanForActivity(activity)) && !vivoNavigationGestureEnabled(activity);
Log.e(TAG,"{getNavigationBarHeight}hasNavigationBar="+hasNavigationBar);
if (!hasNavigationBar) {//如果不含有虚拟导航栏,则返回高度值0
return 0;
}
Resources resources = activity.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height",
"dimen", "android");
//获取NavigationBar的高度
int height = resources.getDimensionPixelSize(resourceId);
return height;
} /*========================================方法1======================================================*/
/**
* 通过获取不同状态的屏幕高度对比判断是否有NavigationBar
* https://blog.csdn.net/u010042660/article/details/51491572
* https://blog.csdn.net/android_zhengyongbo/article/details/68941464*/
public static boolean navigationBarExist(Activity activity) {
WindowManager windowManager = activity.getWindowManager();
Display d = windowManager.getDefaultDisplay(); DisplayMetrics realDisplayMetrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
d.getRealMetrics(realDisplayMetrics);
} int realHeight = realDisplayMetrics.heightPixels;
int realWidth = realDisplayMetrics.widthPixels; DisplayMetrics displayMetrics = new DisplayMetrics();
d.getMetrics(displayMetrics); int displayHeight = displayMetrics.heightPixels;
int displayWidth = displayMetrics.widthPixels;
return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
} /**解决java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to android.app.Activity问题
* https://blog.csdn.net/yaphetzhao/article/details/49639097*/
public static Activity scanForActivity(Context cont) {
if (cont == null)
return null;
else if (cont instanceof Activity)
return (Activity)cont;
else if (cont instanceof ContextWrapper)
return scanForActivity(((ContextWrapper)cont).getBaseContext()); return null;
} /**
* 获取vivo手机设置中的"navigation_gesture_on"值,判断当前系统是使用导航键还是手势导航操作
* @param context app Context
* @return false 表示使用的是虚拟导航键(NavigationBar), true 表示使用的是手势, 默认是false
* https://blog.csdn.net/weelyy/article/details/79284332#更换部分被拉伸的图片资源文件
*/
public static boolean vivoNavigationGestureEnabled(Context context) {
int val = Settings.Secure.getInt(context.getContentResolver(), "navigation_gesture_on", 0);
return val != 0;
} /*========================================方法2======================================================*/
/**
* 检测是否有底部虚拟导航栏【有点儿问题,当隐藏虚拟导航栏后,打开APP,仍然判断显示了虚拟导航栏】
* @param context
* @return
*/
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;
}
}
三、使用方法
package com.why.project.navutilsdemo; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView; import com.why.project.navutilsdemo.utils.NavUtils; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private TextView tv_show; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); tv_show = (TextView) findViewById(R.id.tv_show); int navigationBarHeight = NavUtils.getNavigationBarHeight(this);
tv_show.setText("底部虚拟导航栏高度值为:"+navigationBarHeight + ",单位为px");
}
}
混淆配置
无
参考资料
Android ContextThemeWrapper cannot be cast to android.app.Activity
项目demo下载地址
https://github.com/haiyuKing/NavUtilsDemo
NavUtils【底部虚拟导航栏工具类】的更多相关文章
-
android: 获取屏幕高度和虚拟导航栏高度的几种方法
package com.yongdaimi.android.androidapitest; import android.app.Activity; import android.content.Co ...
-
Flutter实例一--底部规则导航栏制作
先来看看制作效果: 前置知识--StatefulWidget StatefulWidget具有可变状态(state)的窗口组件(widget).使用时要根据变化状态,调整State值, 能够快速初始 ...
-
5.5修改xadmin的头部底部和导航栏名称
1.修改xadmin的头部标题和底部信息: 在users模块中的adminx.py中添加修改函数: from xadmin import views class GlobalSettings(obje ...
-
iOS 导航栏 工具条
导航栏最常见的例子就是返回按钮的所在 在AppDelegate.m中,代码布局最开始定义窗口的时候, _window.rootViewController就应该为一个UINavigationContr ...
-
adjustResize模式下ExpandaleListView中输入框焦点错乱及布局底部的导航栏被顶在键盘上方的处理
为了更好的用户体验,煎熬了许久,得到这么个解决方案.在此记录下来,以供后来者参考. 第一部分 清单文件中组件activity的android:windowSoftInputMode属性值的含义: [A ...
-
【Android】隐藏底部虚拟按键
Google的官方文档是: https://developer.android.com/training/system-ui/navigation.html#behind 示例代码 1 View de ...
-
Android应用底部导航栏(选项卡)实例
现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图: 其 ...
-
【转】Android应用底部导航栏(选项卡)实例
现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图: 其 ...
-
Flutter实战视频-移动电商-03.底部导航栏制作
03.底部导航栏制作 material是谷歌退出的 还有另外的一种:cupertino是IOS的风格 我们底部的导航栏,静态的widget是不合适的,这垃圾我们用到动态的widget 这重新改成动态的 ...
随机推荐
-
【Big Data】HADOOP集群的配置(一)
Hadoop集群的配置(一) 摘要: hadoop集群配置系列文档,是笔者在实验室真机环境实验后整理而得.以便随后工作所需,做以知识整理,另则与博客园朋友分享实验成果,因为笔者在学习初期,也遇到不少问 ...
-
RP
关键印象 Base note 任务(task):一段代码. 进程(process):程序的实体,一个正在运行中的可执行文件.拥有独立的虚拟内存空间和系统资源,包括端口权限. 线程(thread):进程 ...
-
HttpHelper类登录淘宝联盟并下载淘宝客订单xls
本次开发环境与工具如下:IE9.0浏览器 + IE抓包插件HttpWatch +WIN7 64位系统 + VS2005 IDE + .NET 2.0框架本想上传HttpWatch抓包插件,但由于文件超 ...
-
Mysql之执行计划
1.explain分析sql语句 例如: EXPLAIN ) ORDER BY bi.`publish_time` 返回结果: 而今天检查的不是这条sql,远比这条复杂,不过也能反映情况了. (1 ...
-
scala言语基础学习三
map的操作 访问fangwemap元素 修改map元素 遍历map sortmap和linkmap map元素类型tuple
-
boost 编译
备份一下,用的时候直接粘贴,免得到处找>_< 32 bjam threading=multi link=static runtime-link=static --stagedir=stag ...
-
nginx gzip on
# Gzip settings. gzip on; gzip_http_version 1.0;默认值是1.1 gzip_comp_level ; #压缩级别,1压缩比最小处理速度最快,9压缩比最大但 ...
-
python单元测试框架unittest总结
unittest.TestCase:TestCase类,所有测试用例类继承的基本类. class BaiduTest(unittest.TestCase): TestCase类的属性如下: setUp ...
-
EFCore Owned Entity Types,彩蛋乎?鸡肋乎?之鸡肋篇
鸡肋 鸡肋(Chicken ribs),现代汉语词语,出自<三国志·魏书·武帝纪>裴松之注引<九州春秋>曰:"夫鸡肋,弃之如可惜,食之无所得,以比汉中,知王欲还也.& ...
-
FFmpeg封装格式处理3-复用例程
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506653.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...