卷 I · 看清· CH 01· 自由度扫描器 深度 1/28

你不缺审美,你缺的是出处

你写完一个界面,感觉「不太对」,但说不出哪里不对。于是你换了个蓝色,加了点阴影,把圆角从 8 改成 12——还是不对。这一章要做的事,是把「不太对」换成一个能数出来的数字。

全书主线110 个随手定的数收窄,不是变美

先说那个界面

你接了个活:给 App 加一个「订单详情」页。设计稿没有——或者有,但只是一张截图,标注全靠猜。你照着做完了,跑起来看了一眼。

不难看。也不好看。它长得像「一个程序员做的界面」。

你开始调:标题从 18sp 改到 20sp,好像好一点;卡片圆角从 8dp 改到 12dp,说不清有没有变化;把那个灰色从 #9E9E9E 改成 #8A8A8A,嗯,好像深了一点点。三十分钟过去,你把它改回了原样。

这里有一个很关键的事实,值得先说出来:上面这三次修改,每一次都是在做一个新的、没有依据的决定。你不是在修问题,你是在给这一屏又添了三个自由度。

「我没有审美」这句话,通常是错的

你能一眼看出别人的 App 好不好看——说明你的判别能力是够的。你缺的不是判别,是生成:你说不出该用哪个数,于是每次都现编一个。

而判别和生成之间的距离,不靠「培养审美」补,靠把可选项砍到很少补。当你的字号只有五个可选时,你不需要审美就能选对——因为选错的空间被拿掉了。

把它数出来

光说没用。我们找一份东西来数:六个界面(登录、首页、列表、详情、设置、弹窗),44 个元素条目,每条记下它用了什么字号、什么间距、什么圆角、什么颜色。这些值不是我编的怪数——每一个单看都很正常,都是你我在真实业务代码里会写下的那种。

然后数一下:每个维度上,一共出现了多少个互不相同的值。

先看那个总数:110

这一百一十个数,是你(或者你们组)在过去几个月里,一次一个地、在没有任何依据的情况下敲进代码的。每一次敲的时候,你想的都是「这里差不多要 14 吧」。

然后看那一行字号:10 / 11 / 11.5 / 12 / 12.5 / 13 / 13.5 / 14 / 14.5 / 15 / 15.5 / 16 / 17 / 18 / 19 / 20 / 24 / 28

你能说出 13.5 和 14 的分别吗

不能。用户也不能。

但用户能感觉到这一屏有点脏——因为「13.5 和 14 混在一起」制造的不是层级,是噪声。层级需要的是可辨认的差别;13.5 和 14 之间的差别,小到无法辨认,却大到足以让两处本该一样的东西看起来不一样。

这就是「难看」的第一个具体来源:你花了两个决定,买到了零个层级和一点脏。

设计师做的不是「选得比你好」

现在说这本书的主线。

主线

设计师不是每次都选得比你好,是他们不每次都选。

他们在项目开始的时候花半天定下一套值——五个字号、七个间距、一个种子色——之后每画一个界面,只从这几个值里取。他们一年里做「选一个数」这个动作的次数,可能还没有你一天多。

所以「像样」不是审美的产物,是约束的产物。

把上面那 110 个数收进阶梯之后是 34 个。你可以在上面的 Demo 里切到「收窄之后」看代价:

维度平均挪动最大挪动
字号1850.86 px3 px
间距2471.63 px8 px
行高1251.33 px4 px
圆角1244.08 px24 px
颜色251 个种子剩下全部算出来(第 15 章)

注意字号那一行:平均只挪了 0.86 个像素。

这是整本书最重要的一个数字。它说明:把 18 个字号收成 5 个,视觉上几乎什么都没发生。你没有牺牲任何设计意图,没有让任何一处变得更丑。你只是把「随手」换成了「有出处」。

常见的反驳:「但这里就是需要 13.5」

几乎从来不是。真正需要 13.5 的情况,是你在解决一个具体的物理约束——比如「必须在 360dp 宽里塞下 9 个字符」。那时候 13.5 是算出来的,它有出处。

而 99% 的 13.5,来自「14 好像大了一点点」。这句话的真正含义是:它旁边那个元素的字号定错了。你在用一个新的随手值,去补上一个旧的随手值造成的别扭。

你有设计师没有的东西

说到这里,这本书为什么写给开发,而不是「开发也能看的设计入门」,就有答案了。

设计师维持一致靠的是眼睛和纪律:他们要记住这套值,每次手动去取,靠 review 抓漏网的。

你可以靠类型系统

下面这两段代码,功能完全一样。区别在于第二段让「随手写一个数」这件事编译不过

// 第一种:能写任何数,于是你就会写任何数
Text(
    text = title,
    fontSize = 13.5.sp,          // 三个月后没人知道为什么是 13.5
    modifier = Modifier.padding(top = 11.dp)
)

// 第二种:只能从阶梯上取
Text(
    text = title,
    style = MaterialTheme.typography.bodyMedium,
    modifier = Modifier.padding(top = Spacing.medium)
)

再往前一步,你还能加一条 lint 规则,禁止在 UI 层出现裸的 .dp / .sp 字面量。这一步是设计师永远做不到的——他们的工具里没有编译器。

怎么把这套东西真正搭起来,是第 21 章的事。现在你只要记住:这是你的主场优势,别浪费它。

这本书接下来干什么

把上面那张表的每一行拆开,就是这本书的七卷:

卷 II · 距离间距 24 → 7
卷 III · 字字号 18 → 5,行高 12 → 5
卷 IV · 色颜色 25 → 1 个种子
卷 V · 手时长 8 → 4,状态 3 → 14 格(这个反而要变多)
卷 VI · 交付把上面所有值写进 MaterialTheme
卷 VII · 表面投影 7 → 6 级,边框大部分直接删掉

注意卷 V 那一行:有一个维度是要变多的。状态——加载、空、出错、离线、按下、禁用——你现在只写了三种,而实际存在十四种。少写的那十一种不会因为你没写就不出现,它们只是会以「默认值」的样子出现在用户面前。

所以这本书不是一味做减法。准确的说法是:把「你必须临场判断的地方」减到最少,把「你必须交代清楚的地方」补齐。

每章末尾都有这样一张账

从这一章开始,每章结束时会记下这一章帮你关掉了哪几个自由度——也就是从此以后你不用再临场决定的事。28 章加起来是 78 条,那就是第 24 章那张检查表的来源。

顺便:现在按一下键盘上的 M。这一页会浮出红线,把它自己的每一个间距、字号、对比度都量给你看——数字是当场从 DOM 读的。你从第一章就可以开始检查这本书有没有守自己写的规矩。

本章关掉的自由度本章 1 条 · 累计 1 / 78
  • 「这里该用多大 / 多宽 / 什么颜色」——从此这不是一个每次都要回答的问题。答案永远是「去阶梯上取一个」,而阶梯是提前定好的。