基本概念
相关术语
- px:像素;
- dpi:即densityDpi,每英寸中的像素数;
- density:屏幕密度,density = dpi / 160;
- scaledDensity:字体的缩放因子,正常情况下和density相等,可以通过调节系统字体大小改变该值。
android中的dp在渲染前会将dp转为px,公式如下:
p
x
=
d
e
n
s
i
t
y
∗
d
p
px = density * dp
px=density∗dp
限定符匹配
匹配规则:当前dpi > 更高的dpi > 更低的dpi
以图片为例,图片资源的文件夹分为mdpi、hdpi、xhdpi xxhdpi xxxhdpi等。
假设当前设备密度为xhdpi,文件夹为上述5种,则查找顺序为:xhdpi > xxhdpi > xxxhdpi > hdpi > mdpi 。
XML布局适配
动态加载布局
给res目录中的子目录加上“-限定符”,可以给不同设备提供不同的资源以及布局。
指定屏幕大小:-sw+指定大小
例如限定480到1080屏幕,1080以上屏幕:layout-sw480dp,layout-sw1080dp
sw,Smallest-width,最小宽度限定符。
指定屏幕方向:-land、-port
创建自适应布局
思路:尽量不要把view宽高边距等写死,而是设置权重或百分比让其自适应。
缺点:绘图时为实现自适应需要反复测量计算布局的属性,增加开销。
方法:
-
使用LinearLayout时,通过设置
layout_weight
让各个视图自适应大小。
ConstraintLayout
百分比布局
设置水平和竖直方向百分比偏移,左上角为(0,0),右下角为(1,1)。
<TextView
...
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintVertical_bias="0.3" />
设置宽高比
高固定,将宽设为高的两倍:将layout_width
设为0,设置layout_constraintDimensionRatiov
属性。
“2:1” → \rightarrow → w:h = 2:1
“w,2:1” → \rightarrow → w:h = 2:1
“h,2:1” → \rightarrow → h:w = 2:1
<TextView
android:layout_width="0dp"
...
layout_constraintDimensionRatiov="2:1" />
添加引导线
请点击工具栏中的 Guidelines,添加一条用户看不见的引导线。
网格布局
使用链控制线性组,实现网格布局
样式 | 功能 |
---|---|
spread | 默认值 均匀分布 |
spread inside | 首尾固定在两端,中间均匀分布 |
weighted | 权重 |
packed | 紧挨在一起 |
官方示图如下:
对其不同尺寸的文字
TextView 自带边距,当同一段文字中,文字尺寸不同时,边距也不同。
如下图,若直接让两个View的底部对齐,会发现文字不在同一水平线上。
事实上,TextView中存在文本基线,右键点击要添加约束的文本视图,选择 Show Baseline,随后直接将该文本基线并拖到另一TextView的基线上。
图片适配
ScaleType属性
- 以
FIT_
开头的,都会对图片进行缩放; - 以
CENTER_
开头的,图片的中心点会与ImageView
的中心点重叠;
scaleType | 缩放 | 展示位置 | 缺点 |
---|---|---|---|
FIT_CENTER(默认) FIT_START FIT_END | 等比缩放 | 居中 居左上 居右下 | 控件留白 |
FIT_XY | 非等比拉伸 | 填满控件 | 拉伸变形 |
CENTER | 不缩放 | 居中 | 控件留白/图片显示不全 |
CENTER_INSIDE | 等比缩小,不可放大 | 居中 | 控件留白 |
CENTER_CROP | 等比缩放 | 居中填满控件 | 图片显示不全 |
.9图
文件的后缀名是.9.png
左侧、上侧黑色横线:可拉伸区域
右侧、下侧黑色横线:内容区域
刘海屏适配
刘海区域位于状态栏中,若要全屏显示,则需适配。
参考
整体放缩
思路
重设屏幕属性:density、densityDpi、scaledDensity
核心代码
假设以宽为基准进行适配,设计图尺寸1920x1080,代码如下:
//获取设备原始值
val appDm = application.resources.displayMetrics
val appSD = appDm.scaledDensity
//增加对系统配置的监听,用于监听系统字体的改变
application.registerComponentCallbacks(object : ComponentCallbacks {
override fun onConfigurationChanged(newConfig: Configuration) {
if (newConfig!=null && newConfig.fontScale>0){
appSD = application.resources.displayMetrics.scaledDensity
}
}
override fun onLowMemory() {
}
})
//计算目标值
val targetDensity = appDm.widthPixels / 1080; //此以宽为基准,高同理。
val targetDensityDpi = (int) (targetDensity * 160);
val targetScaledDensity = appSD * (targetDensity / appDm.density);
//改变设备值
val dm = activity.resources.displayMetrics
dm.density = targetDensity;
dm.densityDpi = targetDensityDpi;
dm.scaledDensity = targetScaledDensity;
参考
今日头条:一种极低成本的Android屏幕适配方式
dDensity;
## 参考
[Android官网:屏幕兼容性概览](https://developer.android.google.cn/guide/practices/screens_support?hl=zh-cn)
[今日头条:一种极低成本的Android屏幕适配方式](https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA)