首页 文章 精选 留言 我的

精选列表

搜索[MLA 技术],共10000篇文章
优秀的个人博客,低调大师

HBase技术资料下载(持续更新)

标题 下载地址 HBase在车联网中的实践与应用 下载 HBase在爱奇艺的应用实践 下载 HBase2.0重新定义小对象实时存取 下载 HBase基本知识介绍及典型案例分析 下载 HBase Coprocessor 下载 在多租户环境中提高HBase可用性 下载 Quanta:Quora的HBase分层计数系统 下载 HBase中的事务 下载 HBase 高可用HA 下载 HBase In-Memory Compaction 下载 gohbase :HBase go客户端 下载 使用Apache Beam和HBase进行高效数据处理 下载 Democratizing HBase 下载 Apache Spark – Apache HBase Connector 下载 HBase在滴滴的实践 下载 HBase 多租户 下载 HBase 和 Phoenix 的使用 下载 时序及分析在hbase上的使用 下载

优秀的个人博客,低调大师

Android APP全面屏适配技术要点

全面屏的概念 为什么先要解释一下全面屏,因为这个词在现在来讲就是一个伪命题。全面屏字面意思就是手机的正面全部都是屏幕,100%的屏占比。但是现在推出所谓“全面屏”手机的厂商没有一个能达到全面的。 那么下面来说一下Android开发领域对全面屏的理解和定义吧。 一般手机的屏幕纵横比为16:9,如1080x1920、1440x2560等,其比值为1.77,在全面屏手机出现之前,Android中默认的最大屏幕纵横比(maximum aspect ratio)为1.86,即能够兼容16:9的屏幕。 一些手机厂商为了追求更大的屏幕空间以及更极致的用户体验,于是提高了屏幕纵横比,17:9、19:10、18:9、18.5:9的手机开始进入市场,这些手机的屏幕纵横比大大超过了1.86,这些手机被称为全面屏手机。 为何需要适配 我们将targetSdkVersion的值改为小于等于23,运行程序,我们会发现屏幕底部出现一个黑条。 image 如何适配 targetSdkVersion<=23,更大的屏幕纵横比 在Galaxy S8发布之后,Android官方提供了适配方案,即提高App所支持的最大屏幕纵横比,实现很简单,在AndroidManifest.xml中可做如下配置: <meta-data android:name="android.max_aspect" android:value="ratio_float"/> 其中ratio_float为浮点数,官方建议为2.1或更大,因为18.5:9=2.055555555……,如果日后出现纵横比更大的手机,此值将会更大。 <meta-data android:name="android.max_aspect" android:value="2.1" /> max_aspect值也可以在Java代码中动态地设置,通过下面的方法即可实现: public void setMaxAspect() { ApplicationInfo applicationInfo = null; try { applicationInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if(applicationInfo == null){ throw new IllegalArgumentException(" get application info = null "); } applicationInfo.metaData.putString("android.max_aspect", "2.1"); } 如果targetSdkVersion的值的值大于23,那么应该不用设置max_aspect即可。 查看适配之后的截图: image https://android-developers.googleblog.com/2017/03/update-your-app-to-take-advantage-of.html 图片资源适配 我们看一下启动页,在16:9屏幕中适配的图片,到了18:9的屏幕中就会被拉伸了。 16:9屏幕中显示 18:9屏幕中显示 image image 解决这个问题无非就是两种方法,换图片或者是换布局 换图片 不能依赖单一厂商的解决方案,只能从Android系统属性出发。考虑到目前大部分全面屏手机只是在高度上拉长,且大多为6.0英寸左右,像素密度对比xxhdpi并没有多大区别,那我们可以在项目中增加一组资源drawable-xxhdpi-2160x1080 、drawable-long 这样解决图片的拉伸问题,当然这样的方法肯定是不太好的,会增加app的容量。这里就不演示了。 优化布局 当然最好的方法还是用相对布局采用XML的方式,或者.9图的解决方案。 我总结的就是少量多切,尽量减少尺寸对布局的影响。比如这里,使用正方形的切图,让他居中显示,无论屏幕纵横比如何,都不会拉伸这个图片,拉伸的只是背景而已。 image <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" android:src="@drawable/bz002"/> 适配前 适配后 image image 全面屏高度问题适配 首先解释一下window,decorview,rootview这几个概念 image Window官方文档:Window public abstract class Window. Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc. The only existing implementation of this abstract class is android.view.PhoneWindow, which you should instantiate when needing a Window. 翻译一下:每一个 Activity 都持有一个 Window 对象,但是 Window 是一个抽象类,这里 Android 为 Window 提供了唯一的实现类 PhoneWindow。也就是说 Activity 中的 window 实例就是一个 PhoneWindow 对象。 但是 PhoneWindow 终究是 Window,它并不具备多少 View 相关的能力。不过 PhoneWindow 中持有一个 Android 中非常重要的一个 View 对象 DecorView. 现在的关系就很明确了,每一个 Activity 持有一个 PhoneWindow 的对象,而一个 PhoneWindow 对象持有一个 DecorView 的实例,所以 Activity 中 View 相关的操作其实大都是通过 DecorView 来完成。 DecorView就可以理解为手机的内屏,就是那块玻璃,可以发光的屏幕。 这里通过代码,打印出我们页面中的高度的各项数据 int decorviewHeight = decorView.getHeight(); int screenHeight = FullScreenManager.getScreenHeight(); int nativeBarHeight = FullScreenManager.getNativeBarHeight(); int contentViewHeight = rootView.getHeight(); int navigationBarHeight1 = FullScreenManager.getNavigationBarHeight(); Log.d("shijiacheng","======================================="); Log.d("shijiacheng","DecorView height: " + decorviewHeight + " px"); Log.d("shijiacheng","Screen height: " + screenHeight + " px"); Log.d("shijiacheng","NativeBar height: " + nativeBarHeight + " px"); Log.d("shijiacheng","ContentView height: " + contentViewHeight + " px"); Log.d("shijiacheng","NavigationBar height: " + navigationBarHeight + " px"); Log.d("shijiacheng","---------------------------------------"); 获取decorView的高度 final View decorView = getWindow().getDecorView(); int decorviewHeight = decorView.getHeight(); 获得屏幕高度 /** * 获得屏幕高度 * @return */ public static int getScreenHeight() { Resources resource = AppContext.getInstance().getResources(); DisplayMetrics displayMetrics = resource.getDisplayMetrics(); return displayMetrics.heightPixels; } 获取状态栏的高度 /** * 获取状态栏的高度 * * @return */ public static int getNativeBarHeight() { Resources resource = AppContext.getInstance().getResources(); int result = 0; int resourceId = resource.getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = resource.getDimensionPixelSize(resourceId); } return result; } 获取contentView的高度 LinearLayout contentView = findViewById(R.id.root); int contentViewHeight = contentView.getHeight(); 获取NavigationBar的高度 public static int getNavigationBarHeight() { Resources resources = AppContext.getInstance().getResources(); int resourceId = resources.getIdentifier("navigation_bar_height","dimen", "android"); int height = resources.getDimensionPixelSize(resourceId); return height; } 为了更加直观的展示各个数据,这里我们使用布局的方式将各个数据展示出来,布局代码比较简单,这里就不展示了。 image 先展示一下正常的屏幕高度的各项数据 10-08 09:52:03.636 23818-23818/? D/shijiacheng: ========================= 10-08 09:52:03.637 23818-23818/? D/shijiacheng: DecorView height: 1280 px 10-08 09:52:03.637 23818-23818/? D/shijiacheng: Screen height: 1280 px 10-08 09:52:03.637 23818-23818/? D/shijiacheng: NativeBar height: 50 px 10-08 09:52:03.637 23818-23818/? D/shijiacheng: ContentView height: 1230 px 10-08 09:52:03.637 23818-23818/? D/shijiacheng: NavigationBar height: 96 px 10-08 09:52:03.637 23818-23818/? D/shijiacheng: ------------------------- image DecorView = Screen height = NativeBar height + ContentView height 看一下小米mix全面屏的情况 2018-10-08 09:54:15.640 /? D/shijiacheng: ========================= 2018-10-08 09:54:15.640 /? D/shijiacheng: DecorView height: 2160 px 2018-10-08 09:54:15.641 /? D/shijiacheng: RootView height: 2094 px 2018-10-08 09:54:15.641 /? D/shijiacheng: Screen height: 2030 px 2018-10-08 09:54:15.641 /? D/shijiacheng: NativeBar height: 66 px 2018-10-08 09:54:15.641 /? D/shijiacheng: ContentView height: 2094 px 2018-10-08 09:54:15.641 /? D/shijiacheng: NavigationBar height: 130 px 2018-10-08 09:54:15.641 /? D/shijiacheng: ------------------------- image 问题出现了,可以发现contentView的高度比screen屏幕的高度还要大,不禁要怀疑,我们的获取屏幕高度的方法在全面屏下计算错误了。 问题1:获取屏幕高度方法计算不准确 我们一直都是使用如下方法进行屏幕高度测量的: public static int getScreenHeight() { Resources resource = AppContext.getInstance().getResources(); DisplayMetrics displayMetrics = resource.getDisplayMetrics(); return displayMetrics.heightPixels; } 但是这个方法却是一个十分古老的方法,没有与时俱进,虽然说在普通屏幕上这种方法没有问题,但是在全面屏手机上来说,这种方法就不灵了。 下面我们就来研究一下获取屏幕尺寸的方法的演进。 获取屏幕宽高 获取屏幕的宽高是我们开发中经常遇到的问题,而且相信大家都已经非常熟悉,最常用的为以下两种: public static int getScreenHeight1(Activity activity) { return activity.getWindowManager().getDefaultDisplay().getHeight(); } public static int getScreenHeight2(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.heightPixels; } 其实以上两种方式是一样的,只不过第二种是把信息封装到 DesplayMetrics中,再从DesplayMetrics得到数据。 在 Android 3.2(Api 13) 之后又提供了如下的一个方法,将数据封装到Point中,然后返回宽度高度信息。 @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) public static int getScreenHeight3(Activity activity) { Point point = new Point(); activity.getWindowManager().getDefaultDisplay().getSize(point); return point.y; } 在 Android 4.2(Api17) 之后提供了如下方法,与第三种类似也是将数据封装到Point中,然后返回款高度信息。 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static int getScreenHeight4(Activity activity) { Point realSize = new Point(); activity.getWindowManager().getDefaultDisplay().getRealSize(realSize); return realSize.y; } 其实getRealSize这个方法在Android Api15的时候就已经加入了,不过是被隐藏了,通过查阅源码我们可以看到。 image Android Api15 Display.java源码中getRealSize()方法被标记为@hide image 因此,我们可以重写获取高度的方法,适配所有机型,所有系统。 适配所有屏幕的获取屏幕尺寸的方法 public static int[] getScreenSize(Context context) { int[] size = new int[2]; WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display d = w.getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); d.getMetrics(metrics); // since SDK_INT = 1; int widthPixels = metrics.widthPixels; int heightPixels = metrics.heightPixels; // includes window decorations (statusbar bar/menu bar) if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17) try { widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d); heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d); } catch (Exception ignored) { } // includes window decorations (statusbar bar/menu bar) if (Build.VERSION.SDK_INT >= 17) try { Point realSize = new Point(); Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize); widthPixels = realSize.x; heightPixels = realSize.y; } catch (Exception ignored) { } size[0] = widthPixels; size[1] = heightPixels; return size; } 使用新的获取高度的方法,重新运行程序,运行结果已经正常显示了。 2018-10-08 13:19:32.389 /? D/shijiacheng: ========================== 2018-10-08 13:19:32.390 /? D/shijiacheng: DecorView height: 2160 px 2018-10-08 13:19:32.390 /? D/shijiacheng: Screen height: 2160 px 2018-10-08 13:19:32.390 /? D/shijiacheng: NativeBar height: 66 px 2018-10-08 13:19:32.390 /? D/shijiacheng: ContentView height: 2094 px 2018-10-08 13:19:32.390 /? D/shijiacheng: NavigationBar height: 130 px 2018-10-08 13:19:32.390 /? D/shijiacheng: -------------------------- image 问题2:小米mix切为经典导航键模式下的计算问题 我们在MIUI设置中将全面屏导航样式修改为“经典导航键”样式。 image 重新运行程序,运行结果如下: image 可以发现又出问题了,DecorView = Screen height > NativeBar height + ContentView height 这里不难发现,Screen height将底部虚拟导航栏的高度也算进里面了。 很多情况下,我们都用如下方法获取导航栏的高度: public static int getNavigationBarHeight() { Resources resources = AppContext.getInstance().getResources(); int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); int height = resources.getDimensionPixelSize(resourceId); return height; } 这种方法得到的导航栏的高度数值是没问题的,但是在全面屏的手机上,即使隐藏了导航栏,也是可以获取到导航栏的高度的。通过上面的logcat日志可以看到,即使没有导航栏,导航栏的高度的计算也是有值的。 适配小米mix虚拟导航栏 小米mix的机型中,我们可以“force_fsg_nav_bar”来判断小米手机是否开启了全面屏手势。 public static int getHeightOfNavigationBar(Context context) { //如果小米手机开启了全面屏手势隐藏了导航栏则返回 0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0) != 0) { return 0; } } int realHeight = getScreenSize(context)[1]; Display d = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); d.getMetrics(displayMetrics); int displayHeight = displayMetrics.heightPixels; return realHeight - displayHeight; } 因此可以通过这个方法来判断是否显示了底部导航栏,并且可以计算导航栏的高度。 int navigationBarHeight = FullScreenManager.getHeightOfNavigationBar(MainActivity.this); if (navigationBarHeight > 0){ container_navigationview.setVisibility(View.VISIBLE); }else { container_navigationview.setVisibility(View.GONE); } 正常的显示效果如下: 有虚拟导航栏 没有虚拟导航栏 image image 没有虚拟导航栏Log 2018-10-08 13:19:32.389 /? D/shijiacheng: ========================== 2018-10-08 13:19:32.390 /? D/shijiacheng: DecorView height: 2160 px 2018-10-08 13:19:32.390 /? D/shijiacheng: Screen height: 2160 px 2018-10-08 13:19:32.390 /? D/shijiacheng: NativeBar height: 66 px 2018-10-08 13:19:32.390 /? D/shijiacheng: ContentView height: 2094 px 2018-10-08 13:19:32.390 /? D/shijiacheng: NavigationBar height: 0 px 2018-10-08 13:19:32.390 /? D/shijiacheng: -------------------------- 有虚拟导航栏Log 2018-10-08 13:38:03.229 /? D/shijiacheng: ========================== 2018-10-08 13:38:03.230 /? D/shijiacheng: DecorView height: 2160 px 2018-10-08 13:38:03.230 /? D/shijiacheng: Screen height: 2160 px 2018-10-08 13:38:03.230 /? D/shijiacheng: NativeBar height: 66 px 2018-10-08 13:38:03.230 /? D/shijiacheng: ContentView height: 1964 px 2018-10-08 13:38:03.230 /? D/shijiacheng: NavigationBar height: 130 px 2018-10-08 13:38:03.230 /? D/shijiacheng: --------------------------

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册