前两天做了一个不规则图形布局,由于当初做时没有考虑清楚布局的思路和实现的逻辑,所以走了不少弯路,试了很多办法才做出来的。现在有时间,将这类UI的布局思路先记下来,以防日后自己再遇到还会吃亏。
一、多排不规则图形的布局
类似这种不规则图形的布局,为了方便适配,必须让所有按钮按比例布局,否则无法完美适配各种机型的屏幕。但这里有个问题,按钮的宽高比是一定的,所以我们必须将其中一个(宽高)作为基准才能按比例摆放。从UI效果图来看,以宽度作为基准比较合适,考虑到按钮摆放的位置应该是以宽度为准,高度动态增长来设计的,否则按钮距离左右边距会发生变化,且若按高度来算,宽度有可能会出现超过屏宽或离左右边距太多的情况,所以我是按宽度为基准来布局的。
这里还有一个问题就是宽度可以很容易固定(只需要添加左右边距约束即可),但是高度却是时时变化的(随屏宽不同而改变),所以若是按单个按钮布局,就很难将这几个按钮的中心点摆放在背景图的中心上(不可固定按钮的上下边距)。我尝试了多种方法,最后的灵感是将这几个按钮放到一个自己手动添加的view中,view只需要添加左右边距约束,并将Y轴的中心与背景图中心设为相等即可,然后在view里面添加这些按钮,view的大小会随着按钮的大小而改变,这样就可以完美的实现这种不规则图形的布局了。还有最重要的一点,一定要将中间的按钮摆放在最上层,否则它的点击事件会被其他按钮覆盖。
二、一排不规则图形的布局
看到这个UI效果图,首先脑海里想到的方法跟以往的布局一样,将三个按钮分别添加约束,并按照比例摆放。由于这是个不规则图形,不能简单的将按钮三等分,所以做法是将左右两个按钮的边距固定,中间按钮的中心点与背景图中心相等,以高度为基准来算按钮宽度,这样适配屏幕一定是没有问题的(第一次只在6上面运行了,效果和设计图一样)。
按理说,切换屏幕得到的效果应该是一样的,但是我却忽略了一个最重要的问题,跟第一种布局一样,UI效果图都是以宽度为基准来设计的,可是我在这里却以高度为基准来布局(因为宽度无法固定,与第一种情况略有差异),所以切换屏幕得到的效果会导致按钮之间的间距变大,十分不美观。之后的想法是通过手动修改图片的尺寸(保持按钮的大小不变),让图片之间的间距变小,看起来更接近UI的效果。刚开始在6plus上调试的结果是可以的,基本可以达到UI的效果,但是切换到5上面就不行了,因为5和6都是加载的@2x的图片,且5上的图片显示已经达到按钮的最大饱满度了,再手动修改图片尺寸,会导致图片显示不全,在6上也会受到影响,所以放弃了这种做法。最后参考安卓同事的建议,将图片切成整个背景的,只是将后面的按钮处理成透明,这样一来,三个按钮的约束都是相同的,左右边距均为0 ,以宽度为基准算高度,适配就不会再有任何问题了。
到这里,不规则图形的布局已经完美的解决了,但是功能却有缺陷,因为三个按钮的位置是完全重叠在一起的,所以不管你点击哪个按钮,响应的永远是最上层的按钮(底下按钮的点击事件被覆盖了)。要怎么解决这个问题呢,很简单,只要让按钮的响应区域为图片可视范围即可(即是通过图片的透明度来判断按钮的点击能力),这里有两个思路:1、重写按钮的点击范围方法(- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event ),可以在这里画出按钮的响应区域,如圆形,三角形等等(用贝塞尔曲线实现),这种做法不需要判断图片透明度,相对来说比较简单,但是该方法仅适用于不规则图形是一类的情况(在这里就不适用,因为三个按钮的图形都不相同);2、首先获取图片的透明度,然后通过透明度来判断按钮的点击能力,该方法较为复杂,但是适用性广,适用于任何图形的按钮(原理现在还没看懂,先收藏,以后有时间再慢慢钻研)。
这个方法的实现可以是按钮的类别,或者自定义按钮都可以,看个人喜好,如果是通过类别实现,则不需要做任何事情,如果是通过自定义按钮实现,只需要将按钮关联起来即可。