这是《iOS Auto Layout开发秘籍》中的一个例子。这里使用Masonry改写了一下。
实现的效果如下:
代码如下:
#import "LockControl.h"
#import "Masonry.h"
@implementation LockControl
{
UIImageView *lockView;
UIImageView *trackView;
UIImageView *thumbView;
}
#pragma mark - Layout
- (void) layoutConstraints {
// Self
[self mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(256, 256)).priority(UILayoutPriorityRequired);
}];
// Lock
[lockView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self).centerOffset(CGPointMake(0, -38)).priority(UILayoutPriorityRequired);
}];
// Track
[trackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self).centerOffset(CGPointMake(0, 80)).priority(UILayoutPriorityRequired);
}];
// Thumb
[thumbView mas_updateConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(trackView.mas_centerY).priority(UILayoutPriorityRequired);
// 约束的关键!!!左边是大于等于,右边是小于等于
make.left.mas_greaterThanOrEqualTo(12).priorityHigh();
make.right.mas_lessThanOrEqualTo(-12).priorityHigh();
make.leading.mas_equalTo(trackView).priorityMedium();
}];
}
- (void) buildView {
self.translatesAutoresizingMaskIntoConstraints = NO;
self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3f];
self.layer.cornerRadius = 32;
self.layer.masksToBounds = YES;
lockView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"lockClosed"]];
[self addSubview:lockView];
trackView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"track"]];
hug(trackView, UILayoutPriorityRequired);
[self addSubview:trackView];
thumbView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"thumb"]];
[trackView addSubview:thumbView];
[self layoutConstraints];
}
#pragma mark - Creation
- (instancetype) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self == nil) {
return self;
}
self.backgroundColor = [UIColor clearColor];
[self buildView];
return self;
}
- (instancetype) init {
return [self initWithFrame:CGRectZero];
}
#pragma mark - UIControl
- (BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
// 测试开始时候的touch
CGPoint touchPoint = [touch locationInView:self];
CGRect largeTrack = CGRectInset(trackView.frame, -20.0f, -20.0f);
if (!CGRectContainsPoint(largeTrack, touchPoint)) {
return NO;
}
touchPoint = [touch locationInView:trackView];
CGRect largeThumb = CGRectInset(thumbView.frame, -20.0f, -20.0f);
if (!CGRectContainsPoint(largeThumb, touchPoint)) {
return NO;
}
// 开始跟踪
[self sendActionsForControlEvents:UIControlEventTouchDown];
return YES;
}
- (BOOL) continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
// 更新滑动的位置
touchPoint = [touch locationInView:trackView];
[UIView animateWithDuration:0.1f animations:^{
[thumbView mas_updateConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(trackView).mas_offset(touchPoint.x).priorityMedium();
}];
}];
return YES;
}
- (void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:trackView];
if (touchPoint.x > trackView.frame.size.width * 0.75f) {
// 默认为解锁
self.userInteractionEnabled = NO;
[self sendActionsForControlEvents:UIControlEventValueChanged];
// 自我移除
[UIView animateWithDuration:0.5f animations:^{
self.alpha = 0.0f;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
} else {
// 约束的动画
[UIView animateWithDuration:0.2f animations:^{
[thumbView mas_updateConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(trackView).priorityMedium();
}];
// 动画的关键!!!
[trackView layoutIfNeeded];
}];
}
if (CGRectContainsPoint(trackView.bounds, touchPoint)) {
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
} else {
[self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
}
- (void) cancelTrackingWithEvent:(UIEvent *)event {
[self sendActionsForControlEvents:UIControlEventTouchCancel];
[UIView animateWithDuration:0.2 animations:^{
[thumbView mas_updateConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(trackView).priorityMedium();
}];
[trackView layoutIfNeeded];
}];
}
#pragma mark - Helper
void hug(UIView *view, UILayoutPriority priority) {
hug_H(view, priority);
hug_V(view, priority);
}
void hug_H(UIView *view, UILayoutPriority priority){
[view setContentHuggingPriority:(priority) forAxis:UILayoutConstraintAxisHorizontal];
}
void hug_V(UIView *view, UILayoutPriority priority) {
[view setContentHuggingPriority:priority forAxis:UILayoutConstraintAxisVertical];
}
@end
素材:
-
lock
-
thumb
-
track