前言:屏幕适配说白了就是将设计图按宽或高进行总体等比缩放。app
方案:如设计图分辨率(宽360px,高560px),手机屏分别率(宽1080px,高1920px),按宽进行适配须要将设计图的控件尺寸宽高等比放大(手机屏宽1080px / 设计图宽360px = 3)倍,而获取xml中定义的全部控件再分别对宽高放大3倍,这操做咱们经过代码实现,显然很繁重,然而我就将这部分工做交给系统,要知道控件在系统中宽高最终都转成px(px= density * dp),咱们就巧妙利用系统的转换公式,将density = 手机屏宽 / 设计图宽,在xml中直接将设计图px值做为dp值使用便可(如设计图控件宽360px,那么xml中宽定义为360dp)。同理按高适配只需将density = 手机屏高 / 设计图高,在xml中使用dp系统则自行进行缩放。若是有的页面须要按宽有的页面须要按高适配或同一页面不一样控件有的需按高适配有的需按高适配,咱们能够利用(px = xdpi / 72 * pt)将xdpi = 手机屏高 / 设计图高 * 72,xml中将须要按高度适配的控件宽高定义成pt,按宽度适配的控件宽高定义成dp便可。ide
实现:只需在application的onCreate方法中调用ScreenUtil的init方法便可字体
object ScreenUtil { fun init(application: Application, designWith: Float, designHeight: Float){ val appDisplayMetrics = application.resources.displayMetrics val screenWith = appDisplayMetrics.widthPixels //屏幕宽度px val screenHeight = appDisplayMetrics.heightPixels //屏幕高度px val densityDef = appDisplayMetrics.density //系统默认density appDisplayMetrics.density = screenWith / designWith appDisplayMetrics.densityDpi = (appDisplayMetrics.density * 160).toInt() appDisplayMetrics.xdpi = designHeight / screenHeight * 72 //字体跟随系统设置,默认scaleDensity==density appDisplayMetrics.scaledDensity = appDisplayMetrics.density * (appDisplayMetrics.scaledDensity / densityDef) //监听系统字体切换 application.registerComponentCallbacks(object : ComponentCallbacks{ override fun onLowMemory() {} override fun onConfigurationChanged(newConfig: Configuration?) { newConfig?.let { if (it.fontScale > 0){ appDisplayMetrics.scaledDensity = appDisplayMetrics.density * (appDisplayMetrics.scaledDensity / densityDef) } } } }) //activity生命周期监听 application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks{ override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { activity?.let { val activityDisplayMetrics = it.resources.displayMetrics activityDisplayMetrics.density = it.application.resources.displayMetrics.density activityDisplayMetrics.scaledDensity = it.application.resources.displayMetrics.scaledDensity activityDisplayMetrics.densityDpi = it.application.resources.displayMetrics.densityDpi activityDisplayMetrics.xdpi = it.application.resources.displayMetrics.xdpi } } override fun onActivityPaused(activity: Activity?) {} override fun onActivityResumed(activity: Activity?) {} override fun onActivityStarted(activity: Activity?) {} override fun onActivityDestroyed(activity: Activity?) {} override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {} override fun onActivityStopped(activity: Activity?) {} }) } }
补充说明:设计
一、字体大小由scaledDensity控制,默认scaledDensity==density,当用户修改系统字体后scaledDensity缩放至(当前的scaledDensity / 系统默认density)倍,如无需字体跟随系统设置可直接将scaledDensity设置为density同时也无需监听系统字体切换code
二、density=dpi*160 dpi为软件层面在系统配置文件定义的值,而ppi为物理层面一英寸对应的像素值xml
三、宽高限定符适配方案(须要定义须要适配的机型分辨率):values-800x480 若是手机屏幕分辨率不知足咱们定义的将使用默认的values生命周期
四、sw限定符适配(须要定义须要适配的机型宽度dp):values-sw350dp 若是手机屏幕dp不知足咱们定义的系统会向下寻找最近的资源文件资源