所以UI适配的第一条就是:
1. 使用dp代替px来编写布局。
又因为上面无法适配的个别场景,所以UI适配的第二条是:
2.尽量使用自动适配布局,而不要指定分辨率
这一条也很好理解,尽量使用ConstraintLayout
约束布局和LinearLayout
等父布局,不要写死分辨率,比如上面的例子如果使用match_parent
而不是360dp
,也可以避免出现显示不一致问题(但是仅限于上列)。
限定符
Google同样意识到dp满足所以业务场景的需要,所以提供了宽度限定符的概念。
虽然您的布局应始终通过拉伸其视图内部和周围的空间来应对不同的屏幕尺寸,但这可能无法针对每种屏幕尺寸提供最佳用户体验。例如,您为手机设计的界面或许无法在平板电脑上提供良好的体验。因此,您的应用还应提供备用布局资源,以针对特定屏幕尺寸优化界面设计。
最小宽度限定符
使用“最小宽度”屏幕尺寸限定符,您可以为具有最小宽度(以密度无关像素 dp 或 dip 为度量单位)的屏幕提供备用布局。
通过将屏幕尺寸描述为密度无关像素的度量值,Android 允许您创建专为非常具体的屏幕尺寸而设计的布局,同时让您不必对不同的像素密度有任何担心。
通俗一点翻译就是:可用通过xxxx-swXXXdp的方式定义一些最小限定符的资源文件,比如:values-sw400dp、values-sw600dp,系统会自动匹配如屏幕宽度相近资源文件夹。
我们再来看上面的例子两台设备A和B,分辨率是1920x1080,dpi分别为360和400。我们简化下问题比如设计图给的是1920x1080 360dpi,包含一个22.5px * 22.5px = 10dp * 10dp的图片。按经验布局应该如下编写:
<ImageView
android:id="@+id/img_iv"
android:layout_width="10dp"
android:layout_height="10dp"
android:background="@mipmap/ic_launcher"/>
在不同设备上运行的结果:
- 1280 x 720 240dpi的设备,图片显示为15px * 15px;
- 1920 x1080 360dpi的A设备,图片显示为22.5px * 22.5px;
- 1920 x1080 400dpi的B设备,图片显示为25px * 25px;
可以看到B设备图片显示是有问题的,为了解决这个问题,我们使用最小宽度限定符定义两个资源文件夹:values-sw360dp和values-sw400dp。
在values-sw360dp中添加dimen.xml内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="dp_1">1dp</dimen>
<dimen name="dp_2">2dp</dimen>
<dimen name="dp_3">3dp</dimen>
<dimen name="dp_4">4dp</dimen>
<dimen name="dp_5">5dp</dimen>
<dimen name="dp_6">6dp</dimen>
<dimen name="dp_7">7dp</dimen>
<!-- 省略其他值 -->
<dimen name="dp_360">360dp</dimen>
<!-- 因为设计图是360dpi,所以控件尺寸通常不会超过360dp,定义最大360dp的值足够使用 -->
</resources>
在values-sw420dp中添加dimen.xml,文件中的dimen值很容易换算出来:在360dpi中dp_1 = 1dp,那么在400dpi中dp_1 = 360 / 400 = 0.9dp,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="dp_1">0.9dp</dimen>
<dimen name="dp_2">1.8dp</dimen>
<dimen name="dp_3">2.7dp</dimen>
<dimen name="dp_4">3.6dp</dimen>
<dimen name="dp_5">4.5dp</dimen>
<dimen name="dp_6">5.4dp</dimen>
<dimen name="dp_7">6.3dp</dimen>
<!-- 省略其他值 -->
</resources>
注意要在values文件夹下添加默认dimen.xml,文件内容与values-sw360dp中添加dimen.xml一致(因为设计图恰好是360dpi的)。
布局中的ImageView自然要改写为:
<ImageView
android:id="@+id/img_iv"
android:layout_width="@dimen/dp_10"
android:layout_height="@dimen/dp_10"
android:background="@mipmap/ic_launcher"/>
我们再来看一下不同设备运行结果:
- 1280 x 720 240dpi的设备,未匹配到限定符使用values中的dimen,
dp_10 = 10dp, px = 10 * 240 / 160 = 15px
,图片显示尺寸为15px * 15px。 - 1920 x1080 360dpi的A设备,匹配到sw360dp限定符,
dp_10 = 10dp, px = 10 * 360 / 160 = 20px
,图片显示尺寸为22.5px * 22.5px。 - 1920 x1080 400dpi的B设备,匹配到sw420dp限定符,
dp_10 = 9dp, px = 9 * 400 / 160 = 20px
,图片显示尺寸为22.5px * 22.5px。
完美的解决了设备A和B的显示问题,所以UI适配的第三条是:
3. 使用最小(可用)宽度限定符,解决同样分辨率不同dpi的设备适配问题。
这种方案看似完美,但是也有一些隐含的问题:此方案只能解决同样分辨率不同dpi设备的适配问题:
- 一旦出现不同分辨率相同dpi的情况就无效了(当然这种情况的可能性不高)。
- 以上举例只是基于1920x1080这一种分辨率为例说明,试想一下如果1280x720的设备存在240dpi和280dpi的情况呢?我们只能针对特殊情况适配处理,无法解决全部场景适配问题。
宽高限定符
类似于上面说的最小宽度限定符,但是需要精确指定要匹配的设备宽高,values-1920x1080、values-1280x720等。配置与使用方式也与上面类似,如设计图尺寸为1920x1080 360dpi,那么只需要以1920x1080为基准计算所有分辨率对应的尺寸就可以了,布局编写时按照给的尺寸一一对应就可以,比如:给出的ImageView是20px*20px的,那在布局中同样指定width和height为@dimen/dp_20
就可以了。
values-1920x1080中dimens.xml如下:
<resources>
<dimen name="dp_1">1px</dimen>
<dimen name="dp_2">2px</dimen>
<dimen name="dp_3">3px</dimen>
<dimen name="dp_4">4px</dimen>
<dimen name="dp_5">5px</dimen>
<dimen name="dp_6">6px</dimen>
<dimen name="dp_7">7px</dimen>
<dimen name="dp_8">8px</dimen>
<dimen name="dp_9">9px</dimen>
<!-- 省略其他 -->
<dimen name="dp_1920">1920px</dimen>
</resources>
values-1280x720中dimens.xml换算为:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="dp_1">0.66px</dimen>
<dimen name="dp_2">1.33px</dimen>
<dimen name="dp_3">2.0px</dimen>
<dimen name="dp_4">2.66px</dimen>
<dimen name="dp_5">3.33px</dimen>
<dimen name="dp_6">4.0px</dimen>
<dimen name="dp_7">4.66px</dimen>
<!-- 省略其他 -->
</resources>
同样需要在values添加默认尺寸dimen.xml,内容同基准分辨率文件。
如何做好面试突击,规划学习方向?
面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。
同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!