字节跳动被问Android屏幕适配方案,这个回答让我错失offer!

本文详细解释了Android屏幕适配中的dp、dpi概念,介绍了屏幕分辨率限定符和smallestWidth限定符的适配原理,比较了两者选择的原因,包括文件管理、适配效率和单位使用,以及如何通过设计图最小宽度进行适配和使用ScreenMatch插件生成dimens.xml文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于为什么要进行屏幕适配,什么是 dp、dpi 这些概念我就不去一一讲解了,网上很多文章。这里我推荐几篇讲的比较好的:

二、屏幕分辨率限定符与 smallestWidth 限定符适配原理

2.1 屏幕分辨率限定符适配原理

屏幕分辨率限定符适配需要在 res 文件夹下创建各种屏幕分辨率对应的 values-xxx 文件夹,如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后根据一个基准分辨率,例如基准分辨率为 1280x720,将宽度分成 720 份,取值为 1px~720px,将高度分成 1280 份,取值为 1px~1280px,生成各种分辨率对应的 dimens.xml 文件。如下分别为分辨率 1280x720 与 1920x1080 所对应的横向 dimens.xml 文件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

假设设计图上的一个控件的宽度为 720px,那么布局中就写 android:layout_width=“@dimen/x720” ,当运行程序的时候,系统会根据设备的分辨率去寻找对应的 dimens.xml 文件。例如运行在分辨率为 1280x720 的设备上,系统会自动找到对应的 values-1280x720 文件夹下的 lay_x.xml 文件,由上图可知 x720 对应的值为
720.px,可铺满该屏幕宽度。运行在分辨率为 1920x1080 的设备上,系统会自动找到对应的 values-1920x1080 文件夹下的 lay_x.xml 文件,由上图可知 x720 对应的值为 1080.0px,可铺满该屏幕宽度。这样就达到了屏幕适配的要求!

2.2 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 = ScreenUtils.getScreenHeight(this);
int widthPixels = ScreenUtils.getScreenWidth(this);
float density = dm.density;
float heightDP = heightPixels / density;
float widthDP = widthPixels / density;
float smallestWidthDP;
if(widthDP < heightDP) {
smallestWidthDP = widthDP;
}else {
smallestWidthDP = heightDP;
}

ScreenUtils——>ScreenUtils

三、为什么选择 smallestWidth 限定符适配?

既然原理都一样,都需要多套 dimens.xml 文件,那为什么要选择 smallestWidth 限定符适配呢?

  1. 屏幕分辨率限定符适配是根据屏幕分辨率的,Android 设备分辨率一大堆,而且还要考虑虚拟键盘,这样就需要大量的 dimens.xml 文件。因为无论手机屏幕的像素多少,密度多少,90% 的手机的最小宽度都为 360dp,所以采用 smallestWidth 限定符适配只需要少量 dimens.xml 文件即可。
  2. 屏幕分辨率限定符适配采用的是 px 单位,而 smallestWidth 限定符适配采用的单位是 dp 和 sp,dp 和 sp 是 google 推荐使用的计量单位。又由于很多应用要求字体大小随系统改变,所以字体单位使用 sp 也更灵活。
  3. 屏幕分辨率限定符适配需要设备分辨率与 values-xx 文件夹完全匹配才能达到适配,而 smallestWidth 限定符适配寻找 dimens.xml 文件的原理是从大往小找,例如设备的最小宽度为 360dp,就会先去找 values-360dp,发现没有则会向下找 values-320dp,如果还是没有才找默认的 values 下的 demens.xml 文件,所以即使没有完全匹配也能达到不错的适配效果。

四、使用步骤

4.1 获取设计图最小宽度(单位为 dp)

大多数 UI 设计师提供的设计图无非就几种,它们对应的获取方式如下:

  • 蓝湖:开发平台切换到 Android,设计图宽度即为最小宽度。
  • psd 源文件:用像素大厨查看,设计图宽度即为最小宽度。(注意像素大厨需要选择与设计图对应的 dpi 进行显示)
  • dp 单位的设计图:设计图宽度即为最小宽度。
  • px 单位的设计图:问 UI 设计师是几倍图,然后最小宽度 = 设计图宽度/倍数。

4.2 以设计图最小宽度作为基准值,生成所有设备对应的 dimens.xml 文件

这些文件当然不会手动去写,网上已经有大神提供了自动生成这些文件的插件 ScreenMatch。但是这个插件还是有点问题的:

  • 默认没有适配最小宽度为 320dp 的设备。其实自己测试还是有很多设备最小宽度是 320dp 的,所以需要加上。
  • 最小宽度为 392.7272 与 411.4285 的手机不能达到完全适配。原因是该插件的默认值都是取整的,即 392.7272 与 411.4285 在插件中写的是 392 与 411。

基于以上问题,我在该插件的源码上优化生成了新的插件 ScreenMatch,由于插件库已经有原作者的插件了,所以我就不重复造轮子上传到插件库了,你直接用本地安装的方式安装即可。

工具使用步骤:

  1. 在 Android Studio 中安装 ScreenMatch 插件
    下载插件 ScreenMatch 到本地,点击菜单栏上的 File -> Settings -> Plugins -> Install plugin from disk,然后选择我们刚刚下载的插件,最后点击 “OK”,重启 Andorid Studio 即可。如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 在项目的默认 values 文件夹中需要一份 dimens.xml 文件
    我在 github 源码已经提供了一份,直接复制过来即可。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 执行生成
    插件安装好后,在项目的任意目录或文件上右键,选择 ScreenMatch 选项。如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后选择在哪个 module 下执行适配。即基于哪个 module 下的 res/values/dimens.xml 文件作为基准 dimens.xml 文件,生成的其他尺寸 dimens.xml 文件放在哪个 module 下。例如选择 app,然后点击 OK ,出现如下界面表示生成文件成功。如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后再看看 res 目录下会自动生成一堆 dimens.xml 文件,如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过上面的步骤就已经生成了所有设备对应的 dimens.xml 文件。

  1. 根据设计图填写最小宽度基准值,并填写需要适配的设备最小宽度 dp 值

步骤 3 是以插件默认的最小宽度基准值为 360dp,适配的设备最小宽度为
320,360,384,392.7272,400,410,411.4285,432,480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365(包含了平板和 TV )生成的文件,但实际情况要根据设计图和需求设置。

例如设计图的最小宽度为 375dp,则需要更改最小宽度基准值为 375dp。如果项目只需要适配手机的话,适配的设备最小宽度保留 320,360,384,392.7272,400,410,411.4285,432,480 即可,若发现手机还有其他最小宽度自行加上即可,也麻烦把该最小宽度提供给我,我们一起来完善该份适配。

以上修改需要在配置文件里修改,即 screenMatch.properties 文件,该配置文件是执行完上面第 3 步后自动生成在项目的跟目录下的。如下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

打开配置文件,修改下图中 1、3、4 的值即可。(图中单位均为 dp)
1:最小宽度基准值,填写设计图的最小宽度值即可。
2:插件默认适配的最小宽度值,即默认情况下会生成如下值的 dimens.xml 文件。
3:需要适配的最小宽度值(如果是小数,则保留 4 位小数。例如 392.727272…,则取 392.7272),即你想生成哪些 dimens.xml 文件。
4:忽略不需要适配的最小宽度值,即忽略掉插件默认生成的 dimens.xml 文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配置文件修改完成后,重新执行第 3 步,生成新的 dimens.xml 文件。

当然!如果你的设计图也是标准的 360dp,那么上面的步骤你可以忽略。直接复制我 github 上你需要的 dimens.xml 文件到你的项目即可,默认的 values 文件夹下也需要一份

4.3 根据设计图标注,在布局写上对应的值。

设计图标注多少 dp,布局中就写多少 dp ,非常方便!

大多数 UI 设计师提供的设计图无非就几种,它们对应的使用方式如下:

  • 上传到蓝湖:显示多少 dp 就写多少 dp。

  • psd 源文件:用像素大厨查看,显示多少 dp 就写多少 dp(注意像素大厨需要选择与设计图对应的 dpi 进行显示)

  • dp 单位的设计图:标注多少 dp 就写多少 dp。

  • px 单位的设计图:问 UI 设计师是几倍图,然后控件的宽度 = 设计图中控件标注的宽度/倍数(高度同理)。

  • 举例:例如设计图上一个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值

4.4 使用步骤总结

说了这么多,其实只需要简单的 2 步:

  1. 以设计图最小宽度(单位为 dp)作为基准值,利用插件生成所有设备对应的 dimens.xml 文件
  2. 根据设计图标注,标注多少 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 文件中的值。
    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

答应大伙的备战金三银四,大厂面试真题来啦!

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析**

[外链图片转存中…(img-xlpELUjS-1712398766863)]

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
<think>我们正在讨论智能家居项目,用户之前询了关于树莓派扩展GPIO的方案(推荐了MCP23017)。现在用户的新题是关于循迹传感器在智能家居中的用途和应用方式。 注意:用户引用了[1]是一篇关于基于STM32和OneNet的智能家居安防系统的论文,但用户特别说明该引用仅供参考,不是真正的需求。因此我们应该聚焦于用户上一次的题(树莓派项目)和本次关于循迹传感器的具体题。 循迹传感器(也称为线跟踪传感器或红外循迹传感器)通常用于机器人或小车中,通过检测地面上的线(通常是黑色与白色背景的对比)来导航。但在智能家居中,它的应用可能不那么直接。我们需要思考它在智能家居中的可能用途。 可能的智能家居应用: 1. 安防监控:在特定区域(如门口、走廊)布置循迹传感器,检测是否有物体(人或宠物)经过。但通常人体红外传感器(PIR)更常用。 2. 智能清洁机器人:智能家居中的扫地机器人会使用循迹传感器来规划清洁路径,避免重复清洁和遗漏区域。 3. 物品定位:例如,在智能衣柜中,循迹传感器可以跟踪衣架的位置(如果衣架上贴有反光条或黑色标记)。 4. 智能窗帘:循迹传感器可以检测窗帘的位置,确保窗帘在打开或关闭时移动到正确的位置(通过检测轨道上的标记)。 但是,循迹传感器在智能家居中并不是主流传感器,因为它的应用场景有限。我们更常见的是使用PIR传感器、超声波传感器、光敏传感器等。 对于用户(大一学生,能力不是很强)来说,循迹传感器可能并不是智能家居项目中最容易成功的部分。如果用户想要使用,我们可以给出一些简单的应用思路和连接方法。 使用方法(在树莓派上): 1. 硬件连接:循迹传感器通常有3个引脚(VCC, GND, OUT)。将VCC接3.3V,GND接GND,OUT接树莓派的GPIO(或通过MCP23017扩展的GPIO)。 2. 读取数据:循迹传感器输出数字信号(检测到黑线为高电平或低电平,取决于传感器类型),我们可以通过读取GPIO的状态来判断。 示例代码(使用树莓派GPIO): ```python import RPi.GPIO as GPIO import time TRACK_PIN = 18 # 假设连接到树莓派的GPIO18 GPIO.setmode(GPIO.BCM) GPIO.setup(TRACK_PIN, GPIO.IN) try: while True: if GPIO.input(TRACK_PIN) == GPIO.LOW: # 假设低电平表示检测到黑线 print("检测到黑线") else: print("未检测到黑线") time.sleep(0.1) except KeyboardInterrupt: GPIO.cleanup() ``` 但是,在智能家居中如何应用?我们可以设计一个简单的应用:在门口的地毯下放置循迹传感器(黑色胶带),当有人踩过时,传感器检测到黑线(或离开黑线),从而触发开门或开灯等操作。但注意,循迹传感器需要裸露的检测面(通常朝下),所以安装位置需要设计。 然而,考虑到循迹传感器的局限性(需要特定颜色的标记,且安装位置受限),在智能家居中可能不如其他传感器方便。因此,我们也可以建议用户考虑其他更合适的传感器。 总结:循迹传感器在智能家居中应用较少,但可以用于一些特定场景(如清洁机器人、特定位置检测)。对于大一学生的简单项目,可以考虑用它来触发一些简单的动作(如检测到有人经过门口时开灯),但需要合理设计安装方式。 相关题: 1. 循迹传感器在智能家居中有哪些创新的应用方式? 2. 如何将循迹传感器与树莓派扩展板(如MCP23017)连接? 3. 在智能家居项目中,循迹传感器与人体红外传感器(PIR)相比有哪些优缺点?</think>### 循迹传感器在智能家居中的应用解析 #### 一、核心作用 循迹传感器(红外反射传感器)在智能家居中主要用于**位置检测与路径识别**,通过红外发射-接收原理检测物体位置或移动轨迹。主要应用场景包括: 1. **智能安防监控** - 在门窗轨道安装传感器,检测异常开启(如窗户被推开时遮挡红外路径)[^1] - 阈值触发报警:当检测到连续遮挡超过设定时间 $$ t > t_{threshold} $$ 时发送警报 2. **家电自动化控制** - 智能窗帘:检测窗帘移动终点位置(轨道末端贴反光条) - 扫地机器人:识别清洁区域边界(地面贴黑色引导胶带) ```python # 树莓派伪代码示例 if track_sensor.read() == LOW: # 检测到反光条 motor.stop() # 窗帘停止在预设位置 ``` 3. **节能管理系统** - 检测人员活动轨迹:在走廊/房间入口安装,联动灯光空调 - 数据统计:通过移动方向判断进出房间次数 $$ count = \sum_{i=1}^{n} \delta_i $$ #### 二、硬件实现方案(树莓派适配) | 组件 | 说明 | 连接方式 | |---------------|-------------------------------|-----------------------| | TCRT5000 传感器 | 红外循迹模块(成本<¥5) | GPIO 直接读取数字信号 | | 反光胶带 | 标记位置(宽≥2cm) | 贴在目标表面 | | MCP23017 | 扩展GPIO(可接多组传感器) | I2C接口级联 | **接线示例**: ``` 树莓派 GPIO17 → 传感器OUT引脚 树莓派 3.3V → 传感器VCC 树莓派 GND → 传感器GND ``` #### 三、开发实践步骤 1. **传感器校准** - 调节电位器使指示灯在反光条上方熄灭(输出LOW) - 测量非反光区输出值(通常为HIGH) 2. **阈值算法** ```python # 防误触算法(需连续检测3次) detection_count = 0 while True: if GPIO.input(17) == GPIO.LOW: detection_count += 1 if detection_count >= 3: trigger_alarm() # 触发安防动作 else: detection_count = 0 time.sleep(0.1) ``` 3. **联动智能家居平台** - 通过MQTT协议将检测结果发送至OneNet平台 ```python # 消息示例(EDP协议) message = { "dev_id": "tracker01", "status": "triggered", "location": "window_02" } client.publish("home/security", json.dumps(message)) ``` #### 四、应用场景对比 | 场景 | 实现效果 | 优势 | |---------------------|------------------------------|-------------------------------| | 门窗异常开启检测 | 0.5秒内响应非法侵入 | 比传统机械开关灵敏度高300%[^1] | | 扫地机器人边界控制 | 精确识别清洁区域 | 降低碰撞概率,延长设备寿命 | | 老人跌倒监测 | 检测地面停留时间超阈值 | 非接触式,保护隐私 | > 💡 **大一学生适配建议**:从单个门窗监控入手,只需1个传感器+树莓派GPIO直连,3小时内可完成原型开发。 --- ### 相关题 1. 如何用树莓派同时管理多个循迹传感器(如整屋安防系统)? 2. 循迹传感器在强光环境下失效的解决方法有哪些? 3. 如何将循迹传感器数据与OneNet平台可视化界面联动? [^1]: 传统的安防措施在很多方面不仅耗时和消耗人力物力,并且容易让用户错失事故处理最佳时段。为了解决该题,本人设计了一个基于OneNet的智能家居安防系统...该系统以STM32F103ZET6芯片为信息处理中心,能够根据用户需求对采集的数据实时整合处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值