flutter里竟然没有border-box?

2,181 阅读4分钟

某一天我发现需求里需要在flutter里实现一个点击后动态加上边框的输入框,这不简单?只要判断状态给Container加上一个装饰器不就得了?于是我小手一挥,写下了如下代码:

image.png

isOnFocus是监听焦点在不在输入框里的变量,用其来判断是否应该增加边框,效果如下:

1.gif

正当我得意之时,却发现这玩意儿怎么宽高有点小啊?仔细一看原来是边框是往内部加的,而设计稿预期是在外层加上一圈边框,那好办,按照前端的一贯思维,这里应该有个类似borderbox的东西,可以让我把边框加在外面,边框不算在width和height内,在google上查了一圈,惊奇地发现,flutter里竟然没有borderbox?!可能作为一个前端有点想当然了... (当然也可能是我没找到,这里如果有的话麻烦高人指点)

在发现只能自己来模拟boderbox,第一直觉是根据点击状态动态的将box的长宽分别增加,于是就诞生了第一种解决方案–动态宽高法。

1.动态宽高

点击事件既然能给box增加边框,那我们用同一个变量,来更新box的长和宽不就好了?我们来写一个最简单的判断~ image.png 这下没问题了吧?我轻松地点开flutter页面,结果这效果令强迫症的我浑身难受:

2.gif

由于我之前的页面都是用padding控制上下左右距离的,这下一改动就会牵动所有的布局,当然这也可以通过外面再套一层Container来解决,如下图所示,在外层加一个container方便外层其他元素的布局

image.png 转存失败,建议直接上传图片文件

这样总万无一失了吧,but,当你内部不是像我一样只是有一个输入框,而是有元素的话,新的问题又来了,内部padding的边缘是以外边为准的,如下图所示,如果你改变了外边的width,padding长度不变的话,内部布局又会发生变化【吐血】

image.png

这个时候你只能又在内部的padding里加判断,如果isOnFocus了要怎么变化padding,如果内部不复杂还好,如果内部padding比较复杂的话...关键是这里要调整变化宽度的时候真的是牵一发动全身

2.边框变色

那么有没有更简单易行的方法呢?最好是不要修改容器的长宽!啊哈,看我发现了什么,Colors类里面竟然有一个transparent属性,这不就好办了,在没有Focus的时候把Colors设为透明的,focus后再加上颜色:

image.png

我就这样开开心心的以为解决问题了,直到很久很久以后,被一个bug打醒,才发现,大意了啊,在flutter里透明的边框是不占位的,也就是说没有focus的时候输入框的长宽会扩大,这不跟以前一样了嘛!

当然解决办法还是有的,我直接把边框设为背景色就行了吧!天才竟是我自己

image.png

嗯嗯!这样看着不错,效果基本实现了:

4.gif

再仔细看看....嗯?边框的圆角呢?好像是因为设置的是外边框的圆角,内边框就因为边框长度变小了,这可咋整,UI还原不了啊喂,这个方案也不行吗?

诶等等,圆角是可以自己计算的呀,让我们来看看下面这张图

image.png

设计稿上标记的圆角半径为3,我直接设置装饰器的圆角半径其实是设置的图中的outerRadius为3,当borderWith也为3的时候,其实innerRadius直接被挤没啦!这个时候只要把圆角设置为边宽+设计圆角宽度~

image.png

最终的实现效果如下:

3.gif

终于!终于把它还原出来了!

总结一下,踩了4个坑:

1.flutter里的边框是向内添加的,没有border-box

2.flutter如果动态改变容器的宽高,很可能影响到其他布局的元素

3.flutter的边框设置为transparent其实是没有占位效果的,因为边框是像一个图层悬浮在上面的,底下有颜色的话,就相当于没设置边框。

4.flutter中的圆角是外层圆角,而不是内层圆角

实现border-box还是推荐第二种边框变色的方法,成本低且不影响其他元素的布局