Android屏幕适配
2019-02-22 本文已影响0人
Zcurry
屏幕适配.png
关于屏幕适配,我们先来看下官方文档上说了些什么!
👇👇👇👇👇👇
屏幕适配:文档上翻译为屏幕兼容性
dpi(来源于官方视频).png 关于配置限定符的官方表格👈 部分截图.png 👆👆👆👆👆👆
- 必须遵循的核心原则是避免对界面组件的位置和大小进行硬编码。应该允许拉伸视图尺寸并指定视图相对于父视图或其他同级视图的位置。
- 像素密度是屏幕上单位面积内的像素数,称为 dpi(每英寸的点数)。它与分辨率不同,后者是屏幕上像素的总数。
- 使用像素来定义布局尺寸会带来问题,因为不同的屏幕具有不同的像素密度,因此同样数量的像素在不同设备上可能对应于不同的物理尺寸。
- dp 是一种密度无关像素,对应于 160 dpi 下像素的物理尺寸。 sp 是相同的基本单位,但它会按用户首选的文本尺寸进行缩放(属于缩放无关像素),因此在定义文本尺寸时应使用此计量单位(但切勿为布局尺寸使用该单位)。
以上选取的是官方文档中屏幕兼容性的主要内容。或许正是受了文档的指向,在之前我们大多数的屏幕适配方案都采用最小宽度限定符的方式(更早之前采用宽高限定符);另一方面,随着刘海屏、全面屏不断的引入市场,碎片化越来越重。导致最小宽度限定符适配越来越沉重。因此新的适配方案应运而生,今日头条的屏幕适配方案👈将这个问题重新拉回视线。
关于其原理,文章中已经说的很清楚了。简单来讲,就是固定的一个维度,重新获取density的值(density = 设备真实宽(单位px) / UI设计图宽)。上代码🐎。
/**
* 今日头条方案----核心代码(仍需扩展)
* Android适配:修改设备密度
*/
public class DisplayUtil {
//UI提供的设计图尺寸
private static final int UI_MEASURE = 360;
private static float sNoncompatDensity;
private static float sNoncompatScaledDensity;
public static void setCustomDensity(@NonNull Activity activity, @NonNull final Application application) {
//获取DisplayMetrics对象
DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
if (sNoncompatDensity == 0) {
//获取density密度
sNoncompatDensity = appDisplayMetrics.density;
//获取scaledDensity--字体的缩放因子
sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
// 防止系统切换后不起作用--如果在系统设置中切换字体,再返回应用,字体并没有变化
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (newConfig != null && newConfig.fontScale > 0) {
sNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
}
}
@Override
public void onLowMemory() {
}
});
}
float targetDensity = appDisplayMetrics.widthPixels / UI_MEASURE;
// 防止字体变小
// 某些用户在系统中修改了字体大小失效了,但是不能直接用原始的scaledDensity,直接用的话可能导致某些文字超过显示区域
float targetScaleDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity);
int targetDensityDpi = (int) (160 * targetDensity);
/**
* 设置application中的值
*/
appDisplayMetrics.density = targetDensity;
appDisplayMetrics.scaledDensity = targetScaleDensity;
appDisplayMetrics.densityDpi = targetDensityDpi;
/**
* 设置activity中的值
*/
final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDensity;
activityDisplayMetrics.scaledDensity = targetScaleDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}
}
目前项目中采用的方案为最小宽度限定符。其优势,就是稳定,不会出现较大的问题。目前常用sw文件有:xhdpi(320)、360、400、411、420、xxhpdi(480)、560...[hdpi(240\可选)]。
参考链接:
https://developer.android.com/guide/practices/screens_support
https://www.jianshu.com/p/b6b9bd1fba4d
https://www.jianshu.com/p/1302ad5a4b04
https://www.jianshu.com/p/55e0fca23b4f?utm_source=oschina-app
https://juejin.im/post/5c18039d5188253b7e74987e