android中一种方便的适配方案

android设备众多,这致使适配各类机型很麻烦,其中屏幕适配也是一件棘手的事情。其中一种方式是在res文件夹下,根据不一样的屏幕分辨率创建一一对应的values文件夹,以下图所示: java

其实这种适配方式也能够知足适配要求,使用起来中规中矩的感受。今天我想介绍另一种适配方案,那就是github.com/JessYanCodi…android

使用姿式

  • 添加依赖

implementation 'me.jessyan:autosize:1.1.2'git

  • manifest文件中添加以下配置
<manifest>
    <application>            
        <meta-data android:name="design_width_in_dp" android:value="360"/>
        <meta-data android:name="design_height_in_dp" android:value="640"/>           
     </application>           
</manifest>
复制代码
  • 界面适配
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {

    @Override
    public boolean isBaseOnWidth() {
        return false;
    }

    @Override
    public float getSizeInDp() {
        return 667;
    }
}
复制代码

若是某个特殊的activity不须要适配,则实现CancelAdapt接口github

public class CancelAdaptActivity extends AppCompatActivity implements CancelAdapt {

}
复制代码

fragment的适配跟activity如出一辙,都是实现CustomAdapt接口进行适配,实现CancelAdapt接口告诉框架不须要适配.markdown

  • 使用过程当中遇到的问题
  1. 在接入第三方库的时候,第三方的activity和fragment也要进行适配,否则就会报以下错误

“java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wdg.tradecenter/com.yanzhenjie.permission.PermissionActivity}:java.lang.IllegalArgumentException: you must set design_width_in_dp in your AndroidManifest file”app

能够在Application#onCreate方法中添加以下代码取消对指定的activity和fragment取消适配检查框架

AutoSizeConfig.getInstance()
                .getExternalAdaptManager()
                .addCancelAdaptOfActivity(PermissionActivity.class);
复制代码
  • 应用

上图是lanhu上的一张ui设计图,咱们点击控件,右下角直接就出现了对应的xml代码,使用autosize进行适配,就能够直接使用lanhu上生成的布局代码,这一点确实方便了一些。ide

框架原理

  • 单位
单位 解释
px 像素
dp 独立设备像素 计算公式:px = dp(dpi/160)
dpi 像素密度,指的是在系统软件上指定的单位尺寸的像素数量,它每每是写在系统出厂配置文件的一个固定值

经过上面的单位介绍及之间的转换,咱们能够获得以下结论:oop

px= dp(dpi/160), density = dpi/160 => px = dp*density => dp = px/density; 明白上面这个结论,下面咱们来讨论为何咱们平常对控件设置的宽/高为某一dp时,没法作到各个手机屏幕的适配。布局

设备 A , 屏幕宽度为 720px, dpi为160,则屏幕总dp为 720/(160/160) = 720 dp 设备 B , 屏幕宽度为 720px, dpi为320,则屏幕总dp为 720/(320/160) = 360 dp 能够看到屏幕的总 dp 宽度在不一样的设备上是会变化的,可是咱们在布局中填写的 dp 值倒是固定不变的,这就致使咱们设置的固定宽度在不一样的设备上显示的比例不同。 例如咱们布局中有一个View设置固定宽度为180dp,在设备A中会占屏幕宽度的1/4,可是在设备B中只会占屏幕宽度的1/2,这种差异是十分巨大的。

这时咱们要想完美适配,那就必须保证这个 View 在任何分辨率的屏幕上,与屏幕的比例都是相同的。

解决方案

由公式:dp = px/density 可知,因为px是屏幕分辨率,这个值有硬件肯定,咱们是没法改变的,那么咱们能够经过修改density 的值使得不一样分辨率的手机宽度dp值是相同的,这样当咱们对View设置为某一特定的dp宽度时,占总宽度的dp比例是相同的,这样也就达到占屏幕的比例相同。

那么问题来了,咱们如何肯定density 的值呢?

由dp = px/density => 屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度

屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度 => 当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density

若是咱们将一套设计图的总宽度(dp)做为最终手机屏幕的中宽度(dp), 从而达到修改density的目的,同时又能够保证最终不一样分辨率手机的屏幕总宽度是相同的,这也就完成了适配。

AndroidAutoSize/今日头条 就是基于这个原理来实现屏幕适配的。

AndroidAutoSize是怎么以最小侵入代价应用上述原理的

利用ContentProvider初始化该库—— ContentProvideronCreate的调用时机介于ApplicationattachBaseContextonCreate之间。

在初始化的时候注册了一个Application.ActivityLifecycleCallbacks接口类回调

application.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks); 在接口Application.ActivityLifecycleCallbacks的实现类中修改density,以达到适配目的。

总结 这个适配方案优势明显

使用成本低,简单。 代码侵入性低 没有性能损耗 可适配activity/fragment/dialog/toast等 缺点

既然AndroidAutoSize库能够修改density,其它库也能够修改,那么这样就会致使冲突。

相关文章
相关标签/搜索