文章目录

  • 一、简述
  • 二、追根溯源
  • 三、实现
    • 3.1 定义Density用于对系统类值的修改
    • 3.2 在MainActivity中调用
    • 3.3 处理应用程序关于字体大小的监听
    • 3.4 如果多界面统一处理怎么办?
      • 3.4.1 BaseActivity
      • 3.4.2 监听应用程序的变化
  • 四、完整代码

一、简述

修改density(屏幕密度,若每英寸有160像素点,该值就为1)、scaleDensity(字体缩放比例),densityDpi(屏幕上每英寸有多少像素点,如160)的值,就是修改系统内部对于目标尺寸而言的像素密度。

二、追根溯源

每个控件的显示,dp、sp等最终都会转换成px为单位,原因在于android源码TypedValue#applyDimension:

public static float applyDimension(int unit, float value,DisplayMetrics metrics)
{switch (unit) {case COMPLEX_UNIT_PX:return value;case COMPLEX_UNIT_DIP:return value * metrics.density;case COMPLEX_UNIT_SP:return value * metrics.scaledDensity;case COMPLEX_UNIT_PT:return value * metrics.xdpi * (1.0f/72);case COMPLEX_UNIT_IN:return value * metrics.xdpi;case COMPLEX_UNIT_MM:return value * metrics.xdpi * (1.0f/25.4f);}return 0;
}

传入的参数分别是:单位、值、屏幕显示的DisplayMetrics 对象。通过上面的源码可以看出,不管传入的是什么单位,最终都会被转换成px。所以,如果要修改控件的尺寸,只需要修改metrics.density或metrics.scaledDensity即可。修改density和自定义view适配中的scaleX、scaleY类似,不同的设备下的density也不同,同一个分辨率下的density也有可能不一样。所以要对density进行调整,使其跟随分辨率来进行变换。
假设目标设备的像素密度为160,运行设备的像素密度为320,这样算出来的dp值就是320/160=2。既然要修改,就要给出参考像素密度。

三、实现

3.1 定义Density用于对系统类值的修改

定义静态方法setDensity,需要传入application和activity。获取当前app的屏幕显示信息:

     DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();

定义成员变量表示屏幕密度、字体缩放比例:

    private static float appDensity;//表示屏幕密度private static float appScaleDensity; //字体缩放比例,默认appDensity

if判断赋值:

 appDensity = displayMetrics.density;appScaleDensity = displayMetrics.scaledDensity;

随后计算目标值density, scaleDensity, densityDpi:

 float targetDensity = displayMetrics.widthPixels / WIDTH; //比如 1080 / 360 = 3.0float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);int targetDensityDpi = (int) (targetDensity * 160);

替换Activity的density, scaleDensity, densityDpi:

        DisplayMetrics dm = activity.getResources().getDisplayMetrics();dm.density = targetDensity;dm.scaledDensity = targetScaleDensity;dm.densityDpi = targetDensityDpi;

3.2 在MainActivity中调用

必须在setContentView方法前调用:Density.setDensity(getApplication(),this);这样,参考设备(UI设计图)的宽为320dp,在xml中写160dp就表示显示为宽度的一半,并且在任何设备上都会显示为屏幕的一半。

3.3 处理应用程序关于字体大小的监听

手机设置中设置字体显示大小,必须对其回调进行处理,否则改变配置不会适配文字大小。

//添加字体变化监听回调application.registerComponentCallbacks(new ComponentCallbacks() {@Overridepublic void onConfigurationChanged(Configuration newConfig) {//字体发生更改,重新对scaleDensity进行赋值if (newConfig != null && newConfig.fontScale > 0){appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;}}@Overridepublic void onLowMemory() {//低内存情况,暂不用考虑}});

3.4 如果多界面统一处理怎么办?

3.4.1 BaseActivity

BaseActivity中调用Density.setDensity(getApplication(),this);

3.4.2 监听应用程序的变化

Application的onCreate方法中注册监听:

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks()

这里每当一个Activity启动,都会去回调对应的方法,在对应的回调方法中调用Density.setDensity(App.this, activity);即可

四、完整代码

Density.java

public class Density {private static final float  WIDTH = 320;//参考设备的宽,单位是dp 320 / 2 = 160private static float appDensity;//表示屏幕密度private static float appScaleDensity; //字体缩放比例,默认appDensitypublic static void setDensity(final Application application, Activity activity){//获取当前app的屏幕显示信息DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();if (appDensity == 0){//初始化赋值操作appDensity = displayMetrics.density;appScaleDensity = displayMetrics.scaledDensity;//添加字体变化监听回调application.registerComponentCallbacks(new ComponentCallbacks() {@Overridepublic void onConfigurationChanged(Configuration newConfig) {//字体发生更改,重新对scaleDensity进行赋值if (newConfig != null && newConfig.fontScale > 0){appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;}}@Overridepublic void onLowMemory() {//低内存情况,暂不用考虑}});}//计算目标值density, scaleDensity, densityDpifloat targetDensity = displayMetrics.widthPixels / WIDTH; // 1080 / 360 = 3.0float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);int targetDensityDpi = (int) (targetDensity * 160);//替换Activity的density, scaleDensity, densityDpiDisplayMetrics dm = activity.getResources().getDisplayMetrics();dm.density = targetDensity;dm.scaledDensity = targetScaleDensity;dm.densityDpi = targetDensityDpi;}}

App.java

public class App extends Application {@Overridepublic void onCreate() {super.onCreate();registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {Density.setDensity(App.this, activity);}@Overridepublic void onActivityStarted(Activity activity) {}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) {}});}
}

修改系统density适配相关推荐

  1. 屏幕适配--修改系统density进行屏幕适配

    上次发了自定义像素适配后,有小伙伴问我修改density到底是怎么做的.遇到这个问题,我是懒得写一篇博客来说明的,但是当我准备搜一篇发链接给他时,看到好多博客写的并不完整或者看不明白,所以我就自己写吧 ...

  2. android修改系统density,Android应用开发Android 修改系统默认density

    本文将带你了解Android应用开发Android 修改系统默认density,希望本文对大家学Android有所帮助. 如你所知在Anroid N 中,系统添加了多个级别的密度值供用户选择. 系统的 ...

  3. 修改系统density, densityDpi 适配

    Density 工具类 修改density,scaleDensity,densityDpi 值,直接更改系统内部对于目标尺寸而言的像素密度. public class Density {private ...

  4. Android屏幕适配-修改全局density

    转自:https://www.jianshu.com/p/e02cd88ae062,记录一下,以便查阅 屏幕适配好几种,目前主流且成本最低的还是修改系统density的方案. 概念 像素:屏幕的最小单 ...

  5. Android 屏幕适配(修改系统字体大小、显示大小、修改分辨率相关适配)

    Android实际开发中会遇到各种各样的机型,所以就需要对多种机型进行适配.常见的适配在这类就不详细介绍了,大家可以参考这里的系列文章Android通用屏幕适配讲解的已经很详细了.下面说的是:当修改系 ...

  6. 通过修改sw来适配应用界面——源码修改

    一.前言 我遇到的问题主要就是在自研 PAD 横屏时,微信应用的登录界面中,"登录" 和 "注册" 按钮堆叠在一起了.这个明显就是微信应用没有适配对应 sw 的 ...

  7. 华为鸿蒙系统智能手机_余承东再度确认:鸿蒙系统将适配到华为手机上

    近期余承东承认华为芯片不够用,麒麟芯片也将在9月15日暂时停产,华为麒麟芯片或将成为绝唱已经确定为事实,这显然是有点遗憾的事情,不过华为也有好消息传来,那就是余承东再度确认鸿蒙系统将适配到手机上,具体 ...

  8. 深入理解HTTPS及在iOS系统中适配HTTPS类型网络请求(上)

    2019独角兽企业重金招聘Python工程师标准>>> 深入理解HTTPS及在iOS系统中适配HTTPS类型网络请求 一.引言 本篇博客主要讨论如何在客户端与服务端之间进行HTTPS ...

  9. 新版小爱课程表正方教务系统课表适配

    新版小爱课程表正方教务系统课表适配 前言 之前写过一篇小爱课程表的教务系统适配,但是是比较老的版本开发者工具适配了,最近看到小爱课程表开发者工具更新了,就想着写一篇新的博客,顺便优化一下之前的代码,还 ...

最新文章

  1. Android SDK上手指南:虚拟与物理设备
  2. 数据远程实时备份容灾方案
  3. 上周五,小编参加了一场高大上的“9”会
  4. 东北大学计算机分数线2017,东北大学2017年艺术类专业录取分数线
  5. 数据结构与算法之美-排序(下)
  6. 汇编怎么从内存地址写入连续的数字_汇编语言 第一章 基础知识
  7. 解决方案-vector初始化后存放Mat,出现Mat矩阵数据同变问题
  8. 使用JSON作为函数的参数(转载)
  9. JSP项目《教师年终个人成果统计系统的设计与应用》实战(一)——密码加密算法...
  10. 计算机相关知识抢答题题库,计算机基础知识抢答赛题库
  11. php 安装扩展管理工具 pecl
  12. [强化学习实战]马尔可夫决策-悬崖寻路python实现
  13. WIN7使用手机蓝牙共享网络,及利用蓝牙及WLAN实现双网卡同时上内外网
  14. Learning Standard C++ as a New Language ( By Bjarne Stroustrup )
  15. 护眼体验新升级,引领2023护眼风潮,南卡Pro护眼台灯评测报告
  16. Linux下vi命令编辑器怎样编辑,怎样保存退出
  17. 夺命雷公狗—玩转SEO---44---外链群发原理
  18. 随机车牌号python
  19. 计算机与应用课程,计算机基础与应用课程的教学探讨
  20. C语言中break和continue区别

热门文章

  1. 周长相等的正方形面积一定相等_习题创编——周长相等的长方形面积(20200108)...
  2. (轉貼) 美電腦工程師改寫遊戲軟體向女友求婚成功 (News)
  3. @RequestParam @PathVariable
  4. 第55件事 产品疯传的7个基本原则
  5. 解锁新姿势 |如何利用配置中心规范构建PaaS服务配置
  6. 西安电子地图下载 来自谷歌电子地图库 地图展示15、17、19级
  7. cogs 服务点设置
  8. 基于matlab的退化图像复原(二)------逆滤波复原
  9. F5负载均衡的初识和基本配置
  10. jeecg3.5.2中上传下载文件的示例中的的一个bug