不感兴趣难点在于气泡的定制,气泡上的箭头所指的控件是动态的。根据控件在屏幕不同的区域箭头所指朝上还是朝下也是动态的,所以 就没有用设计师提供的切图,这个切图也不符合要求。
下面直接上部分源码:
首先用贝赛尔曲线画箭头:
- (instancetype)initWithFrame:(CGRect)frame arrowDirection:(DislikeArrowDirection)arrowDirection {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
_arrowDirection = arrowDirection;
}
return self;
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGSize currentSize = rect.size;
UIColor *color = [UIColor whiteColor];
[color set];
UIBezierPath *aPath = [UIBezierPath bezierPath];
aPath.lineWidth = 1.0;
aPath.lineCapStyle = kCGLineCapRound;
switch (_arrowDirection) {
case DislikeArrowDirectionDown: {
[aPath moveToPoint:CGPointMake(0, currentSize.height)];
[aPath addQuadCurveToPoint:CGPointMake(currentSize.width, 0) controlPoint:CGPointMake(currentSize.width * kScale, currentSize.height * kScale)];
[aPath addQuadCurveToPoint:CGPointMake(currentSize.width, currentSize.height) controlPoint:CGPointMake(currentSize.width * kScale, currentSize.height * kScale)];
}
break;
case DislikeArrowDirectionUp: {
[aPath moveToPoint:CGPointMake(0, 0)];
[aPath addQuadCurveToPoint:CGPointMake(currentSize.width, currentSize.height) controlPoint:CGPointMake(currentSize.width * kScale, currentSize.height * (1 - kScale))];
[aPath addQuadCurveToPoint:CGPointMake(currentSize.width, 0) controlPoint:CGPointMake(currentSize.width * kScale, currentSize.height * (1 - kScale))];
}
break;
default:
break;
}
[aPath fill];
}
这里是列表文本定制不喜欢气泡弹出框
+ (instancetype)showFromView:(UIView *)aView items:(NSArray <DislikeItem *> *)items dislikeBlock:(DislikeViewBlock)dislikeBlock {
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
UIControl *backgroundControl = [UIControl new];
backgroundControl.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
backgroundControl.frame = keyWindow.bounds;
[backgroundControl addTarget:self action:@selector(hide:) forControlEvents:UIControlEventTouchUpInside];
[keyWindow addSubview:backgroundControl];
triggerRect = [aView convertRect:aView.bounds toView:keyWindow];
DislikeArrowDirection arrowDirection = DislikeArrowDirectionDown;
CGFloat dislikeViewHeight = kArrowHeight + DislikeViewHeaderHeight + ((items.count + 1) / 2) * (DislikeViewItemHeight + DislikeViewItemVerticalPadding) + (DislikeViewBottomAreaHeight - DislikeViewItemVerticalPadding) + 50+14;
if (CGRectGetMaxY(triggerRect) + dislikeViewHeight + 49+30 > ScreenH) {
arrowDirection = DislikeArrowDirectionUp;
}
CGRect frame = CGRectZero;
switch (arrowDirection) {
case DislikeArrowDirectionDown: {
frame = CGRectMake(10 + (ScreenW - 20) / 2., CGRectGetMaxY(triggerRect) - dislikeViewHeight / 2., ScreenW - 20, dislikeViewHeight);
}
break;
case DislikeArrowDirectionUp: {
frame = CGRectMake(10 + (ScreenW - 20) / 2., CGRectGetMinY(triggerRect) - dislikeViewHeight + dislikeViewHeight / 2., ScreenW - 20, dislikeViewHeight);
}
break;
default:
break;
}
TTVDislikeView *dislikeView = [[self alloc] initWithFrame:frame items:items direction:arrowDirection dislikeBlock:dislikeBlock];
[backgroundControl addSubview:dislikeView];
dislikeView.alpha = 0.0;
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:1.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
dislikeView.transform = CGAffineTransformMakeScale(1.0, 1.0);
dislikeView.alpha = 1.0;
backgroundControl.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.12];
} completion:^(BOOL finished) {
}];
return dislikeView;
}
+ (void)hide {
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
for (UIView *subview in keyWindow.subviews) {
if ([subview.subviews.lastObject isKindOfClass:[self class]]) {
[self hide:(UIControl *)subview];
break;
}
}
}
+ (void)hide:(UIControl *)control {
for (UIView *subview in control.subviews) {
if ([subview isKindOfClass:[TTVDislikeView class]]) {
TTVDislikeView *dislikeView = (TTVDislikeView *)subview;
[UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:1.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
dislikeView.transform = CGAffineTransformMakeScale(0.000001, 0.000001);;
dislikeView.alpha = 0.0;
control.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
} completion:^(BOOL finished) {
[control removeFromSuperview];
}];
return;
}
}
[control removeFromSuperview];
}
#pragma mark - getter & setter
- (NSMutableArray *)dislikeReasonArray {
if (!_dislikeReasonArray) {
_dislikeReasonArray = [NSMutableArray array];
}
return _dislikeReasonArray;
}
#pragma mark - life cycle
- (instancetype)initWithFrame:(CGRect)frame items:(NSArray <DislikeItem *> *)items direction:(DislikeArrowDirection)direction dislikeBlock:(DislikeViewBlock)dislikeBlock {
self = [super initWithFrame:frame];
if (self) {
self.dislikeBlock = dislikeBlock;
self.items = items;
CGRect arrowFrame = CGRectZero;
CGRect collectionFrame = CGRectZero;
switch (direction) {
case DislikeArrowDirectionDown: {
self.layer.anchorPoint = CGPointMake(1.0, 0);
arrowFrame = CGRectMake(triggerRect.origin.x-10, 1, kArrowWidth, kArrowHeight);
collectionFrame = CGRectMake(0, kArrowHeight, frame.size.width, frame.size.height - kArrowHeight);
}
break;
case DislikeArrowDirectionUp: {
self.layer.anchorPoint = CGPointMake(1.0, 1.0);
arrowFrame = CGRectMake(triggerRect.origin.x-10 , frame.size.height - kArrowHeight, kArrowWidth, kArrowHeight);
collectionFrame = CGRectMake(0, 0, frame.size.width, frame.size.height - kArrowHeight);
}
break;
default:
break;
}
self.transform = CGAffineTransformMakeScale(0.0001, 0.0001);
TTVDisliekArrow *arrowView = [TTVDisliekArrow arrowViewWithFrame:arrowFrame arrowDirection:direction];
[self addSubview:arrowView];
[self buildReasonViewWithFrame:collectionFrame];
}
return self;
}
- (void)buildReasonViewWithFrame:(CGRect)frame {
UIView *view = [[UIView alloc] initWithFrame:frame];
view.backgroundColor = [UIColor whiteColor];
view.layer.cornerRadius = 10.0;
__block typeof(UIButton *) lastButton = nil;
for (NSInteger idx = 0; idx < self.items.count; idx++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = self.items[idx].dislikeId + kBaseTag;
button.backgroundColor = [UIColor whiteColor];
button.layer.cornerRadius = 5.0;
button.layer.borderWidth = 1.0;
button.layer.borderColor = [UIColor ttv_B1].CGColor;
button.layer.masksToBounds = YES;
button.titleLabel.font = [UIFont systemFontOfSize:14];
button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
[button setTitle:[NSString stringWithFormat:@" %@ ", self.items[idx].dislikeText] forState:UIControlStateNormal];
[button setTitleColor:[UIColor ttv_T2] forState:UIControlStateNormal];
[button setTitleColor:[UIColor ttv_A3] forState:UIControlStateSelected];
[button addTarget:self action:@selector(onClickItemButton:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:button];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(DislikeViewItemHeight);
if (lastButton) {
make.top.equalTo(lastButton.mas_bottom).offset(DislikeViewItemVerticalPadding);
} else {
make.top.equalTo(view).offset(50);
}
if (idx % 2) {
make.left.equalTo(view.mas_centerX).offset(15);
make.right.mas_equalTo(view.mas_right).offset(-20);
lastButton = button;
} else {
make.left.mas_equalTo(20);
make.right.mas_equalTo(view.mas_right).offset(-frame.size.width/2.0-7.5);
}
}];
if (idx ==self.items.count -1) {
self.sepatatorLine = [UIView new];
self.sepatatorLine.backgroundColor = [UIColor ttv_B1];
[view addSubview:self.sepatatorLine];
[self.sepatatorLine mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(button.mas_bottom).offset(15);
make.left.offset(0);
make.right.offset(0);
make.height.mas_equalTo(0.5);
}];
}
}
self.titleLabel = ({
UILabel *label = [UILabel new];
label.text = @"可选理由,精准屏蔽(可多选)";
label.font = [UIFont systemFontOfSize:16];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = important_gray_color;
[view addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(15);
make.centerX.equalTo(view.mas_centerX);
}];
label;
});
self.dislikeButton = ({
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.titleLabel.font = [UIFont systemFontOfSize:16];
[button setTitle:@"不感兴趣" forState:UIControlStateNormal];
[button setTitle:@"确定" forState:UIControlStateSelected];
[button setTitleColor:[UIColor ttv_A3] forState:UIControlStateNormal];
[button setTitleColor:[UIColor ttv_A3] forState:UIControlStateSelected];
[button addTarget:self action:@selector(onClickDislikeButton:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:button];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(view);
make.top.mas_equalTo(self.sepatatorLine.mas_bottom).offset(15);
make.size.mas_equalTo(CGSizeMake(80, 32));
}];
button;
});
self.reasonView = view;
[self addSubview:view];
}