屏幕适配方案

前言:屏幕适配说白了就是将设计图按宽或高进行整体等比缩放。

方案:如设计图分辨率(宽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即可。

实现:只需在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?) {}
        })
    }
}

补充说明:

1、字体大小由scaledDensity控制,默认scaledDensity==density,当用户修改系统字体后scaledDensity缩放至(当前的scaledDensity  / 系统默认density)倍,如无需字体跟随系统设置可直接将scaledDensity设置为density同时也无需监听系统字体切换

2、density=dpi*160      dpi为软件层面在系统配置文件定义的值,而ppi为物理层面一英寸对应的像素值

3、宽高限定符适配方案(需要定义需要适配的机型分辨率):values-800x480  如果手机屏幕分辨率不满足我们定义的将使用默认的values

4、sw限定符适配(需要定义需要适配的机型宽度dp):values-sw350dp 如果手机屏幕dp不满足我们定义的系统会向下寻找最近的资源文件

5、设置density要在setContentView之前进行,否则不生效

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值