屏幕适配基础图标
drawable 选择器, shape标签 ,帧动画列表 密度值 分辨率 密度比
drawable-ldpi 低分辨率目录 120 240320 0.75 公式 密度值除160
drawable-mdpi 中等分辨率目录 160 320480 1
drawable-hdpi 高分辨率目录 240 480800 1.5
drawable-xhdpi 特高分辨率目录 320 7201280 2
drawable-xxhpi 超高分辨率目录 480 1080*1920 3
drawable-xxxhdpi 超超高分辨率目录
在屏幕密度是120的手机上 1dp=0.75px
在屏幕密度是160的手机上 1dp=1px
在屏幕密度是240的手机上 1dp=1.5px
在屏幕密度是320的手机上 1dp=2px
在屏幕密度是480的手机上 1dp=3px
在屏幕密度是640的手机上 1dp=4px
宽度是100px 160 100dp
宽度是100px 240 66.7dp
宽度是100px 320 50dp
宽度是100px 480 33.3dp
宽度是100px 640 25dp
适配市场上主流的手机屏幕(流量研究院,全域罗盘)
今日头条适配
大概的实现原理:
px = dp * density
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
mPx:当前设备屏幕总宽度(变化)
mDp:设计图总宽度(不变)
mDensity: mPx/mDp 系数比(变化)
- 假设当前设备的屏幕总宽度为1080px,当前设计图总宽度为375dp,根据以上计算出mDensity为2.88
屏幕上有一个50dp50dp的控件,转化为px是50dp2.88=144px
144px/1080px=0.133 即此控件占屏幕的实际比例为0.133
- 2.假设当前设备的屏幕总宽度为1440 px,当前设计图总宽度为375dp,根据以上计算出mDensity为 3.84
屏幕上有一个50dp50dp的控件,转化为px是50dp 3.84= 192px
192px/1080px=0.133 即此控件占屏幕的实际比例为0.133
由此可看出,随着屏幕大小的变化,控件的实际占比是一样的
第一步:
使用步骤:
implementation 'me.jessyan:autosize:0.9.1'
2.声明设计图中的尺寸(如果项目完全使用副单位, 则可以直接以像素为单位填写 AndroidManifest 中需要填写的设计图尺寸, 不需再把像素转化为 dp)
<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>
3.MyApplication中(记得清单文件注册)可以设置副单位(只能在 pt、in、mm 这三个冷门单位中选择一个作为副单位,选择什么单位就在 layout 文件中用什么单位进行布局)。
AutoSizeConfig.getInstance().getUnitsManager()
.setSupportDP(false).setSupportSubunits(Subunits.MM);
副单位是用于规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
副单位是用于规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
public enum Subunits {
/**
* 不使用副单位
*/
NONE,
/**
* 单位 pt
*
* @see android.util.TypedValue#COMPLEX_UNIT_PT
*/
PT,
/**
* 单位 in
*
* @see android.util.TypedValue#COMPLEX_UNIT_IN
*/
IN,
/**
* 单位 mm
*
* @see android.util.TypedValue#COMPLEX_UNIT_MM
*/
MM
}
/**
isBaseOnWidth()
是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只>能在宽度和高度之中选一个作为基准进行适配)@return {@code true} 为按照宽度适配, {@code false} 为按照高度适配
*/
/**
getSizeInDp()
返回设计图上的设计尺寸, 单位 dp
{@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸,
{@link #getSizeInDp} 则返回 {@code 0}
@return 设计图上的设计尺寸, 单位 dp
Activity(BaseActivity)
public class CustomAdaptActivity extends AppCompatActivity implements CustomAdapt {
@Override
public boolean isBaseOnWidth() {
return false;
}
@Override
public float getSizeInDp() {
return 667;
}
}
Fragment
public class CustomAdaptFragment extends Fragment implements CustomAdapt {
@Override
public boolean isBaseOnWidth() {
return false;
}
@Override
public float getSizeInDp() {
return 667;
}
}
XML
<TextView
android:layout_width="200mm"
android:layout_height="100mm"
android:background="@color/colorAccent" />
完整demo
<!-- 这个 Demo 主要展示副单位的用法, 如果只使用副单位 (pt、in、mm) 就可以直接以像素作为单位填写设计图的尺寸, 不需再把像素转化为 dp-->
<meta-data
android:name="design_width_in_dp"
android:value="1080"/>
<meta-data
android:name="design_height_in_dp"
android:value="1920"/>
BaseApplication
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//对单位的自定义配置, 请在 App 启动时完成
configUnits();
}
/**
* 注意!!! 布局时的实时预览在开发阶段是一个很重要的环节, 很多情况下 Android Studio 提供的默认预览设备并不能完全展示我们的设计图
* 所以我们就需要自己创建模拟设备, 以下链接是给大家的福利, 按照链接中的操作可以让预览效果和设计图完全一致!
* @see <a href="https://github.com/JessYanCoding/AndroidAutoSize/blob/master/README-zh.md#preview">dp、pt、in、mm 这四种单位的模拟设备创建方法</a>
* <p>
* v0.9.0 以后, AndroidAutoSize 强势升级, 将这个方案做到极致, 现在支持5种单位 (dp、sp、pt、in、mm)
* {@link UnitsManager} 可以让使用者随意配置自己想使用的单位类型
* 其中 dp、sp 这两个是比较常见的单位, 作为 AndroidAutoSize 的主单位, 默认被 AndroidAutoSize 支持
* pt、in、mm 这三个是比较少见的单位, 只可以选择其中的一个, 作为 AndroidAutoSize 的副单位, 与 dp、sp 一起被 AndroidAutoSize 支持
* 副单位是用于规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
* 您选择什么单位, 就在 layout 文件中用什么单位布局
* <p>
* 两个主单位和一个副单位, 可以随时使用 {@link UnitsManager} 的方法关闭和重新开启对它们的支持
* 如果您想完全规避修改 {@link DisplayMetrics#density} 所造成的对于其他使用 dp 布局的系统控件或三方库控件的不良影响
* 那请调用 {@link UnitsManager#setSupportDP}、{@link UnitsManager#setSupportSP} 都设置为 {@code false}
* 停止对两个主单位的支持 (如果开启 sp, 对其他三方库控件影响不大, 也可以不关闭对 sp 的支持)
* 并调用 {@link UnitsManager#setSupportSubunits} 从三个冷门单位中选择一个作为副单位
* 三个单位的效果都是一样的, 按自己的喜好选择, 比如我就喜欢 mm, 翻译为中文是妹妹的意思
* 然后在 layout 文件中只使用这个副单位进行布局, 这样就可以完全规避修改 {@link DisplayMetrics#density} 所造成的不良影响
* 因为 dp、sp 这两个单位在其他系统控件或三方库控件中都非常常见, 但三个冷门单位却非常少见
*/
private void configUnits() {
//AndroidAutoSize 默认开启对 dp 的支持, 调用 UnitsManager.setSupportDP(false); 可以关闭对 dp 的支持
//主单位 dp 和 副单位可以同时开启的原因是, 对于旧项目中已经使用了 dp 进行布局的页面的兼容
//让开发者的旧项目可以渐进式的从 dp 切换到副单位, 即新页面用副单位进行布局, 然后抽时间逐渐的将旧页面的布局单位从 dp 改为副单位
//最后将 dp 全部改为副单位后, 再使用 UnitsManager.setSupportDP(false); 将 dp 的支持关闭, 彻底隔离修改 density 所造成的不良影响
//如果项目完全使用副单位, 则可以直接以像素为单位填写 AndroidManifest 中需要填写的设计图尺寸, 不需再把像素转化为 dp
AutoSizeConfig.getInstance().getUnitsManager()
.setSupportDP(false)
//当使用者想将旧项目从主单位过渡到副单位, 或从副单位过渡到主单位时
//因为在使用主单位时, 建议在 AndroidManifest 中填写设计图的 dp 尺寸, 比如 360 * 640
//而副单位有一个特性是可以直接在 AndroidManifest 中填写设计图的 px 尺寸, 比如 1080 * 1920
//但在 AndroidManifest 中却只能填写一套设计图尺寸, 并且已经填写了主单位的设计图尺寸
//所以当项目中同时存在副单位和主单位, 并且副单位的设计图尺寸与主单位的设计图尺寸不同时, 可以通过 UnitsManager#setDesignSize() 方法配置
//如果副单位的设计图尺寸与主单位的设计图尺寸相同, 则不需要调用 UnitsManager#setDesignSize(), 框架会自动使用 AndroidManifest 中填写的设计图尺寸
// .setDesignSize(2160, 3840)
//AndroidAutoSize 默认开启对 sp 的支持, 调用 UnitsManager.setSupportSP(false); 可以关闭对 sp 的支持
//如果关闭对 sp 的支持, 在布局时就应该使用副单位填写字体的尺寸
//如果开启 sp, 对其他三方库控件影响不大, 也可以不关闭对 sp 的支持, 这里我就继续开启 sp, 请自行斟酌自己的项目是否需要关闭对 sp 的支持
// .setSupportSP(false)
//AndroidAutoSize 默认不支持副单位, 调用 UnitsManager#setSupportSubunits() 可选择一个自己心仪的副单位, 并开启对副单位的支持
//只能在 pt、in、mm 这三个冷门单位中选择一个作为副单位, 三个单位的适配效果其实都是一样的, 您觉的哪个单位看起顺眼就用哪个
//您选择什么单位就在 layout 文件中用什么单位进行布局, 我选择用 mm 为单位进行布局, 因为 mm 翻译为中文是妹妹的意思
//如果大家生活中没有妹妹, 那我们就让项目中最不缺的就是妹妹!
.setSupportSubunits(Subunits.MM);
}
BaseActivity
public class BaseActivity extends AppCompatActivity implements CustomAdapt {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_adapt);
}
/**
* 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配)
*
* @return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配
*/
@Override
public boolean isBaseOnWidth() {
return false;
}
/**
* 这里使用 iPhone 的设计图, iPhone 的设计图尺寸为 750px * 1334px, 因为这个页面使用副单位进行布局
* 所以可以直接以像素作为单位返回设计图的尺寸
* <p>
* 返回设计图上的设计尺寸
* {@link #getSizeInDp} 须配合 {@link #isBaseOnWidth()} 使用, 规则如下:
* 如果 {@link #isBaseOnWidth()} 返回 {@code true}, {@link #getSizeInDp} 则应该返回设计图的总宽度
* 如果 {@link #isBaseOnWidth()} 返回 {@code false}, {@link #getSizeInDp} 则应该返回设计图的总高度
* 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, {@link #getSizeInDp} 则返回 {@code 0}
*
* @return 设计图上的设计尺寸
*/
@Override
public float getSizeInDp() {
return 1334;
}