赞
踩
简单介绍屏幕适配(三种常用方案)
1、像素(px):
含义:通常所说的像素,就是CCD/CMOS上光电感应元件的数量,一个感光元件经过感光,光电信号转换,A/D转换等步骤以后,在输出的照片上就形成一个点,我们如果把影像放大数倍,会发现这些连续色调其实是由许多色彩相近的小方点所组成,这些小方点就是构成影像的最小单位“像素”(Pixel)。简而言之,像素就是手机屏幕的最小构成单元。
单位:px(pixel),1px = 1像素点 一般情况下UI设计师的设计图会以px作为统一的计量单位。
2、分辨率:
含义:手机在横向、纵向上的像素点数总和 一般描述成 宽*高 ,即横向像素点个数 * 纵向像素点个数(如1080 x 1920)。
单位:px(pixel),1px = 1像素点
3、屏幕尺寸(in):
含义:手机对角线的物理尺寸
单位 英寸(inch),一英寸大约2.54cm 常见的尺寸有4.7寸、5寸、5.5寸、6寸
4、屏幕像素密度(dpi):
含义:每英寸的像素点数。 例如每英寸内有160个像素点,则其像素密度为160dpi。
单位:dpi(dots per inch)
计算公式: 像素密度 = 像素 / 尺寸 (dpi = px / in)
标准屏幕像素密度(mdpi): 每英寸长度上还有160个像素点(160dpi),即称为标准屏幕像素密度(mdpi)
密度类型 代表的分辨率(px) 屏幕密度(dpi) 换算(px/dp) 比例 图片px
低密度(ldpi) 240x320 120 1dp=0.75px 3 3636
中密度(mdpi) 320x480 160 1dp=1px 4 4848
高密度(hdpi) 480x800 240 1dp=1.5px 6 7272
超高密度(xhdpi) 720x1280 320 1dp=2px 8 9696
超超高密度(xxhdpi) 1080x1920 480 1dp=3px 12 144*144
一.Autolayout 用法 鸿洋地址 https://blog.csdn.net/qq_37237245/article/details/78134010
1、将autolayout引入
dependencies {
compile project(’:autolayout’)
}
也可以直接
dependencies {
compile ‘com.zhy:autolayout:1.4.5’
}
2、标明设计稿尺寸
在AndroidManifest
3、使用时候有两种用法:
一种是让你的Activity继承自AutoLayoutActivity.一般可以把你的基类继承AutoLayoutActivity
如果你觉得这种对你的activity改变太大等等,,,
那么,你可以将你的布局替换成
LinearLayout -> AutoLinearLayout
RelativeLayout -> AutoRelativeLayout
FrameLayout -> AutoFrameLayout
系统原有的属性都会保留。
ps:几个注意事项
1、可以多用margin,减少嵌套,因为不需要考虑适配问题,所以,可以直接margin固定距离尺寸等等,
LinearLayout的weight也不需要,直接每个布局设置相同宽度即可。
2、textview使用中发现很多问题,直接用px会出现高度不对问题。鸿洋这样解释:设计稿一般只会标识一个字体的大小
,比如你设置textSize=”20px”,实际上TextView所占据的高度肯定大于20px,字的上下都会有一定的间隙,所以一定要
灵活去写字体的高度,比如对于text上下的margin可以选择尽可能小一点。或者选择别的约束条件去定位(比如上例,选
择了marginBottom)
但是更简单的处理方式是,我们的字体尺寸可以继续用sp.
3、在listview ,recycleview 或者一些布局我们无法转换为autoXXX的布局,我们想为子布局做适配的时候,我们需要
用到同一个方法, AutoUtils.autoSize(convertView);我们可以实例化出来子布局,然后设置适配,那么这个子布局将
会适配auto布局。
对于ListView
对于ListView这类控件的item,默认根局部写“px”进行适配是无效的,因为外层非AutoXXXLayout,而是ListView。但
是,不用怕,一行代码就可以支持了:
@Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder = null;
if (convertView == null){
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
convertView.setTag(holder);
//对于listview,注意添加这一行,即可在item上使用高度
AutoUtils.autoSize(convertView);
} else{
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
注意AutoUtils.autoSize(convertView);这行代码的位置即可。demo中也有相关实例。
对于RecyclerView
public ViewHolder(View itemView){
super(itemView);
AutoUtils.autoSize(itemView);
}
//…
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View convertView = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_item, parent, false);
return new ViewHolder(convertView);
}
一定要记得LayoutInflater.from(mContext).inflate使用三个参数的方法!
当然大家现在也没谁用这种low炸了,直接写adapter了吧,太麻烦了,BaseQucickAdapter是一个高达14k的强大的adapter,
二 百分比的引入(需要一个jar包)
1、引入
其实我们的解决方案,就是在项目中针对你所需要适配的手机屏幕的分辨率各自简历一个文件夹。
如下图:
然后我们根据一个基准,为基准的意思就是:
比如480*320的分辨率为基准
宽度为320,将任何分辨率的宽度分为320份,取值为x1-x320
高度为480,将任何分辨率的高度分为480份,取值为y1-y480
例如对于800*480的宽度480:
可以看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;
其他分辨率类似~~
你可能会问,这么多文件,难道我们要手算,然后自己编写?不要怕,下文会说。
那么,你可能有个疑问,这么写有什么好处呢?
假设我现在需要在屏幕中心有个按钮,宽度和高度为我们屏幕宽度的1/2,我可以怎么编写布局文件呢?
<Button
android:layout_gravity="center"
android:gravity="center"
android:text="@string/hello_world"
android:layout_width="@dimen/x160"
android:layout_height="@dimen/x160"/>
三 smallestWidth 限定符 适配原理
smallestWidth 限定符适配原理与屏幕分辨率限定符适配原理一样,系统都是根据限定符去寻找对应的 dimens.xml 文件。例如程序运行在最小宽度为 360dp 的设备上,系统会自动找到对应的 values-sw360dp 文件夹下的 dimens.xml 文件。区别就在于屏幕分辨率限定符适配是拿 px 值等比例缩放,而 smallestWidth 限定符适配是拿 dp 值来等比缩放而已。需要注意的是“最小宽度”是不区分方向的,即无论是宽度还是高度,哪一边小就认为哪一边是“最小宽度”。如下分别为最小宽度为 360dp 与最小宽度为 640dp 所对应的 dimens.xml 文件:
获取设备最小宽度代码为:
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int heightPixels = dm.heightPixels;
int widthPixels = dm.widthPixels;
float density = dm.density;
float heightDP = heightPixels / density;
float widthDP = widthPixels / density;
float smallestWidthDP;
if(widthDP < heightDP) {
smallestWidthDP = widthDP;
}else {
smallestWidthDP = heightDP;
}
为什么选择 smallestWidth 限定符适配?
既然原理都一样,都需要多套 dimens.xml 文件,那为什么要选择 smallestWidth 限定符适配呢?
屏幕分辨率限定符适配是根据屏幕分辨率的,Android 设备分辨率一大堆,而且还要考虑虚拟键盘,这样就需要大量的 dimens.xml 文件。因为无论手机屏幕的像素多少,密度多少,90% 的手机的最小宽度都为 360dp,所以采用 smallestWidth 限定符适配只需要少量 dimens.xml 文件即可。
屏幕分辨率限定符适配采用的是 px 单位,而 smallestWidth 限定符适配采用的单位是 dp 和 sp,dp 和 sp 是google 推荐使用的计量单位。又由于很多应用要求字体大小随系统改变,所以字体单位使用 sp 也更灵活。
屏幕分辨率限定符适配需要设备分辨率与 values-xx 文件夹完全匹配才能达到适配,而 smallestWidth 限定符适配寻找 dimens.xml 文件的原理是从大往小找,例如设备的最小宽度为 360dp,就会先去找 values-360dp,发现没有则会向下找 values-320dp,如果还是没有才找默认的 values 下的 demens.xml 文件,所以即使没有完全匹配也能达到不错的适配效果。
使用步骤
1、以设计图最小宽度(单位为 dp)作为基准值,生成所有设备对应的 dimens.xml 文件
生成这些文件当然不会手动去写,网上已经有大神 android阿杜 提供了自动生成工具。
工具使用步骤:
在 Android Studio 中安装 ScreenMatch 插件,如图:
在项目的默认 values 文件夹中需要一份 dimens.xml 文件
我在 github 源码已经提供了一份,直接复制过来即可。
执行生成
插件安装好后,在项目的任意目录或文件上右键,选择 ScreenMatch 选项。如下图:
然后选择在哪个 module 下执行适配。即基于哪个 module 下的 res/values/dimens.xml 文件作为基准 dimens.xml 文件,生成的其他尺寸 dimens.xml 文件放在哪个 module 下。例如选择 app,然后点击 OK ,出现如下界面表示生成文件成功。如下图:
然后再看看 res 目录下会自动生成一堆 dimens.xml 文件,如下图:
通过上面的步骤就已经生成了所有设备对应的 dimens.xml 文件。
根据设计图填写最小宽度基准值,并填写需要适配的设备最小宽度 dp 值
步骤 3 是以插件默认的最小宽度基准值为 360dp,适配的设备最小宽度为
384,392,400,410,411,432,480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365(包含了平板和 TV )生成的文件,但实际情况要根据设计图和需求设置。
例如设计图的最小宽度为 375dp,则需要更改最小宽度基准值为 375dp。如果项目只需要适配手机的话,适配的设备最小宽度保留 320,360,384,392,400,410,411,480 即可,若发现手机还有其他最小宽度自行加上即可,也麻烦把该最小宽度提供给我,我们一起来完善该份适配。
以上修改需要在配置文件里修改,即screenMatch.properties 文件,该配置文件是执行完上面第 3 步后自动生成在项目的跟目录下的。如下图:
打开配置文件,修改下图中 1、3、4 的值即可。(图中单位均为 dp)
1:最小宽度基准值,填写设计图的最小宽度值即可。
2:插件默认适配的最小宽度值,即默认情况下会生成如下值的 dimens.xml 文件。
3:需要适配的最小宽度值,即你想生成哪些 dimens.xml 文件。
4:忽略不需要适配的最小宽度值,即忽略掉插件默认生成的 dimens.xml 文件。
配置文件修改完成后,重新执行第 3 步,生成新的 dimens.xml 文件。
当然!如果你的设计图也是标准的 360dp,那么上面的步骤你可以忽略。直接复制我 github 上你需要的 dimens.xml 文件到你的项目即可,默认的 values 文件夹下也需要一份。
2、根据设计图标注,在布局写上对应的值。
设计图标注多少 dp,布局中就写多少 dp ,非常方便!
大多数 UI 设计师提供设计图有如下几种方式:
上传到蓝湖:显示多少 dp 就写多少 dp。
psd 源文件:用像素大厨查看,显示多少 dp 就写多少 dp(注意像素大厨需要选择与设计图对应的dpi 进行显示)
dp 单位的设计图:标注多少 dp 就写多少 dp。
px 单位的设计图:叫 UI 设计师标注为 dp 单位或跟她要 psd 源文件,如果都不行,那自己算吧!
举例:例如设计图上一个Button 的宽为 360dp,高为 50dp,字体大小为 15 sp,在布局中则这样使用:
代码中动态设置 dp 或 sp:
如果需要在代码中动态设置 dp 或 sp,则需要通过 getDimension()方法获取对应资源文件下的 dp 或 sp 值再设置(具体参考 github 上的 demo)。如下:
/获取sp值/
float pxValue = getResources().getDimension(R.dimen.sp_15);//获取对应资源文件下的sp值
int spValue = ConvertUtils.px2sp(this, pxValue);//将px值转换成sp值
mTvShowParams.setTextSize(spValue);//设置文字大小
/*获取dp值*/
float pxValue2 = getResources().getDimension(R.dimen.dp_360);//获取对应资源文件下的dp值
int dpValue = ConvertUtils.px2dp(this, pxValue2);//将px值转换成dp值
使用步骤总结
说了这么多,其实只需要简单的 2 步:
以设计图最小宽度(单位为 dp)作为基准值,利用插件生成所有设备对应的 dimens.xml 文件
根据设计图标注,标注多少 dp,布局中就写多少dp,格式为@dimen/dp_XX。
怎么适配其他 module?
问题:在项目的其他 module 中怎么实现适配?难道也要多套 dimens 文件?
解决:并不需要多套 dimens 文件,只需要在 values 文件夹下有一套与 app module 一样的 dimens 文件即可达到适配。因为经过编译,所有 module 中的 dimen 数据都会统一归类到主 module(即 app module)中的 values/dimens.xml 文件中了,然后系统又会根据你设置的值去找对应 values-swxxxdp 文件夹下的dimens.xml 文件中的值。
验证:在项目中建一个 module,然后随便取一个 dimens.xml 文件中的值进行打印,分别运行在不同 widthDP 的设备上(用模拟器即可)观察打印的结果发现确实是这样的。
常见问题汇总
为什么宽度适配了,高度有时候没有完全适配?
因为各种屏幕高宽比并不是固定的,有16:9、4:3,还有全面屏的19.5:9等等,如果强行将宽高都适配那只会导致布局变形。
例如一个控件的宽高为360dp和640dp,如果将它显示在宽高为360dp和640dp的设备上是正常铺满整个屏幕的,但是显示在宽高为360dp和780dp的设备上高度则不能铺满,如果你让高度铺满,而宽度又保持不变,那就会出现变形的情况。所以这也就是为什么目前市面上的屏幕适配方案只能以宽或高一个维度去适配,另一个方向用滑动或权重的方式去适配的原因。
那你为什么说高度也能适配呢?
这里说的高度也能适配指的是在不同分辨率和密度的手机上能达到等比缩放的适配,其他屏幕适配方案也是一样的。
如何同时适配横竖屏?
方案一:(不推荐)
计算出设备宽度和高度的dp值,然后生成对应的宽高 dimens.xml 文件。然后去掉所有 values-swXXXdp 目录上的s,即改为 values-wXXXdp。这样设备不管横竖屏都能找到对应的 values-wXXXdp 目录下的 dimens.xml 文件了。 虽然也能达到一定程度的适配,但是这样会增加很多 dimens.xml 文件,而且使用竖屏的设计图显示出来的效果也不够好。
方案二:(推荐)
因为横屏时宽高变化太大,想要横屏时也能完全适配,那就只能让设计师出一套横屏的设计图,然后单独写一套横屏的布局文件。
注意:smallestWidth 限定符适配的效果是让不同分辨率和密度的设备上能达到以设计图等比缩放的适配,如果设备与设计图相差太大时并不能达到很好的适配效果,需要单独出图,其他屏幕适配方案也是一样的。
如何适配平板、TV?
同横屏道理一样,平板、TV 与手机的宽高差距太大,想要平板、TV 也能完全适配,那就只能让设计师出一套平板、TV 的设计图,然后单独写一套平板、TV 的布局文件。
注意:再说一遍,smallestWidth 限定符适配的效果是让不同分辨率和密度的设备上能达到以设计图等比缩放的适配,如果设备与设计图相差太大时并不能达到很好的适配效果,需要单独出图,其他屏幕适配方案也是一样的。
作者:wildma
链接:https://www.jianshu.com/p/1302ad5a4b04
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。