屏幕适配
首先声明:本人只是一名大四在校学生,没有实际开发的屏幕适配经验,以下都是个人学习所得,说得不妥之处请指正。
总结来说:有些产品在后期屏幕适配一大堆麻烦,有的却很轻松。为什么呢?这与你平时写代码的是否有良好的习惯有关。
减少后期屏幕适配的良好编程习惯:
- 多用相对布局和线性布局(权重weight)。
- 用dp不用px。
- 用sp不用px。
- 代码中如果需要动态设置尺寸的话,不直接设置px,而是根据当前设备的设备密度,将dp转化为px后再设置。
**图片适配**
dpi : 屏幕像素密度是指每英寸上的像素点数。屏幕像素密度与屏幕尺寸和屏幕分辨率有关.
在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。
px:像素。 分辨率就是用的像素为单位,Android原生API都会以px作为统一的计量单位,像屏幕宽高等。
dip和dp:屏幕像素密度。dp和px换算:dp = px / 设备密度
sp:文字大小首选项进行放缩,是设置字体大小的单位
Android项目目录下一般有mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,
用来区分不同像素密度下的图片和dimen值。
名称 像素密度范围
ldpi 随着移动设备配置的不断升级,这个像素密度的设备已经很罕见了,所在现在适配时不需考虑。
mdpi 120dpi~160dpi
hdpi 160dpi~240dpi
xhdpi 240dpi~320dpi
xxhdpi 320dpi~480dpi
xxxhdpi 480dpi~640dpi
屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点
会根据手机的分辨率,自动的选择相近分辨率的资源文件里的图片来显示。
所以开发时,把合适大小的图片放在合适的文件夹里面,一般根据当前市场主流手机主流的分辨率做一套图片
**布局适配**(不常用)
Android项目目录下一般只有一个layout目录,里面放的都是布局文件,其实你可以新建出更多的layout文件夹,命名方式是layout-land、
layout-xlarge、layout-sw720dp等。
但需要注意的是,一般都不会添加额外的控件。如果你多加了一个按钮,那么两种不同的分辨率下,你findViewById是找个按钮呢还是不找呢?
一般用途在于,你的app在某一款手机的分辨率下出现问题,你就可以根据这个分辨率单独做一个布局文件以适应该分辨率。
**尺寸适配**
Android项目目录下有一个values目录,里面有个名为dimens的xml文件。它一般是各种各样控件尺寸的声明,但如果公司一般没有要求的情况下我们
都直接写在了布局文件当中。但是我们得知道这个xml文件时用来做什么的。
其实尺寸适配最重要的是知道上文中提到的 dp 与 px 的转化。
dp = px / 设备密度。
常见的设备的分辨率与设备密度
320x480 1.0
480x800 1.5
240x320 0.75
1280x720 2
我们很常见的一个问题就是,你做出一款产品,在当前市场主流机型和主流分辨率上布局、尺寸都是正常的,但是如果在一个特别大分辨率的手机上
就可能会被挤成一坨,造成这个的根本原因就是控件在该大分辨率下的width、height、margin或者padding都是不够的。为什么呢?
举个例子:
情景:在你的app某个activity中有一个TextView,你给TextView的宽度设置为160dp:
*在320x480的手机中,根据dp与px的换算公式,可以得到该TextView在320x480的真机上实际上是
160dp x 1.0(设备密度)= 160px。刚好是屏幕的一半。显示正常。
*在480x800的手机中,160dp x 1.5(设备密度)= 240px。刚好也是屏幕的一半。显示正常。
*在1280x780的手机中,160dp x 2(设备密度)= 320px,就只有屏幕的四分之一了,显示是不正常的。
那这种情况下该怎么办呢?这时你就可以将上文提到的values文件夹,新建一个values-1280*720的文件夹,里面重写dimens文件,
将在该分辨率下显示有问题的控件一一重新声明尺寸即可。
那么问题来了,在实际开发中,我们如果要动态的设定一个控件的尺寸,是只能设置像素px,而不能设置dp的,那这种情况下该怎么办?
也很简单,你可以写一个工具类,将dp与px互相转化。附上转换代码。
public class DensityUtil {
/**
* 根据手机的分辨率从 dip 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float density = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * density + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float density = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / density + 0.5f);
}
}
总结一点,在实际开发中,
尽量多用dp而不尽量不用px,在可以尺寸匹配的情况下不去布局匹配。(这个为什么?因为更简单啊)
**权重适配**
权重适配是应用于线性布局LinearLayout当中。它是一些控件的属性,weight。
如果在某个方向上使用了weight ,那么我们必须在对应的方向上将width设置为0dp. 它告诉了我们设置为0dp是因为使用weight,系统是采用了另外一套计算占用空间大小的算法的
通俗来说:一旦View设置了权重weight属性,那么该 View的宽度等于原有宽度(android:layout_width)加上剩余空间(减去其他View控件所占宽度)的占比。
总结一点:在实际开发当中,在线性布局中,
能用weight权重的地方尽量用,因为它在任何分辨率的手机上显示的都是同一个效果。
可以给后期屏幕适配省去不少麻烦。当然它有一定局限性,比如只能在线性布局中使用,而且复杂的布局中很难派上用场。
**代码适配**
基本上就是解决屏幕适配的终极办法了,就是运行时动态获得手机屏幕属性,来动态设置View控件的尺寸。
常见的一个场景就是,如果你的app有一个侧边栏,比如我们是使用第三方的SlidingMenu,我们会设置它为屏幕预留空间,setBehindOffset(int pixels)。
我们就可以动态获取屏幕宽度,取屏幕的三分之二即可。(这些简单代码就不累赘叙述了)