前言:屏幕適配說白了就是將設計圖按寬或高進行總體等比縮放。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不知足咱們定義的系統會向下尋找最近的資源文件資源