小程序TabBar图标规范:透明PNG、app.json配置与真机排查 做小程序的这些年我最怕的不是接口联调也不是样式适配而是上线前一天晚上真机预览一打开底部 TabBar 上本该是购物车的那一格赫然显示成一个白色的方块。这套「含首页/分类/购物车/我的等多状态PNG图标、透明背景、规范命名」的图标包就是被这类事故反复教育之后我给自己攒下来的一套标准件。它解决的事情很具体把底部导航需要的每一个状态图用统一的尺寸、干净的透明背景、一眼能看懂的命名整理好让app.json里那几行配置一次写对不用再靠猜路径和试错。如果你正在从零搭一个小程序、或者接手了一个图标风格五花八门的旧项目这篇东西基本能覆盖你从拿到图标包到真机跑通的全部环节——包括那些文档里不会写、只有踩过才知道的细节。1. TabBar图标这套小图为什么最容易在最后一刻出问题1.1 一次真机预览里的白色方块那次事故的现场我记得很清楚。设计给的图标是一套挺漂亮的线性图标我在开发者工具里看了一遍四个格子都好端端的颜色、间距、文字对齐都没毛病。真机预览一开购物车那一格变成了纯白方块其余三个正常。第一反应是图片没打包进去翻了一遍目录文件在第二反应是路径写错了逐字对了一遍app.json也没错。折腾了快四十分钟才发现那张购物车图标的源文件是从一张带白色背景的 JPG 里抠出来的导出时存成了不带 alpha 通道的 PNG开发者工具的渲染层在某些情况下会做近似处理真机就老老实实把白底画了出来。这件事给我留下的教训不是以后注意点而是TabBar 图标是整个小程序里最不值钱、却最容易翻车的资源。它小到没人愿意为它单独走一遍设计评审又重要到一旦出问题用户第一眼就看见。而且它的约束条件特别集中——尺寸、格式、大小、路径、背景五件事里错一件表现都是显示不出来或者显示得不对劲错误现象高度相似排查时几乎没有指向性。更麻烦的是这类问题往往在开发后期才暴露。因为大部分人在开发者工具里调样式的时候根本不会去点底部那几个 tab等到功能都做完了、准备提审了才发现图标有问题。这时候改图、重新导出、重新走一遍资源替换流程时间成本比一开始就规范化高出好几倍。所以我后来给自己定了个规矩不管项目多小TabBar 图标必须在项目初始化阶段就落地且必须真机验证一次。这套图标包就是为这个规矩服务的——它把首页、分类、购物车、我的这几个几乎每个项目都会用到的高频图标按统一规格做好选中态和未选中态成对出现透明背景处理干净文件名直接对应配置字段拿来就能用。1.2 原生tabBar对图标的四道硬约束很多人对 TabBar 图标的认知停留在放张图上去就行实际上原生 TabBar 对图片有四道非常明确的约束任何一条不满足轻则显示异常重则整个 tabBar 配置报错。第一道是格式。原生 TabBar 只认位图PNG、JPG、JPEG 这三种SVG 不支持WebP 不支持字体图标更不支持。这一点劝退了不少想用 iconfont 统一管理图标的同学——在原生 TabBar 里这条路是走不通的要么老老实实用 PNG要么就得开自定义 tabBar那是另一套成本。第二道是体积。单张图标的文件大小有上限官方给的建议是控制在 40KB 以内。这个数字看着宽松实际很容易超——尤其是那种带渐变、带阴影、尺寸做到 200px 以上的图标一张就能干到 60KB 往上。超了不会报错但有可能在某些机型上加载失败表现就是空白。第三道是路径。iconPath写的是相对路径相对于app.json所在的目录。写绝对路径、写网络地址都不行。而且路径是大小写敏感的——开发者工具在部分系统上不敏感真机敏感这个差异坑过无数人。第四道是数量与配对。list数组最少 2 项、最多 5 项少于 2 项或多于 5 项都会直接报配置错误。同时每个 tab 的iconPath和selectedIconPath最好成对给只给一个的话切到选中态时图标会消失或者保持不变视觉上很怪。把这四条约束记住其实已经能避开 TabBar 图标 70% 的问题。剩下的 30%集中在图本身画得对不对上——那就不是配置问题是设计规范问题。2. 81×81画布上的取舍尺寸、留白与像素对齐2.1 81这个数字是怎么定下来的刚接触的人常问为什么图标要做 81×81做个 48×48 不是更省体积吗这个数字的推导逻辑其实很朴素。原生 TabBar 上单个图标实际渲染出来的视觉尺寸大约在 25 到 27 个逻辑像素之间不同平台略有差异。而主流的移动设备屏幕像素比常见的是 2 倍和 3 倍。为了让图标在 3 倍屏上也能保持清晰你至少需要准备 27×3 81 像素的图。这就是 81 的来源——它是为了覆盖最高密度屏幕而准备的三倍图。理解了这一点尺寸选择就有依据了画布尺寸适用情况3倍屏表现建议48×48只考虑低密度屏明显发虚不建议64×64折中方案轻微发虚勉强可用81×81覆盖 3 倍屏清晰推荐96×96 及以上有余量清晰可用但注意体积120×120冗余清晰体积浪费慎用我个人的习惯是固定 81×81。理由有两个一是它刚好是 27 的整数倍缩放比例是干净的 1/3像素对齐好处理二是这个尺寸下一张纯色线性图标的 PNG 通常只有 2 到 5KB一套五个 tab 十个状态图全加上也就四五十 KB对主包压力可以忽略。如果项目里有大尺寸需求比如某些安卓平板我会额外准备一套 96×96 的但不会默认塞进主包而是按需加载。大部分项目 81×81 足够用别为了预留余量把体积翻倍。2.2 三分法留白图形该画多大拿到画布之后第二个问题就是图形在 81×81 的格子里画多大新手最容易犯的错是把图形撑满画布。看起来更清楚实际显示在 TabBar 上会显得又大又挤和旁边的文字挤在一起整个底部导航看起来非常压迫。而且撑满之后不同图标之间的视觉重量会严重失衡——圆形的购物车和方形的首页图标同样撑满画布圆形的视觉面积只有方形的 78% 左右看起来就是一大一小。我的经验值是图形的有效外接框控制在 60 到 66 像素之间也就是画布的 74% 到 81%。四周留出大约 8 到 10 像素的空白。这个比例下图标既不会显得小气又能和上下元素拉开呼吸感。具体到几个高频图标可以这样把握首页房子的屋顶是最宽处宽度控制在 62px 左右屋檐到底部的总高度约 58px整体略微偏上因为房子的视觉重心在屋顶。分类四宫格或者三横线最外框 60×60格子之间的间距用 6px避免缩小后糊成一块。购物车车身宽度约 56px把手往左上延伸整体高度约 54px。购物车的视觉重心偏下画的时候整体上移 2px 左右看起来才不会往下掉。我的人像的肩宽是主体宽度约 58px头部的圆直径约 20px头部中心大概在画布纵向 30% 的位置。这些数字不是玄学是反复对比之后的结果。判断标准只有一个把五个图标并排放在一起眯起眼睛看它们的视觉重量应该差不多。如果有一个明显更重或更轻就回去调它的外接框。还有一个容易被忽略的点图标和文字之间的垂直关系。原生 TabBar 里文字大小是系统定的你改不了。所以图标的视觉重心必须自己控制好。如果图形重心偏下图标会显得贴着文字偏上又会显得离文字太远。稳妥的做法是把图形在画布内整体上移 1 到 2 像素给底部的文字留出视觉间隙。2.3 线条取3的倍数避免半像素灰边这一条是从像素对齐里来的属于那种不知道也能做知道了就再也回不去的细节。前面说了81 是 27 的 3 倍缩放比正好是 1/3。这意味着设计稿上一根 3 像素宽的线显示出来正好是 1 个逻辑像素边缘干净。如果画成 4 像素缩放后是 1.33 个像素渲染引擎会做抗锯齿处理结果就是一根边缘发灰、看起来有点糊的线。所以我在 81px 的画布上画线性图标时线宽一律取 3 的倍数主干线用 6px显示 2px次级细节用 3px显示 1px。圆角半径也尽量取 3 的倍数比如拐角用 9px 或 12px 的圆角。这样导出后无论在哪档屏幕上边缘都是锐利的。同样的逻辑适用于图形的位置。图形的起始坐标、宽度、间距尽量都落在 3 的整数倍的网格上。听起来有点强迫症但你会发现按这个网格画出来的图标五个摆在一起的时候间距天然就是均匀的——因为大家用的是同一套网格。提示如果设计稿是按 162×162 画的二倍稿那线宽就用 6 和 12网格步长变成 6逻辑是一样的。关键是设计稿尺寸和最终导出尺寸保持整数倍关系中间不要出现 0.5 这样的缩放。这三件事——尺寸、留白、对齐——决定了图标看起来正不正规。而下面要说的透明背景和状态配对决定的是它能不能用。3. 透明背景与状态对两件比画图更重要的手艺3.1 alpha通道踩坑白底图、描边白边、PNG-8索引色回到开头那个白色方块。它的成因值得单独拆开说清楚因为这一类的坑反复出现。第一种从 JPG 或截图里抠图导出时没有保留 alpha 通道。很多人在做图标时图省事从网上找一张图、或者从设计稿里截一块抠掉背景之后直接另存为 PNG。但 PNG 有两种常见形态带 alpha 通道的 32 位 PNG和不带 alpha 的 24 位 PNG。后者虽然有PNG的扩展名背景其实是实打实的白色像素。这种图在浅色背景下看不出来一旦 TabBar 背景色是深色或者带渐变白底立刻现形。第二种抠图不干净留下的白边。抠图工具处理边缘时往往会在图形轮廓外侧留下半透明的白色像素。在白色背景上看不出来放到深色背景上图标周围会有一圈淡淡的白晕看起来像描了个不干净的边。这个在真机上特别明显因为真机的 PPI 高。第三种导出时选了 PNG-8 索引色模式。PNG-8 最多支持 256 色虽然也支持单一透明色但边缘只有透明和不透明两种状态没有半透明过渡。结果就是图标的圆弧边缘出现锯齿状的硬边看起来像上世纪的图标。正确做法是导出 PNG-24 或者 PNG-32保留完整的 alpha 通道。我的自检流程是这样的三步很快在图片查看器里把背景切成纯黑和纯白各看一遍。纯黑背景上看有没有白边纯白背景上看有没有黑边或者灰底。放大到 400% 看图形边缘。正常应该有一圈半透明的过渡像素颜色是图形色到透明的渐变如果边缘是硬切或者有杂色说明抠图不干净。看一眼文件大小。81×81 的纯色线性图标正常在 1.5 到 5KB 之间。如果只有 800 字节很可能是索引色或者色深被压过头了如果超过 15KB大概率是带了多余的通道或者元数据。注意这套图标包里所有图标的背景都是完全透明的也就是说它们在 TabBar 上显示的颜色完全由图标自身的填充色决定。因此图标的颜色必须在导出前就定好不要指望用 CSS 或者配置项去染——原生 TabBar 的color和selectedColor字段只作用于文字对图标无效这一点是新手最常见的误解之一。3.2 选中态与未选中态靠明度和填充不靠换形状一套 TabBar 图标真正专业的地方不在单个图标画得多好而在两个状态之间的关系处理得对不对。我见过两种典型错误。一种是两个状态用了完全不同的图形——未选中是线框房子选中变成实心圆点用户点完之后会有一种图标换了个人的割裂感。另一种是两个状态只差颜色形状完全一样结果在低亮度屏幕或者强光下用户根本分不清当前在哪一页。正确的做法是轮廓保持一致靠填充方式和明度建立差异。具体拆开讲维度未选中态选中态说明描边方式线性描边实心填充或加粗描边最直观的差异来源图形颜色中性灰明度约 55%深色或品牌主色明度约 15%明度差拉开到 40% 以上线条粗细基础线宽可加粗一档视觉重量增加图形尺寸基准尺寸可略微放大 1-2px强化被点亮的感觉内部细节保留可适当简化实心后细节容易糊这里的关键是明度差。很多设计稿只在色相上做区分比如灰色和蓝色但灰色和蓝色如果明度接近在小尺寸下几乎看不出区别。判断标准很简单把图转成灰度看一眼如果两个状态还能明显分出深浅说明明度差够了。关于灰色取什么值我的经验是未选中态用#8A8A8A到#999999这个区间选中态用#1A1A1A到#262626或者直接用品牌主色但把明度压到 20% 以下。避免用纯黑#000000在某些屏幕上会显得过于锐利也避免用纯灰#CCCCCC在浅色背景上对比度不够。还有一个细节选中态的实心填充要留出呼吸孔。比如购物车的实心版本如果能从填充块里透出车身和轮子之间的间隙辨识度会高很多。全部糊成一坨黑缩到 27px 之后就是一块黑色多边形用户得盯着看两秒才认出来是什么。我的做法是填充区域之间至少留 3px在 81px 画布上的间隙保证缩小后还能看见结构。4. 命名规范不是洁癖是给三个月后的自己留后路4.1 一套可执行的命名公式先说一个真实场景项目做了半年产品突然要把分类改成发现图标内容不变只是文案变了。这时候你需要找到所有相关的资源并改掉引用。如果文件名是1.png、2.png、3.png你只能靠肉眼比对如果是tab_category_normal.png改起来就是一次搜索替换的事。命名这件事的价值只有在需要维护的时候才体现出来。所以我给这套图标包定的命名公式是tab_功能名_状态.png四个部分每一段都有明确含义tab_前缀标明这是底部导航专用图标。项目里往往还有大量业务图标列表页的箭头、空状态的插图、按钮里的小图标统一加tab_前缀一眼就能筛出来也避免了业务图标和 tab 图标重名的可能。功能名用英文小写多个单词用下划线连接。首页用home分类用category购物车用cart我的用profile。不要用拼音shouye这种也不要缩写到看不懂ct、pf。状态只有两个值normal和active。不要用off/on不要用default/selected也不要出现hover这种从 Web 时代带过来的词。全项目统一一套词比用哪个词更重要。扩展名全部小写.png。按这个公式一套五个 tab 的图标包文件清单是这样的tab_home_normal.png tab_home_active.png tab_category_normal.png tab_category_active.png tab_cart_normal.png tab_cart_active.png tab_profile_normal.png tab_profile_active.png如果要放第五个 tab比如订单就是tab_order_normal.png和tab_order_active.png。规律很直白新人接手也能照着往下加。有几个细节需要提醒不要用中文文件名。开发者工具里可能没问题但打包上传、跨平台构建的时候中文名是经典的事故源。不要用空格和特殊字符。空格在某些构建流程里会被转义成%20路径就匹配不上了。不要用版本号后缀如_v2、_final。要迭代就在 Git 里管文件系统里永远保持干净的名字。真要区分版本用目录分。大小写统一小写。前面提过部分平台对文件名大小写敏感Tab_Home_Normal.png和tab_home_normal.png在开发者工具里可能都能读真机上就是找不到。4.2 目录分层与app.json路径的对应文件放哪也是一个需要一开始就定好的事。我习惯在项目根目录建这样的结构project/ ├── app.json ├── app.js ├── app.wxss ├── assets/ │ └── tabbar/ │ ├── tab_home_normal.png │ ├── tab_home_active.png │ ├── tab_category_normal.png │ ├── tab_category_active.png │ ├── tab_cart_normal.png │ ├── tab_cart_active.png │ ├── tab_profile_normal.png │ └── tab_profile_active.png └── pages/关键是assets/tabbar/这个分层。assets放所有静态资源下面再按用途分子目录tabbar专门放底部导航图标。这样做的好处是图标包可以整目录替换不会和业务图标混在一起同时也方便你算体积——直接看这个目录多大就知道静态资源占了多少主包空间。对应的app.json路径写法是iconPath: assets/tabbar/tab_home_normal.png, selectedIconPath: assets/tabbar/tab_home_active.png注意路径是相对于app.json所在目录的前面不要加./也不要加/。加了/在某些版本里会被解析成项目根目录的绝对路径虽然有时候也能用但属于不规范写法跨端构建工具处理时容易出问题。如果项目页面层级比较深导入了子包的app.json在主包根目录路径依然按主包根目录算这一点别忘了。4.3 图标包跨项目复用时的冲突处理这套图标包我用了好几个项目中途遇到过复用带来的问题项目 A 用的是圆角风格项目 B 要用更锐利的直线风格但两边的文件名一模一样。如果直接复制过去很容易在某个项目里改错了文件改完才发现改的是另一个项目的副本。解决办法是在目录层级上做风格区分assets/tabbar/ ├── line/ # 线性风格 │ ├── tab_home_normal.png │ └── ... ├── filled/ # 实心风格 │ ├── tab_home_normal.png │ └── ...文件名保持不变靠父目录区分风格。这样app.json里只要换一个目录名整体风格就切换了文件名规则依然是统一的。比在文件名里加_line后缀要干净得多。还有一种情况是同一个项目里要做主题切换浅色主题/深色主题两套图标。原生 TabBar 是支持wx.setTabBarItem动态改图标的但频繁调用有性能开销而且切换时会闪一下。我的做法是把两套图标的目录分好主题切换时统一调一次setTabBarItem批量替换而不是每张图单独调。5. 从图标包到跑通app.json配置与替换全流程5.1 目录落位与文件清单核对拿到一套图标包第一步不是急着改配置而是先把文件放好、核对清单。这一步花三分钟能省掉后面半小时的排查。具体动作建目录。在项目根目录下建assets/tabbar/把八个或十个PNG 全部拷进去。不要散放在根目录也不要放进pages里。数文件。ls assets/tabbar/ | wc -l或者直接在文件管理器里看。数量必须等于 tab 数乘以 2。四个 tab 就是八张少一张后面配置就写不完整。查命名。逐张核对文件名确认状态后缀是normal还是active别出现actived这种拼写变体。命名不统一的话配置里手写路径的时候极容易写错一个字母。看大小。每张图应该在 2 到 8KB 之间。如果有超过 20KB 的单独看看是不是尺寸做大了或者带了多余的通道。验透明。随手抽两张在深色背景的查看器里打开确认没有白底。这五步做完再动app.json。顺序反过来的人很多——先写配置路径报错了再回头找文件越找越乱。5.2 tabBar字段逐个说清楚配置本身不复杂但每个字段的边界得弄明白。一个完整的配置长这样{ pages: [ pages/home/home, pages/category/category, pages/cart/cart, pages/profile/profile ], tabBar: { color: #8A8A8A, selectedColor: #1A1A1A, backgroundColor: #FFFFFF, borderStyle: black, list: [ { pagePath: pages/home/home, text: 首页, iconPath: assets/tabbar/tab_home_normal.png, selectedIconPath: assets/tabbar/tab_home_active.png }, { pagePath: pages/category/category, text: 分类, iconPath: assets/tabbar/tab_category_normal.png, selectedIconPath: assets/tabbar/tab_category_active.png }, { pagePath: pages/cart/cart, text: 购物车, iconPath: assets/tabbar/tab_cart_normal.png, selectedIconPath: assets/tabbar/tab_cart_active.png }, { pagePath: pages/profile/profile, text: 我的, iconPath: assets/tabbar/tab_profile_normal.png, selectedIconPath: assets/tabbar/tab_profile_active.png } ] } }几个字段的实际含义和容易搞混的地方字段作用对象常见误解color未选中 tab 的文字颜色误以为能改图标颜色selectedColor选中 tab 的文字颜色同上backgroundColortabBar 背景色误以为能改文字背景borderStyletabBar 上边框只有black和white两个值iconPath未选中状态图标忘记写或写了网络地址selectedIconPath选中状态图标写成了和iconPath一样的路径pagePath对应页面路径与pages数组里的路径不一致再说几个实操中的补充点pagePath必须和pages数组里的路径完全一致包括大小写。这是最容易犯的错之一因为手写路径的时候人眼会自动忽略细微差别。对不上不会在开发者工具里报错但真机上点了没反应。list的顺序就是 tab 的显示顺序从左到右。先想清楚哪个放在第一位通常是首页再写配置。text是必填的即使你想做纯图标无文字的 tabBar原生也不支持隐藏文字。想隐藏只能走自定义 tabBar。iconPath和selectedIconPath都要给。只给一个的话切换状态时会出现图标消失或者两个状态看起来一样的情况。图标颜色和文字颜色要匹配。如果图标是深灰的#666666文字是浅灰的#8A8A8A底部看起来会很不协调。既然图标颜色在导出时已经定死那color和selectedColor就应该按图标颜色来填保持视觉一致。5.3 换成自定义tabBar之后要注意的三件事原生 TabBar 有个硬限制图标只能用位图位置、大小、动效都改不了。当产品要求图标上加角标动画选中时图标弹一下tabBar 做成悬浮胶囊样式这类效果时就必须开自定义 tabBarcustom: true。开了之后这套图标包依然能用但用法变了——不再是app.json里配路径而是自己写一个组件用image标签贴图标。这里有三件事要特别注意第一尺寸单位换成 rpx。图标在自定义组件里可以用任意尺寸但建议用rpx而不是px这样能自动适配不同屏宽。81px 的图在 375 屏宽下显示成54rpx左右比较合适27 逻辑像素 ≈ 54rpx。第二底部安全区必须自己处理。原生 TabBar 会自动避开 iPhone 底部那条横条自定义的不会。不加处理的话图标会被裁掉一截。做法是在 tabBar 容器的padding-bottom里加上env(safe-area-inset-bottom)这是标准写法。第三selectedIconPath的切换逻辑得自己写。组件里通常用一个currentIndex变量控制点击时切换。要注意的是自定义 tabBar 每次切换页面都会重新渲染如果状态管理没做好会出现点了图标高亮不跟着变的问题。稳妥的做法是把当前索引存在全局数据里onShow时同步一次。自定义 TabBar 的成本比原生高不少我的建议是除非有明确的产品需求否则一律用原生。图标包本身就是为原生场景设计的直接配置就能跑省下来的时间可以花在更值得的地方。6. 真机异常排查图标不显示、发虚、被裁切6.1 图标完全不出现的排查链路图标不显示是最常见的症状但成因有五六种靠猜很浪费时间。我的排查顺序是固定的从最可能到最不可能一条条过第一步看控制台有没有配置报错。list项数不对、pagePath缺失、字段名拼错这些都会在编译阶段报出来控制台直接能看到。如果控制台是干净的说明配置结构没问题往下走。第二步在开发者工具的调试器里看图片请求。打开 Network 面板切到图片资源看那几张 tabBar 图标有没有被成功加载。如果显示 404说明路径不对如果显示 200 但是不显示说明是图片本身的问题。第三步核对路径大小写。这是 404 的头号原因。assets/tabbar/tab_home_normal.png和Assets/Tabbar/tab_home_normal.png在开发者工具里可能都能读到取决于系统真机上一定失败。把路径复制出来和文件名逐字符对一遍。第四步检查图片格式和体积。把图片拖进浏览器直接打开能正常显示说明文件没坏。然后看文件大小超过 40KB 的单独压一下。再看扩展名是不是.webp改了后缀伪装的 PNG——这种情况开发者工具能显示真机解析失败。第五步确认图片有没有真的被打进包里。有些项目的构建配置会忽略assets目录下的某些文件比如配了ignore规则或者资源被 CDN 化了。打开打包产物直接在包里搜文件名确认它在。第六步看tabBar的层级有没有被遮挡。有些页面用了全屏的fixed定位容器z-index设得比 tabBar 高把 tabBar 整个盖住了。这种情况下图标其实加载了只是看不见。临时把容器背景改成半透明如果能看到图标轮廓就是层级问题。这六步走完基本没有定位不到的情况。我把它写成了一个小清单贴在工位边上每次遇到直接照着过比凭经验瞎猜快得多。6.2 图标发虚与位置偏移的定位图标能显示但看起来糊或者位置偏了这类问题更隐蔽因为不报错只是感觉不对。发虚通常有三个原因。一是图标本身尺寸不够用了 48×48 的图在 3 倍屏上放大到 81必然糊。二是图标导出时被压缩过头色深掉了或者用了有损压缩。三是图形里的细节太多比如一根头发丝粗细的线条在 81px 画布上只有 1px缩小到 27px 之后直接消失了视觉上就是一片糊。前两种换图就行第三种得改设计。我的原则是在 81px 画布上任何线条宽度不低于 3px任何间隙不小于 3px。低于这个值的细节在 TabBar 这个尺寸下都是无效信息只会增加视觉噪音。位置偏移分为横向和纵向。横向偏移通常是图形在画布内没有居中——比如画购物车的时候把手往左上伸导致整体视觉重心偏左。解决办法不是挪文件是回设计稿里把图形往右补一点让视觉重心对齐画布中心注意是视觉重心不是几何外接框的中心。纵向偏移更常见表现是图标离文字太近或太远。前面提过原生 TabBar 的文字位置是固定的所以只能调图标。我的一般做法是让图形在画布内整体略偏上——因为视觉上图形的下沿和文字的上沿之间需要留出间隙如果图形居中实际显示时会显得贴着文字。还有一个小概率情况某些安卓机型上tabBar 的高度和 iOS 有差异导致图标看起来整体偏下。这种情况不用改图改了反而在 iOS 上不对。统一按主流机型的表现调个别机型的微小差异可以接受。6.3 包体积与上传限制的取舍图标本身不大但架不住项目里图标多。一个中型小程序各种状态的图标加起来上百张是很正常的。主包体积有上限2MB超了就得拆子包而assets目录下的静态资源是不能拆到子包里的——tabBar 图标必须在主包。算一笔账一套五个 tab 的图标包十个文件按平均 4KB 算总共 40KB占主包 2%。听起来不多但如果项目里还有十几个业务图标集、几张大图、几套字体加起来就危险了。我的做法是TabBar 图标严格控制体积。线性图标压到 3KB 以内实心图标不超过 6KB。方法是导出时用无损压缩工具过一遍通常能再瘦 20% 到 30%。不要在图标里放渐变和阴影。这两样东西会让文件体积翻好几倍而且在 27px 的显示尺寸下根本看不出来。一个 tab 只配一套图。不要为了以后可能换风格把两套都塞进主包。要换风格就在发版时替换。定期清理废弃图标。项目改版之后老的图标文件经常留在目录里没人删。每隔一两个月搜一遍引用把没人用的清掉。有个细节值得单独说图标文件的体积和它的像素内容强相关。一张纯色、线条简单的 PNG81×81 可能只有 1.8KB同样的尺寸加一圈渐变或者一点噪点就能到 15KB。所以控制体积这件事本质是在设计阶段就要做的决策而不是导出之后再压。7. 图标包的长期维护与交付说明7.1 角标、禁用态这些多状态要不要做成图标题里说的是多状态实际项目里最容易让人纠结的是除了选中和未选中还要不要做禁用态、警告态、带角标的状态我的答案是大部分不要做图用 API 解决。角标购物车上显示3这种小红点绝对不要做成图。原生提供了wx.setTabBarBadge和wx.showTabBarRedDot两个接口动态设置位置和样式都是系统算好的各机型一致。自己做图的话数字一变就得换图完全不现实。禁用态在 TabBar 上几乎用不到。用户能不能点某个 tab通常是通过页面内的权限控制实现的而不是把 tab 灰掉——把 tab 灰掉是个很差的体验用户会以为程序坏了。警告态比如我的上面有个红点表示有待处理事项同样用 API 解决showTabBarRedDot就够。所以这套图标包只做两个状态normal和active是刻意的取舍。状态越多维护成本指数上升而实际用得到的场景非常有限。真要做特殊状态在具体项目里单独加一两张图比在通用包里预置一堆用不上的文件要合理。如果确实需要自定义角标样式比如数字背景是品牌色、带描边那就只能走自定义 tabBar 了那是另一套方案。7.2 给图标包配一份能看懂的使用说明最后说一件容易被跳过、但价值很高的事给图标包写一份 README。这套图标包我前后给过好几个项目组用一开始只是丢一个文件夹过去结果每次都有人来问这个图是选中还是未选中为什么我放进去显示不出来能不能给我加个订单的图标。问的次数多了我就写了一页说明放在目录里问题少了八成。说明里包含这几块内容基本信息画布尺寸 81×81格式 PNG-24 带 alpha 通道单文件建议不超过 8KB图形有效区域 60 到 66px。这几个数字写清楚别人拿到就能判断自己的新图标符不符合规范。命名规则tab_功能名_状态.png状态只有normal和active。附一张现有文件清单方便对照。颜色约定未选中#8A8A8A选中#1A1A1A。如果项目要用品牌色说明里注明选中态可整体替换为品牌色但明度需压到 20% 以下。新增图标的操作步骤从哪个模板文件复制、怎么改、导出参数是什么、导出后怎么自检就是我前面说的深色背景看一遍那三步。常见问题把我踩过的那些坑列成问答比如图标显示成白块怎么办真机上图标模糊怎么办路径应该怎么写。每条给一句话的解法。这份说明看着琐碎实际省下的是团队里最贵的东西——沟通成本。而且写说明的过程本身也是一次梳理很多自己没想清楚的细节写着写着自己就明白了。提示说明文档里别写请参考官方文档就完事。官方文档讲的是通用规则你这套图标包的具体约定尺寸、颜色、命名是项目私有的必须自己写清楚否则下一个人拿到手还是得重新问一遍。用久了会发现一套好的图标包价值不在那八张图本身而在它背后那套可复制的规范。图会过时风格会变但尺寸统一、背景干净、命名清晰、状态成对这四条原则换多少个项目都成立。我在实际使用中最大的体会是图标这种看起来最不起眼的资源反而是最考验工程习惯的地方。设计稿画得再漂亮导出时忘了留 alpha 通道上线前就得多熬一个晚上命名随手写成1.png三个月后改需求就得靠肉眼找文件。把这几件小事在项目开头做对后面能省下的时间远超你想象。