目录
一、为什么要适配
由于Android系统的开放性,OEM厂商、运营商都可以对Android进行定制,于是导致运行 Android 的设备多种多样,它们有着不同的屏幕尺寸和像素密度。
尽管系统可通过基本的缩放和调整大小功能使界面适应不同屏幕,但你应做出进一步优化,以确保界面能够在各类屏幕上美观地呈现。
例如UI以375px宽度来设计,如果你直接使用1dp=1px的这种方式来写代码,那么在不同屏幕的手机上面的显示可能是不一样的,这就需要你来做适配。
二、几个重要的概念
2.1 屏幕尺寸
屏幕尺寸指屏幕的对角线的长度,单位是英寸(inch),1英寸=2.54厘米
还有一些特殊屏幕尺寸,例如Redmi K40:6.67英寸。
这个一般在设置关于手机中查看自己的屏幕尺寸。
2.2 屏幕分辨率
屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以「纵向像素x横向像素,如1080x2400」。表示宽度方向上有1080个像素点,在高度方向上有2400个像素点
2.3 屏幕像素密度
屏幕像素密度是指每英寸上的像素点数,单位是dpi,即"dot per inch"的缩写。
屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。
安卓手机对于每类手机屏幕大小都有一个相应的屏幕像素密度:
2.4 屏幕尺寸、分辨率、像素密度三者关系
像素密度(dpi) =宽高/屏幕大小。
例如:屏幕分辨率为1080x2400,屏幕尺寸为6.67来计算。
1. 像素密度(dpi) = / 6.67
2. 像素密度(dpi) = 6926400 / 6.67
3. 394.573532825 = 6926400 / 6.67
三、常用单位
3.1 密度无关像素(dp)
density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。可以保证在不同屏幕像素密度的设备上显示相同的效果
3.2 独立比例像素(sp)
sp,即scale-independent pixels,与dp类似,但是可以根据文字大小首选项进行放缩,是设置字体大小的御用单位。
3.3 dp与px的转换
在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px。
px = dp * (dpi / 160)
四、解决方案
4.1 今日头条
px值 = dp值 * metrics.density
,这里的density
是指的手机的屏幕密度,由系统提供,不同的手机的density
可能不同;所以我们不能直接使用系统的density
,需要篡改density
来达到适配的目的
public class MainActivity extends AppCompatActivity {
private static float sNoncompatDensity;// 系统的Density
private static float sNoncompatScaleDensity;// 系统的ScaledDensity
private static void setCustomDensity(Activity activity, final Application application){
final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
if(sNoncompatDensity == 0){
// 系统的Density
sNoncompatDensity = appDisplayMetrics.density;
// 系统的ScaledDensity
sNoncompatScaleDensity = appDisplayMetrics.scaledDensity;
// 监听在系统设置中切换字体
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
if(newConfig != null && newConfig.fontScale > 0){
sNoncompatScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;
}
}
@Override
public void onLowMemory() {
}
});
}
// 此处以360dp的设计图作为例子
final float targetDensity = appDisplayMetrics.widthPixels / 360;
final float targetScaledDensity = targetDensity * (sNoncompatScaleDensity/sNoncompatDensity);
final int targetDensityDpi = (int)(160 * targetDensity);
appDisplayMetrics.density = targetDensity;
appDisplayMetrics.scaledDensity = targetScaledDensity;
appDisplayMetrics.densityDpi = targetDensityDpi;
final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDensity;
activityDisplayMetrics.scaledDensity = targetScaledDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCustomDensity(this,this.getApplication());
setContentView(R.layout.activity_main);
}
}
4.2 ScreenMatch适配
Android ScreenMatch屏幕适配是一种简单适用的适配方式,是由Android官方推出的适配方法
4.2.1 下载插件
4.2.2 使用
之后会有选择项目的界面,选择你想在哪个项目中使用ScreenMatch。
根据你选择的尺寸来生成对应的values,默认有一大堆。
4.2.3 自定义values文件
在screenMatch.properties中你需要关注:
-
1.base_dp:若base_dp=360这种机型在你项目中就不可能有,你完全可以根据你项目中的基础机型来配置这个基础base_dp。我这是UI用的375,所以此处改为375。
-
2.match_dp和ignore_dp要配合使用:
-
match_dp:需要的尺寸
-
ignore_dp:忽略的尺寸
-
所有尺寸在红框上方的注解里面有。
4.3 选择适配方案->今日头条
-
1.快捷方便
-
2.后期维护调整也省事
-
3.包体小