苹果的自动布局这套框架的确是好.
但是好的同时, 也给开发者带来了不小的挑战.
刚开始使用的时候, 还不如 Android 的 xml 布局好用, 虽然苹果多了可以拖拽的功能.
当你熟练使用后, 你会发现, 还真 TM 有那么回事.
之前有朋友私信问我, 平时在 iOS 开发中怎么书写 UI 布局的.
这里统一给出答复:
- 优先 AutoLayout.
- 其次 Masonry.
- 纯代码打造.
今天的任务
- 在 XIB 中给 UIView 添加几个 CALayer 相关的属性
- 在 XIB 中给 UIImageView 设置圆角
老规矩, 先看一下效果图.
在 CALayer.h 里面, 可以看到 Border 和 shadow 的属性定义.
/* The width of the layer's border, inset from the layer bounds. The
* border is composited above the layer's content and sublayers and
* includes the effects of the `cornerRadius' property. Defaults to
* zero. Animatable. */
@property CGFloat borderWidth;
/* The color of the layer's border. Defaults to opaque black. Colors
* created from tiled patterns are supported. Animatable. */
@property(nullable) CGColorRef borderColor;
/** Shadow properties. **/
/* The color of the shadow. Defaults to opaque black. Colors created
* from patterns are currently NOT supported. Animatable. */
@property(nullable) CGColorRef shadowColor;
/* The opacity of the shadow. Defaults to 0. Specifying a value outside the
* [0,1] range will give undefined results. Animatable. */
@property float shadowOpacity;
/* The shadow offset. Defaults to (0, -3). Animatable. */
@property CGSize shadowOffset;
/* The blur radius used to create the shadow. Defaults to 3. Animatable. */
@property CGFloat shadowRadius;
/* When non-null this path defines the outline used to construct the
* layer's shadow instead of using the layer's composited alpha
* channel. The path is rendered using the non-zero winding rule.
* Specifying the path explicitly using this property will usually
* improve rendering performance, as will sharing the same path
* reference across multiple layers. Upon assignment the path is copied.
* Defaults to null. Animatable. */
@property(nullable) CGPathRef shadowPath;
那么, 我们在 xib 中设置跟这两个相关的属性, 设置如下:
如果你的设置也像我一样, 那么 Run 一下吧!
我保证你看不到上面的效果(没有 Border 和 shadow 效果).
这个世界的牛人很多, 他们给出的解决方案就是重写 boderColor 和 shadowColor 这两个 property.
具体办法就是, 写个 CALayer 的 Category.
CALayer+MZXibConfig.h
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer (MZXibConfig)
- (void)setBorderColorXib:(UIColor *)color;
- (UIColor *)borderColorXib;
- (void)setShadowColorXib:(UIColor *)color;
- (UIColor *)shadowColorXib;
@end
CALayer+MZXibConfig.m
#import "CALayer+MZXibConfig.h"
@implementation CALayer (MZXibConfig)
// MARK: 设置 BorderColor
- (void)setBorderColorXib:(UIColor *)color
{
self.borderColor = color.CGColor;
}
- (UIColor *)borderColorXib
{
return [UIColor colorWithCGColor:self.borderColor];
}
// MARK: 设置 ShadowColor
- (void)setShadowColorXib:(UIColor *)color
{
self.shadowColor = color.CGColor;
}
- (UIColor *)shadowColorXib
{
return [UIColor colorWithCGColor:self.shadowColor];
}
@end
修改一下 xib 中设置的属性.
注意:
borderColor 改为了 borderColorXib
shadowColor 改为了 shadowColorXib
再 Run 一下, 你就能看到效果了.
这里还要提醒各位看官
shadowOpacity 一定要设置非0的值, 该值默认是0, 否则看不到 shadow 效果的. 别问我怎么知道, 看CALayer.h吧!
至于 UIImageView 设置圆角, 很简单了.
当你 Run 后,你发现然并卵!
我没有耍你, 是我们太年轻了.
好吧, 需要加个属性.
搞定!
写到这里, 本想收当睡觉, 但是怎么想那个 Category 的代码就是不美, 于是修改一下.
细心的读者可以发现, 上面那个 Category 头文件里面就是 set 和 get 的声明.
那我们是否可以简化一下代码?
使用强大的 property 属性.
那么, 问题来了
Category 中是不可以写成员变量的
那我们怎么可以这么做呢?
答案:
property 声明的属性, 编译器默认会声明set 和 get 方法.所以声明的不是成员变量, 而是成员方法.
使用 property 来声明CALayer+MZXibConfig.h
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer (MZXibConfig)
@property (nonatomic, weak) UIColor *borderColorXib;
@property (nonatomic, weak) UIColor *shadowColorXib;
@end
代码已经放在 github