摘要:
2018年的时候,艺灵接单时搞过微信小程序。当时在写地址页时碰到了一个bug,主要是针对ios设备的。即:textarea有最小的padding且不可被设置。当时的解决方法是利用wx.getSystemInfo这个API获取设备信息,然后做进一步的兼容处理…
记得在2018年时,艺灵的《微信小程序从入坑到放弃之坑八:textarea在苹果手机中的大Bug》这篇文章中有提到过微信小程序的textarea
在苹果手机上是有坑的。一眨眼,现在都0202
年了,没想到这个bug
依然存在!微信官方这是已经放弃治疗了吗?[:笑哭][:笑哭][:笑哭]
如果看官还没有阅读《微信小程序从入坑到放弃之坑八:textarea在苹果手机中的大Bug》这篇文章的话,建议先阅读一下,了解下当时的场景。没有阅读过的也没关系,在这篇笔记中,艺灵会详细的介绍这个bug。都说有图有真相,咱们先来上图看下bug长什么样子吧!如图:textarea组件在安卓和苹果手机中的默认样式.png
现在看来,好像并没有什么问题对吧!那我们再来输入一些文字后对比一下可好?上图!textarea组件在安卓和苹果手机中输入内容后的样式.png
可能很多看官还是没有get到上面图片想表示啥,仔细看红框框的地方。为了更清楚的突出问题,再来张局部特写照。如图:textarea组件在安卓和苹果手机中输入内容后的局部特写.png
此时,我们已经能很明显的看出区别了。同样的代码,在苹果手机和安卓手机上输入内容后问题就出现了,是不是很神奇???
前面的图片中还有一个重要信息一直没有用到,是什么呢?就是文本框前面的2rpx
、6rpx
、12rpx
等色块。这是用来干嘛的呢?方便测量输入框中的文字离左侧的距离。如图:textarea组件设置相同属性后在苹果和安卓手机中左侧的距离不一致.png
现在,我们已经能很明显的看出textarea组件在苹果手机上的区别了。但是新的问题又出现了,到底是10rpx
还是12rpx
呢?仔细看图,安卓的离左侧也有一点空隙,若以安卓的为准,左侧有一点点空隙是正常的,那么在苹果手机上的差值则为10rpx
;若以12rpx
为准,但那个汉字一的左侧有点虚。所以,为了保险起见,艺灵个人认为此处的差值是10rpx
。特别说明下,此处的截图用手机传图时选择的是原图哈~
说到这里,略懂前端代码的看官都知道,想要实现上面的效果至少有两种方法。
padding-left:12rpx
;设置textarea的左内边距值padding-left: 0;text-indent: 12rpx
;设置textarea的左内边距值 + 文本缩进那既然答案已经出来了,这篇文章是不是就到此结束了呢?骚年,太天真了吧!!!如图:textarea已经设置了padding属性值为0了哦~.png
有看官要说了:你只展示了wxml
页面的代码,谁知道你的wxss
中有没有搞鬼呢?有本事你加个!important
。
不服?!没关系,有图有真相!上图:padding添加了!important属性后在苹果手机中的效果.png
看到了没有,强大的!important
在这里也变得一点儿用都没有。看官这下服了吧!2018年的文章可不是白写的,当时没少测试。[:笑哭]
既然直接修改padding:0
在苹果手机中是无效的,那我使用text-indent
呢?话不多说,继续上图!textarea组件设置text-indent后在安卓和苹果手机上的对比图.png
这下懵逼了!难道text-indent
写法有问题?可现在的textarea
已经是块元素了呀。换个view
标签试试,如图:view标签使用text-indent是有效果的.png
嗯,跟期望的一样,是有效果的,但为什么在textarea
上会无效呢?艺灵也不知道,可能这又是个bug
吧…[:笑哭]
现在问题已经清楚明了了,那接下来就说说如何解决这个bug
吧!
虽然在安卓手机上padding
的值可以正常设置,但为了跟苹果手机一致,可以设置最小值为10rpx
。那这样就有了新的问题,由于ios端本身最小值就是10rpx
,那此时若不做处理就成了20rpx
。所以,我们要判断用户的设备。大致思路就是:如果用户的是ios设备,就设置padding
为0,这样就跟安卓端统一了。下面开始搞代码了,看官是不是已经迫不及待了?不急不急,一步步来。
首先我们先创建一个名叫textarea-padding-bug-on-ios
的组件,目录如下:
// 微信小程序中的目录结构
components /* 组件目录 */
textarea-padding-bug-on-ios /* textarea组件目录 */
index.js /* js文件,交互及逻辑都在这里(可以当成.js来理解) */
index.json /* json文件,可配置标题、引用组件等 */
index.wxml /* wxml模板文件,前台展示(可以当成.html来理解) */
index.wxss /* wxss样式文件(可以当成.css来理解) */
pages /* pages目录 */
index /* 首页目录 */
index.js /* js文件 */
index.json /* json文件 */
index.wxml /* wxml模板文件 */
index.wxss /* wxss样式文件 */
组件目录创建完毕,接下来最重要的就是js
了,代码如下:
// 组件的核心js代码
/* 获取系统信息 */
handleGetSystemInfo() {
wx.getSystemInfo({ /* 获取系统信息 官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/base/system/system-info/wx.getSystemInfo.html */
success: (res) => {
this.setData({
platform: res.platform /* 客户端平台 */
})
console.log('获取系统信息 ', res)
}
})
}
上面的handleGetSystemInfo
方法写在methods
中,然后在ready
中调用this.handleGetSystemInfo()
方法即可。另外,wxml
模板页也需要修改下,在textarea
的class
上做下判断即可。相关代码如下:
// 组件的核心WXML源码
<textarea class="textarea {{platform === 'ios' ? 'textarea__ios_bug' : '' }}"></textarea>
最后,在wxss
中添加一个textarea__ios_bug
类名即可。
// 组件的核心wxss源码
/* 修复ios的padding bug start */
.textarea__ios_bug {
padding: 0; /* 此处的值= 安卓端的值 - 10,单位:rpx。示例:安卓上是16rpx,此处就是6rpx */
}
/* 修复ios的padding bug end */
现在,我们就可以愉快的在安卓端和ios端统一UI样式了。如图:使用getSystemInfo判断设备来解决padding的bug.png
怎么样,左侧的距离一样了,开心不开心!
等等,好像有点儿不对劲,怎么感觉上边的距离不一样高呢?如图:textatea的上内边距也不一样.png
怎么样,padding: 0
可以解决左内边距,但解决不了上内边距,现在是不是更加懵逼了???[:偷笑]
说真的,别说你懵逼了,艺灵我自己都陷入了沉思中…
等等,为什么我们不使用line-height
行高属性来控制这个问题呢?骚年,能想到这一点,很赞哦!
说起行高line-height
这个属性,其值有好几种写法且不能为负。其值可以是:%
百分比、数字
或px 或 rpx 或 vw
等转换单位。这里我们还是先写一波代码看效果,直接上图。如图:对比几个不同值的行高后并没有发现变化.png
此时,不管是安卓机还是苹果手机,都没有明显的变化。难道行高也不支持???继续调大行高的值来看下会怎样。如图:苹果和安卓手机上都有最小行高.png
此时通过对比可以发现:苹果手机上的最小行高值为34rpx
;安卓手机上的最小行高值为31 ~ 32rpx
。 有关行高的知识点,参考网络文章:《CSS行高——line-height》
是不是又发懵了???说起行高,这里还隐藏了另外一个大坑!什么坑呢?那就是字体!我们都知道,苹果手机中默认是苹方字体,而安卓的却没有苹方字体,也没有像pc端的微软雅黑,网上说是Droid Sans
,具体的无法验证。再来看看上面的代码,艺灵未设置统一字体,所以安卓上出现畸形的行高可能与手机有关。反正有一点是可以肯定的:默认最小行高值都不是1。另外再提一点儿,即使是苹果手机,苹方字体也有坑的哈,具体见艺灵在微信官方社区中提问的帖子:《苹方字体PingFang-SC-Bold比Medium要小?!》。虽然事情过去很久了,但同样没有得到解决哈。[:笑哭]
说真的,我现在看到微信小程序就觉得恶心,坑太多不说,还没有解决方案。关键你遇到的也只是冰山一角而已…
那是不是就没救了呢?答案是否定的,如果我们的项目对设计稿要求不太严格或者压根就没有设计标准的话,这篇文章前面讨论的这些全都可以忽略不计了。如果要求稍微宽松一些的话,最简单的解决方案就是:调整安卓的padding
,最小值设置为20rpx 10rpx
,最小行高以苹果为准即可。 那如果设计师不肯退步,如何实现高保真还原设计稿呢???
通过前面的一系列测试,不难发现一个现象:padding
和line-height
是有效的,但在ios设备上有最小值且不能被重置掉,text-indent
目前在安卓和ios端都是无效的。 如果想保证安卓和ios端尽可能统一,那就要再想其他办法尽可能消除这种差异。
接下来,我们祭出最后的法宝margin外边距。理由:margin
的值可为负,通常与padding
配合使用以实现一些特殊布局。 例如:自适应高度的多列布局。视频演示:css布局之自适应高度的多列布局.mp4
其原理就是:设置一个足够高的padding-bottom
再设置一个负的相等的margin-bottom
,这样正负相互抵消,就实现了自适应高度了。
回到这篇文章中来,我们再捋捋:由于最小行高是无法改变的,能改变的也就只剩下“内边距”了。出于布局考虑,我们给textarea
再添加一个父级并设置overflow:hidden
裁剪属性,避免textarea
因负边距而出现布局错乱等现象。
看官应该能猜到该怎么实现了吧,还是直接上代码吧。
// 组件的核心WXML源码
<view class="form__label_content textarea-wrap {{platform === 'ios' ? 'textarea__ios_bug' : ''}}">
<textarea class="textarea" placeholder="请输入详细地址"></textarea>
</view>
// 组件的核心wxss源码
.textarea-wrap .textarea {
background: transparent;
width: 100%;
height: 120rpx;
margin: 0;
font-size: 28rpx;
padding: 10rpx; /* ios端最小值 20rpx 10rpx */
line-height: 34rpx; /* ios端最小行高*/
}
/* 修复ios上的bug start */
.textarea__ios_bug .textarea {
padding: 0;
margin-top: -10rpx; /* 负10抵消 */
}
/* 修复ios上的bug end */
最后,来看下在上述代码上略加优化后的效果吧。如图:使用margin的负边距来抵消padding.png
最后再来回顾下本文的几个重点:ios端的padding
最小值为:20rpx 10rpx
,最小line-height
为:34rpx
。所以设计师在出稿时尽可能避免踩坑或者对这块儿的要求度降低,以避免开发人员花费大量的时间在细节的打磨上面。
demo源码已上传到了github
上的dev-textarea-padding-bug-in-ios-20200414
分支中。如果看官需要研究源码,可以点击下面的链接进行访问并下载。前往github仓库下载源码
源码中会有必要注释和本篇文章的所有示例。若有疑问可与艺灵联系,方式见下方二维码或右侧。
原文首发于艺灵设计,转载请注明来源,谢谢。