// // YYTextContainerView.m // YYKit // // Created by ibireme on 15/4/21. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import "YYTextContainerView.h" @implementation YYTextContainerView { BOOL _attachmentChanged; NSMutableArray *_attachmentViews; NSMutableArray *_attachmentLayers; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (!self) return nil; self.backgroundColor = [UIColor clearColor]; _attachmentViews = [NSMutableArray array]; _attachmentLayers = [NSMutableArray array]; return self; } - (void)setDebugOption:(YYTextDebugOption *)debugOption { BOOL needDraw = _debugOption.needDrawDebug; _debugOption = debugOption.copy; if (_debugOption.needDrawDebug != needDraw) { [self setNeedsDisplay]; } } - (void)setTextVerticalAlignment:(YYTextVerticalAlignment)textVerticalAlignment { if (_textVerticalAlignment == textVerticalAlignment) return; _textVerticalAlignment = textVerticalAlignment; [self setNeedsDisplay]; } - (void)setContentsFadeDuration:(NSTimeInterval)contentsFadeDuration { if (_contentsFadeDuration == contentsFadeDuration) return; _contentsFadeDuration = contentsFadeDuration; if (contentsFadeDuration <= 0) { [self.layer removeAnimationForKey:@"contents"]; } } - (void)setLayout:(YYTextLayout *)layout { if (_layout == layout) return; _layout = layout; _attachmentChanged = YES; [self setNeedsDisplay]; } - (void)setLayout:(YYTextLayout *)layout withFadeDuration:(NSTimeInterval)fadeDuration { self.contentsFadeDuration = fadeDuration; self.layout = layout; } - (void)drawRect:(CGRect)rect { // fade content [self.layer removeAnimationForKey:@"contents"]; if (_contentsFadeDuration > 0) { CATransition *transition = [CATransition animation]; transition.duration = _contentsFadeDuration; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; transition.type = kCATransitionFade; [self.layer addAnimation:transition forKey:@"contents"]; } // update attachment if (_attachmentChanged) { for (UIView *view in _attachmentViews) { if (view.superview == self) [view removeFromSuperview]; } for (CALayer *layer in _attachmentLayers) { if (layer.superlayer == self.layer) [layer removeFromSuperlayer]; } [_attachmentViews removeAllObjects]; [_attachmentLayers removeAllObjects]; } // draw layout CGSize boundingSize = _layout.textBoundingSize; CGPoint point = CGPointZero; if (_textVerticalAlignment == YYTextVerticalAlignmentCenter) { if (_layout.container.isVerticalForm) { point.x = -(self.bounds.size.width - boundingSize.width) * 0.5; } else { point.y = (self.bounds.size.height - boundingSize.height) * 0.5; } } else if (_textVerticalAlignment == YYTextVerticalAlignmentBottom) { if (_layout.container.isVerticalForm) { point.x = -(self.bounds.size.width - boundingSize.width); } else { point.y = (self.bounds.size.height - boundingSize.height); } } [_layout drawInContext:UIGraphicsGetCurrentContext() size:self.bounds.size point:point view:self layer:self.layer debug:_debugOption cancel:nil]; // update attachment if (_attachmentChanged) { _attachmentChanged = NO; for (YYTextAttachment *a in _layout.attachments) { if ([a.content isKindOfClass:[UIView class]]) [_attachmentViews addObject:a.content]; if ([a.content isKindOfClass:[CALayer class]]) [_attachmentLayers addObject:a.content]; } } } - (void)setFrame:(CGRect)frame { CGSize oldSize = self.bounds.size; [super setFrame:frame]; if (!CGSizeEqualToSize(oldSize, self.bounds.size)) { [self setNeedsLayout]; } } - (void)setBounds:(CGRect)bounds { CGSize oldSize = self.bounds.size; [super setBounds:bounds]; if (!CGSizeEqualToSize(oldSize, self.bounds.size)) { [self setNeedsLayout]; } } #pragma mark - UIResponder forward - (BOOL)canBecomeFirstResponder { return YES; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return [self.hostView canPerformAction:action withSender:sender]; } - (id)forwardingTargetForSelector:(SEL)aSelector { return self.hostView; } @end