-
屏幕适配的几种方式
2019-09-06 17:13:21衍生出许许多多手机厂商,各厂商生产的手机百十种机型不算多吧,往往国人有一种习惯,就是喜欢和别人的不一样,遵循:“别人无,我有;别人有,我好;别人好,我优”的心态。 往往不按照规范走,随意修改API,这都...Andorid是开源的,开源的好处是“百家争鸣,百花齐放”,更快的打入并占有市场,弊端呢?衍生出许许多多手机厂商,各厂商生产的手机百十种机型不算多吧,往往国人有一种习惯,就是喜欢和别人的不一样,遵循:“别人无,我有;别人有,我好;别人好,我优”的心态。
往往不按照规范走,随意修改API,这都是常态;想做自己独特的东西,API任意修改,做我自己的定制,产品独特……往往只管赚钱,钱是首要的,记不清是谁说过的话,“先生产,后环保”;几十年过去了,国家、国人为了环保付出了多少努力?难道还不能反思一下自己吗?代价还不够沉重吗?
言归正传,我等千千万猴子的现状是什么?做一个功能,这个机型很好,换一种机型就成了狗屎……屏幕适配千千万,到底什么才是最好的呢?答案是:没有最好的,只有最适合自己的;遇到问题不要想着如何回避,避免的实现思路短期可以,但是往往再次碰到的时候要怎么做?也许到了不得不来面对、不得不做的时候后悔莫及吗?什么事情都心理安慰自己,以后有时间再回过头来做吧,我一定记住,随着时间积累,需要做的事情越积累越多,压得自己透不过气来,到那时候已经为时已晚了;
进入正题:什么是屏幕适配?
讲解屏幕适配之前先要了解什么是dp、sp、px的概念;
dp(dip): device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA
如果设置表示长度、高度等属性时可以使用dp 或sp。但如果设置字体,需要使用sp。
dp是与密度无关,sp除了与密度无关外,还与scale无关。如果屏幕密度为160,这时dp和sp和px是一 样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏幕密度变成了320。那么原来TextView的宽度设成160px,在密度为320的3.2寸屏幕里看要比在密度为160的3.2寸屏幕上看短了一半。但如果设置成160dp或160sp的话。系统会自动将width属性值设置成320px的。也就是160 * 320 / 160。其中320 /160可称为密度比例因子。也就是说,如果使用dp和sp,系统会根据屏幕密度的变化自动进行转换。
px: pixels(像素). 不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多。
pt: point,是一个标准的长度单位,1pt=1/72英寸,用于印刷业,非常简单易用;
sp: scaled pixels(放大像素). 主要用于字体显示best for textsize。
当然了,dip虽然可以在某种程度上帮助我们去更好的适应不同密度的屏幕,但他也并不是万能的;
一个尺寸标注为N dp的物体,它在不同屏幕上的实际物理尺寸(单位inch)为多少呢?
计算公式如下:
physical_size=N*(dpi/160)*(1/dpi)=N/160
dpi代表了这个屏幕的密度,我们得到一个结论:
用dp标注的物品,他在不同屏幕上的实际物理尺寸理论上将保持不变;
只有dp就足够了吗?NO,NO,NO,
布局适配
布局要如何适配呢?大概可以通过以下几种思路来实现
应杜绝使用绝对布局,使用绝对布局硬编的后果是,这一款或几款手机差不多可以,换其他手机来测试,会发现,这是我写的吗?什么鬼?Google提供的相对布局不可说不好,支持拖拽,画界面快,开发效率高,一脱成名,但是后期修改,维护成本有点高,原因不再累赘,所以这里也不再做相关介绍;
1.初期参考使用权重来动态比例展示,LinearLayout的weight属性来进行权重设置,进而达到按比例显示布局的意图:
不再相互规定,让各个view自己去做处理,在不同的屏幕上相互间距都是一样的(最起码看上去,哈),
需要注意一点:weight是float类型
2.view背景(button、textview等)尽可能少使用图片来做操作,多实用shape和seleter控制,效率高,错误率低,好控制;
3.分块控制,杜绝所有的东西一笼统的在一个布局文件里面,找的困难,错误率大大提升,所以建议使用标签来控制<include>、<merge>、<viewstub>???,了解一下
图片资源适配
往往项目里面需要使用大量图片,来显得华丽一点,给人眼前一亮的感觉,资源图片Google也做了适配,不同的分辨率会先去加载最适应自己分辨率的资源,如果没有就去找最邻近的资源图片,直到找到为止;所以一些需要做适配的图片资源应该让UI出5套(hdpi、mdpi、xhdpi、xxhdpi、xxxhdpi),一些icon看情况来做适配,影响甚微;
-
android 屏幕适配的几种方式
2019-03-07 11:57:19简单介绍屏幕适配(三种常用方案)- 1、像素(px): 含义:通常所说的像素,就是CCD/CMOS上光电感应元件的数量,一个感光元件经过感光,光电信号转换,A/D转换等步骤以后,在输出的照片上就形成一个点,我们如果...简单介绍屏幕适配(三种常用方案)-
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 36*36
中密度(mdpi) 320x480 160 1dp=1px 4 48*48
高密度(hdpi) 480x800 240 1dp=1.5px 6 72*72
超高密度(xhdpi) 720x1280 320 1dp=2px 8 96*96
超超高密度(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
<meta-data android:name="design_width" android:value="768">
</meta-data>
<meta-data android:name="design_height" android:value="1280">
</meta-data>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,我可以怎么编写布局文件呢?
<FrameLayout >
<Button
android:layout_gravity="center"
android:gravity="center"
android:text="@string/hello_world"
android:layout_width="@dimen/x160"
android:layout_height="@dimen/x160"/></FrameLayout>
三 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,在布局中则这样使用:
<Button android:layout_width="@dimen/dp_360" android:layout_height="@dimen/dp_50" android:textSize="@dimen/sp_15"/>
- 代码中动态设置 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
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。 -
-
iOS屏幕适配的几种方式
2016-07-23 23:48:43在iOS开发中,会经常碰到屏幕适配的问题,下面来说一下自己在项目开发中遇到的几种屏幕适配的方式. 第一种: 利用宽高比,在不同的屏幕中来进行对控件的位置与控件的宽高进行等比例缩放.选定一个型号的屏幕的宽高为...在iOS开发中,会经常碰到屏幕适配的问题,下面来说一下自己在项目开发中遇到的几种屏幕适配的方式.
第一种:
利用宽高比,在不同的屏幕中来进行对控件的位置与控件的宽高进行等比例缩放.选定一个型号的屏幕的宽高为基准,进行等比例缩放.例如以iPhone6或者iPhone6s为基准.
其宽高分别是375与667.Iphone6ScaleWidth = [UIScreen mainScreen].bounds.size.width/375; Iphone6ScaleHeight = [UIScreen mainScreen].bounds.size.height/667;
如果是iPhone6或者iPhone6s则Iphone6ScaleWidth与Iphone6ScaleHeight的值都为1.但是此方法对于iPhone5之后的型号可以适用.因为我们知道iPhone4或者iPhone4s尺寸是320x480.iPhone5是320x568.所以对于4或者4s来说计算得到的宽高比不相同.可能会造成一个方形控件,在iPhone5之后的机型上显示的都是正方形.但是在4或者4s上显示的是长方形.需要进行自己的判断(目前来说4或者4s市场上已经不多见了).
同时也可以在代理增加两个属性,宽高比例属性,例如:
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property float autoSizeScaleX;
@property float autoSizeScaleY;在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if(CurrentScreenHeight > 480){
nowAppDelegate().autoSizeScaleX = CurrentScreenWidth/320.0;
nowAppDelegate().autoSizeScaleY = CurrentScreenHeight/568.0;
}else{
nowAppDelegate().autoSizeScaleX = 1.0;其中nowAppDelegate() = (AppDelegate *)[[UIApplication sharedApplication] delegate];
nowAppDelegate().autoSizeScaleY = 1.0;
}}
在项目对于控件的位置和尺寸乘以这两个缩放比例.
第二种:
使用autoLayout进行屏幕适配.代码如下:
UIView *headView = [[UIView alloc] init]; headView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:headView]; headView.backgroundColor = [UIColor redColor]; NSLayoutConstraint *headViewLeft = [NSLayoutConstraint constraintWithItem:headView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]; NSLayoutConstraint *headViewTop = [NSLayoutConstraint constraintWithItem:headView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; NSLayoutConstraint *headViewRight = [NSLayoutConstraint constraintWithItem:headView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]; NSLayoutConstraint *headViewHeight = [NSLayoutConstraint constraintWithItem:headView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0 constant:200]; self.headHeightCons = headViewHeight; [self.view addConstraints:@[headViewTop,headViewLeft,headViewRight]]; [headView addConstraint:headViewHeight]; UIImage *imageLol = [UIImage imageNamed:@"lol"]; UIImageView *imageViewLol = [[UIImageView alloc] initWithImage:imageLol]; [headView addSubview:imageViewLol]; imageViewLol.translatesAutoresizingMaskIntoConstraints = NO; [imageViewLol setContentMode:UIViewContentModeScaleAspectFill]; NSLayoutConstraint *imageLolViewLeft = [NSLayoutConstraint constraintWithItem:imageViewLol attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:headView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]; NSLayoutConstraint *imageViewLolViewTop = [NSLayoutConstraint constraintWithItem:imageViewLol attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:headView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; NSLayoutConstraint *imageViewLolViewRight = [NSLayoutConstraint constraintWithItem:imageViewLol attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:headView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]; NSLayoutConstraint *imageViewLolViewBottom = [NSLayoutConstraint constraintWithItem:imageViewLol attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:headView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; [headView addConstraints:@[imageLolViewLeft,imageViewLolViewTop,imageViewLolViewRight,imageViewLolViewBottom]];
第三种:使用框架Masonry进行屏幕适配.读者可以自己找到框架或者demo看下,在这里就不多说了. -
Android 适配的几种方式
2019-07-04 10:36:14一般来说,常见的屏幕适配方式有以下几种: 1)布局适配 -避免写死控件,采用wrap_content,match_parent -LinearLayout权重 -RelativeLayout -ContrainLayout 约束布局 -Percent-support-lib ...由于Android的碎片化,导致app的界面元素在不同屏幕尺寸上显示不一致,所以Android的适配问题一直都比较让人蛋疼。一般来说,常见的屏幕适配方式有以下几种:
1)布局适配
-避免写死控件,采用wrap_content,match_parent
-LinearLayout权重
-RelativeLayout
-ContrainLayout 约束布局
-Percent-support-lib xxx:layout_widthPercent=“30%” 百分比布局2)图片资源适配
-.9图或者SVG图
-备用位图匹配不同分辨率3)用户流程适配
-根据业务逻辑执行不同的跳转逻辑
-根据别名展示不同的界面4)限定符适配
-分辨率限定符 drawable-hdp,drawable-xdpi
-尺寸限定符 layout-small,layout-large
-最小宽度限定符 values-sw360dp
-屏幕方向限定符 layout-land,layout-port5)刘海屏适配
-9.0官方适配
-华为、VIVO等适配文档下面我们来看几个适配方案:
一、自定义像素适配
何为自定义像素适配,美工在切图时,是以某屏幕尺寸为基准来操作的,如7201280,那么我们就以该尺寸为基准,获取当前手机的宽高值,计算出与基准值的缩放比,再通过自定义布局容器,遍历子View,给每一个子View重新赋值宽高以及margin值,从而达到适配的目的。
看一下效果图
再来看一下布局文件
这里用的是7201280的模拟器,标准尺寸是480960,在xml布局文件中,TextView的宽高均设为了标准尺寸的一半,我们发现在7201280的设备中也是占用了宽高的一半,这里有个地方需要注意,TextView的宽高单位必须是px,这是因为在Android系统内部,会将单位如dp,dip等都转换为px,详见TypedValue类
计算缩放比例的代码private static final int WIDTH = 480; private static final int HEIGHT = 960; private static float targetWidth; private static float targetHeight; private static UiUtils mInstance; public static float stateBarHeight; public static UiUtils getInstance(Context context) { synchronized (UiUtils.class) { if (mInstance == null) { mInstance = new UiUtils(context.getApplicationContext()); } return mInstance; } } private UiUtils(Context context) { WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics metrics = context.getResources().getDisplayMetrics(); manager.getDefaultDisplay().getMetrics(metrics); if (targetWidth == 0 || targetHeight == 0) { stateBarHeight = getSystemBarHeight(context); //横屏 if (metrics.widthPixels > metrics.heightPixels) { targetWidth = (float) metrics.heightPixels; targetHeight = (float) (metrics.widthPixels - stateBarHeight); } else { //竖屏 targetWidth = (float) metrics.widthPixels; targetHeight = (float) (metrics.heightPixels - stateBarHeight); } } } //获取横向缩放值 public float getHorizontalScaleValue() { return ((float) (targetWidth)) / WIDTH; } //获取纵向缩放值 public float getVerticalScaleValue() { return ((float) (targetHeight)) / (HEIGHT - stateBarHeight); } /** * 用于得到状态框的高度 */ public int getSystemBarHeight(Context context) { int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); int height = context.getResources().getDimensionPixelSize(resourceId); if (height != -1) { return height; } return getValue(context, "com.android.internal.R$dimen", "system_bar_height", 48); } private int getValue(Context context, String dimeClass, String system_bar_height, int defaultValue) { try { Class<?> clz = Class.forName(dimeClass); Object object = clz.newInstance(); Field field = clz.getField(system_bar_height); int id = Integer.parseInt(field.get(object).toString()); return context.getResources().getDimensionPixelSize(id); } catch (Exception e) { e.printStackTrace(); } return defaultValue; }
自定义布局容器,这里的isScale对象是为了防止多次计算宽高值
在xml布局中引用该View即可。二、百分比布局适配
说到百分比布局适配,相信大家对percentLayout应该不陌生,percentLayout是继承于RelativeLayout,结合定义的style,给子View重新设置宽高值,从而达到适配效果。下面我们来看一下如何来实现百分比布局适配。
首先,先看一下源码中是如何将view添加到屏幕上的,进入activity的setContentView方法,发现其最终调用了PhoneWindow类的setContentView方法,在该方法中有这样一段代码mLayoutInflater.inflate(layoutResID, mContentParent);
最终进入了LayoutInflater的inflate方法
在该方法中,主要是初始化LayoutParams对象public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(getContext(), attrs); }
public LayoutParams(Context c, AttributeSet attrs) { TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout); setBaseAttributes(a, R.styleable.ViewGroup_Layout_layout_width, R.styleable.ViewGroup_Layout_layout_height); a.recycle(); }
在generateLayoutParams方法中,通过创建LayoutParams对象,可以获取到自定义style属性,在percentLayout中需要重写generateLayoutParams方法,并构建自己的LayoutParams。
在onMeasure中,判定子View的LayoutParams是否为我们自定义的LayoutParams@Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { return p instanceof LayoutParams; }
然后为子View重新设置宽高值即可
效果图,宽度占了0.3,高度占了0.5
xml布局文件<?xml version="1.0" encoding="utf-8"?> <com.android.jcj.demoanimui.netease.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/colorAccent" app:heightPercent="0.5" app:widthPercent="0.3" /> </com.android.jcj.demoanimui.netease.PercentRelativeLayout>
自定义属性:
三、修改系统density,scaleDensity,densityDpi
density:指屏幕密度,一般来说,屏幕上每一寸有160个像素点,如果某屏幕每一寸有320个像素点,那么density值就为2
scaleDensity:指字体缩放比例,一般情况下与density值相同
densityDpi:指每一寸屏幕有多少像素点,如上述160、320等。
该适配方式是以某宽度为基准,通过获取手机的宽度值计算出两者之间的比值,即目标density值,再计算出目标scaleDensity以及densityDpi,将计算的值重新赋值给系统即可
这里有一个监听器registerComponentCallbacks,用来监听系统的字体变化,如用户在设置中调整了字体大小,那么在app中也要做相应调整。
该方法需要在setContentView之前来调用,也可以配合Application来使用
效果图,设备是720*1280,发现宽度占用了一半。
xml布局文件
这里我们设置了160dp,正好是基准WIDTH(320)的一半。四、刘海屏适配
在Google官方9.0提供的关于刘海屏的适配策略是这样的:
1)如果非全屏模式(有状态栏)下,app不受刘海屏的影响,刘海屏的高度就是状态栏的高度
2)全屏模式下,如果app未对刘海屏适配,系统会对界面做特殊处理,即竖屏内容向下移动,横屏内容向右移动这里我们以常见的刘海屏为主——仅上方中间区域有刘海
在9.0的api中,刘海屏有三种模式:
1)WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
默认状态下的模式,表示在全屏模式下内容区下移
2)WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
全屏模式下,允许内容区域延伸进刘海区域
3)WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
不允许内容区域延伸进刘海区域
xml布局文件
了解三种模式后,对刘海屏的适配主要是针对第二种模式LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES,它允许内容延伸进刘海区。在该模式下,我们需要将app设置为沉浸式即可
//设置沉浸式 int flag = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; int visibility = window.getDecorView().getSystemUiVisibility(); visibility |= flag;//追加沉浸式设置 window.getDecorView().setSystemUiVisibility(visibility);
如果出现下面这种情况,我们需要对控件重新计算相应的边界值
xml布局文件Button btn = findViewById(R.id.button); RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) btn.getLayoutParams(); lp.setMargins(lp.leftMargin, lp.topMargin + UiUtils.getInstance(this).getSystemBarHeight(this), lp.rightMargin, lp.bottomMargin); btn.setLayoutParams(lp);
UiUtils.getInstance(this).getSystemBarHeight(this) 是获取状态栏的高度
由于刘海屏是在9.0中出现的,所以我们需要知道当前设备是否有刘海屏
在其他手机厂商,如华为,VIVO,OPPO,小米,各自提供了相应的刘海屏适配策略及api,这里不一一表述。
华为:https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114
小米:https://dev.mi.com/console/doc/detail?pId=1293
Oppo:https://open.oppomobile.com/service/message/detail?id=61876
Vivo:https://dev.vivo.com.cn/documentCenter/doc/103Android的适配暂告一段落,上述提供的几种方式依照实际情况来使用。
-
学习一种极低成本的Android屏幕适配方式
2018-08-15 18:21:26学习一种极低成本的Android屏幕适配方式 学习今日头条技术团队–&amp;gt;一种极低成本的Android屏幕适配方式 文章中刚开的的计算供着几个参数就没弄懂,搜了2遍不错的文章 两分钟理解Android中PX、DP... -
Android 屏幕适配常用方法
2017-05-17 16:31:39Android 中屏幕适配的几种方式 -
使用vw进行移动端的适配_移动端适配的几种实现方式
2021-01-17 19:19:09rem布局用js获取视窗宽度,然后设置html的font-size为视窗宽度的十分之一...flex布局类似于百分比布局,无需计算百分比,可以很好的适配所有屏幕。手机天猫 典型的flex布局,flex做了很好的兼容处理,高度写死,可查... -
手机屏幕适配
2015-06-20 17:00:49屏幕适配的几种方式: 1 图片适配---在res/drawable文件夹下。注意事项:如果当前需要加载的分辨率图片没有 那么就王高密度加载。 2 dimens--values/dimens文件夹下--计算像素密度。 3 layout--res/layout针对性... -
移动端页面像素值的适配问题的几种处理方式
2019-11-15 15:13:00移动端页面像素值适配问题的几种处理方式 移动端机型巨多,各种屏幕分辨率,眼花缭乱!作为前端开发,样式的适配性也显得非常重要!那么。今天,就说说我在之前h5开发过程中,对于像素值的适配问题的几种解决方法 .... -
骚年你的屏幕适配方式该升级了!-今日头条适配方案
2018-10-12 16:30:40前言 这个月在 Android 技术圈中 屏幕适配 这个词曝光率挺高的,为什么这么说呢?...上个星期 拉丁吴 老师在 鸿神 的公众号上发布了一篇 文章,详细描述了市面上主流的几种屏幕适配方案,并发布了他的... -
android屏幕适配计算方式及适配values文件生成
2017-11-26 02:33:59随着时代的发展,我们的手机的分辨率越来越高,并且伴随着的尺寸也越来越多,对于android程序开发的我们,大多数android手机屏幕适配也成为了一个问题,因为不像以前只有几种规定尺寸及分辨率的手机了所以这个问题... -
获取屏幕分辨率_教大家如何自动适配电脑不同尺寸的屏幕,这几种方法就足够...
2021-01-12 07:32:34这一期教大家如何对不通的分辨率...接下来大家大家介绍几种方式如何自适应加载文件的方式,绝对的干货,喜欢的可以关注哈!接下来直接上代码演示1,根据js判断屏幕大小分辨率来自动加载对应的css文件我们首先定义一... -
Android的屏幕适配
2016-09-07 22:17:12Android的屏幕适配主要有以下几种: 1.适配方式之 dp 控件尺寸尽量使用dp,文字尺寸尽量使用sp。 在我们的 Android 工程res目录中有 drawable-*dpi(mipmap) 目录, 这些目录是用来适配不同分辨率手机的。 ... -
安卓屏幕适配
2016-08-20 09:44:35Configuration 适配各种屏幕规格,首先要取到系统对于屏幕的配置信息,这些配置可从工具类Configuration获得。Configuration对象在Activity中通过调用...有下列几种取值定义:"未定义", "不支持触摸", "专用笔触摸 -
android屏幕适配
2018-05-21 10:24:39一般有以下几种适配方案:1.布局适配2.权重适配权重的计算方式:自身宽度+占剩余空间的比例 TextView1 0dp 1 1/3L=0dp+(L-(0+0))*1/3 TextView2 0dp 2 2/3L=0dp+(L-(0+0))*2/3 TextView1 L 1 1/3L=L+(L-... -
Android下屏幕适配
2016-05-12 22:36:34适配:即当前应用在相同的手机上面显示相同的效果...在android中,屏幕视频主要有以下几种方式: 图片适配 dimens适配 布局文件适配 java代码适配 权重适配 案例一:手机型号:G700 手机分辨率:1280*720 (注:手 -
移动端的几种适配方案
2019-08-16 15:20:39媒体查询的方式可以说是早期采用的布局方式, 它主要是通过查询设备的宽度来执行不同的css代码,最终达到界面的配置 2.媒体查询优势 简单, 哪里不对改哪里 调整屏幕宽度的时候不用刷新页面即可响应式展示 特别适合对... -
UIKit框架(8)屏幕适配(一)
2016-02-29 13:06:58本篇本章介绍iOS开发中经常使用的几种屏幕适配方式,包括:通过frame进行适配通过AutoResizing进行适配使用AutoLayout进行适配 使用ZXPAutoLayout进行适配...这里面最重要的是:通过frame适配以及AutoLayout屏幕适配... -
Android屏幕适配(二)多分辨率布局适配策略
2016-05-13 11:33:38Android布局的适配方法有很多种,不过每一种方法的思路无非就是让不同分辨率的手机去读各自的适配文件,我主要总结有下面几种方式: 1、每个分辨率下面一套layout,比如layout-480x800,layout-1280x720,1080x1080等... -
web前端开发之 -移动端屏幕的适配总结
2019-10-14 17:47:35在前端开发中,适配移动端我们主要有以下几种方式: 流式布局:百分比布局实现在移动端的宽高自适应 响应式布局:css3中媒体查询 REM(弹性)布局:实现盒子的宽高自适应 流式布局 流式布局在css2时代就有,主要是靠... -
网页布局的几种方式
2019-03-06 11:18:00固定布局 为网页设置一个固定的宽度,通常以px做为长度单位,常见于PC端网页。 这种布局具有很强的稳定性与可控性,... 为网页设置一个相对的宽度,页面元素的大小按照屏幕分辨率进行适配调整,但整体布局不... -
values在碎片化各种屏幕中的系统加载策略问题探讨及ui适配的选择
2018-05-07 10:58:21values在碎片化各种屏幕中的系统加载策略问题探讨及ui适配的选择android寻找资源策略values 两种系统识别...适配优先宽度,宽高适配几种方式系统加载策略的探索项目中使用到了多个values来进行适配的问题,想从... -
android 屏幕适配 详解——其实你并不需要这么麻烦
2019-01-02 16:51:10bd“android屏幕适配”会发现全是类似于增加文件夹values-1080x1920文件夹并为每一个px(dp)都写进去的方式,个人是非常鄙视这种方式的(不喜欢的可以关闭了)。 首先千篇一律:没有任何新鲜感。 2.冗余较大:... -
Android中实现截图的几种方式
2017-03-08 15:45:11最近项目需求中需要实现屏幕截图,开启了新一轮的翻腾,找寻。是的,我就是一个搬运工,简单的搬运工~~做不完的功能,连接不断地需求~~ 基本需求:实现当前页面截图并保存; 扩展需求:截图去除自己添加的控件... -
Android开发笔记(八十一)屏幕规格适配
2016-03-16 14:25:50Configuration 适配各种屏幕规格,首先要取到系统对于屏幕的配置信息,这些配置可从工具类Configuration获得。Configuration对象在Activity中通过调用...有下列几种取值定义:"未定义", "不支持触摸", "专用笔触摸 -
iPhone 检测 iPhone X 设备的几种方式和分辨率终极指南
2018-09-21 08:50:00检测设备是否为 iPhone X/XS/XR 的几种方式 iPhone 屏幕分辨率终极指南 上周,苹果发布了三款新的 iPhone 设备,它们的屏幕数据分别如下: iPhone XS: 5.8 英寸,375pt * 812pt (@3x); iPhone XR: 6.1... -
cocos2d-x IOS适配 一种不改变你图片品质的适配原理
2013-08-30 15:04:14首先,我想说的是,cocos2d-x有自己的几种自适配方式,网上有很多资料,我就不多说了!也许你也遇到过跟我一样的适配麻烦,老板、策划并不满意cocos2d-x自带的适配原则,因为它往往要改变你的图片质量!现在,我想把... -
cocos2d-x IOS适配 一种不改变你图片品质的适配原理(美女程序员的文章)
2013-12-10 12:17:02首先,我想说的是,cocos2d-x有自己的几种自适配方式,网上有很多资料,我就不多说了!也许你也遇到过跟我一样的适配麻烦,老板、策划并不满意cocos2d-x自带的适配原则,因为它往往要改变你的图片质量!现在,我想把...
-
cookie
-
android底层开发!不断提升自己创造溢价的能力,附面试题答案
-
小波熵阈值的心电信号去噪及 R 波检测算法
-
blackedge:Tienda在线“ BlackEdge”商店-源码
-
华为1+X——网络系统建设与运维(中级)
-
爬虫日记(1):为什么需要爬虫
-
代码块
-
Amoeba 实现 MySQL 高可用、负载均衡和读写分离
-
新型电力线载波通信算法
-
Redis Cluster
-
盘点:你可能不知道的Linux下开源云平台
-
NFS 实现高可用(DRBD + heartbeat)
-
离心泵轴承的技术改造.rar
-
Android在java代码中修改颜色
-
云开发后台+微信扫码点餐小程序+cms网页管理后台 含后厨端和用户端
-
MySQL 高可用工具 heartbeat 实战部署详解
-
关于射线检测的一些方法
-
python Flask+scrapy+人工智能 实现高性能搜索引擎
-
uni-app 配置 地图
-
法国VOC标签:环保认证A+