Files
IQKeyboardManager/Demo/Objective_C_Demo/YYText/YYTextMagnifier.m
hackiftekhar 6becc06ca3 - Converted Obj-C demo with Autolayout
- Enhanced demo project and added various examples demonstrating almost all properties of library.
- Enhanced library Settings Controller.
- Moved some contents of README.md file to other files.
2016-05-22 23:13:04 +05:30

356 lines
12 KiB
Objective-C
Executable File

//
// YYTextMagnifier.m
// YYText <https://github.com/ibireme/YYText>
//
// Created by ibireme on 15/2/25.
// 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 "YYTextMagnifier.h"
#import "YYTextUtilities.h"
#define kCaptureDisableFadeTime 0.1
@interface _YYTextMagnifierCaret : YYTextMagnifier {
UIImageView *_contentView;
UIImageView *_coverView;
}
@end
@implementation _YYTextMagnifierCaret
#define kMultiple 1.2
#define kDiameter 113.0
#define kPadding 7.0
#define kSize CGSizeMake(kDiameter + kPadding * 2, kDiameter + kPadding * 2)
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
_contentView = [UIImageView new];
_contentView.frame = CGRectMake(kPadding, kPadding, kDiameter, kDiameter);
_contentView.layer.cornerRadius = kDiameter / 2;
_contentView.clipsToBounds = YES;
[self addSubview:_contentView];
_coverView = [UIImageView new];
_coverView.frame = (CGRect){.origin = CGPointZero, .size = kSize};
_coverView.image = [self.class coverImage];
[self addSubview:_coverView];
return self;
}
- (instancetype)init {
self = [self initWithFrame:CGRectZero];
self.frame = (CGRect){.size = [self sizeThatFits:CGSizeZero]};
return self;
}
- (YYTextMagnifierType)type {
return YYTextMagnifierTypeCaret;
}
- (CGSize)sizeThatFits:(CGSize)size {
return kSize;
}
- (void)setSnapshot:(UIImage *)snapshot {
if (self.captureFadeAnimation) {
[_contentView.layer removeAnimationForKey:@"contents"];
CABasicAnimation *animation = [CABasicAnimation animation];
animation.duration = kCaptureDisableFadeTime;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[_contentView.layer addAnimation:animation forKey:@"contents"];
}
_contentView.image = snapshot;
}
- (UIImage *)snapshot {
return _contentView.image;
}
- (CGSize)snapshotSize {
CGFloat length = floor(kDiameter / 1.2);
return CGSizeMake(length, length);
}
- (CGSize)fitSize {
return [self sizeThatFits:CGSizeZero];
}
+ (UIImage *)coverImage {
static UIImage *image;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CGSize size = kSize;
CGRect rect = (CGRect) {.size = size, .origin = CGPointZero};
rect = CGRectInset(rect, kPadding, kPadding);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef boxPath = CGPathCreateWithRect(CGRectMake(0, 0, size.width, size.height), NULL);
CGPathRef fillPath = CGPathCreateWithEllipseInRect(rect, NULL);
CGPathRef strokePath = CGPathCreateWithEllipseInRect(YYTextCGRectPixelHalf(rect), NULL);
// inner shadow
CGContextSaveGState(context); {
CGFloat blurRadius = 25;
CGSize offset = CGSizeMake(0, 15);
CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.16].CGColor;
CGColorRef opaqueShadowColor = CGColorCreateCopyWithAlpha(shadowColor, 1.0);
CGContextAddPath(context, fillPath);
CGContextClip(context);
CGContextSetAlpha(context, CGColorGetAlpha(shadowColor));
CGContextBeginTransparencyLayer(context, NULL); {
CGContextSetShadowWithColor(context, offset, blurRadius, opaqueShadowColor);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextSetFillColorWithColor(context, opaqueShadowColor);
CGContextAddPath(context, fillPath);
CGContextFillPath(context);
} CGContextEndTransparencyLayer(context);
CGColorRelease(opaqueShadowColor);
} CGContextRestoreGState(context);
// outer shadow
CGContextSaveGState(context); {
CGContextAddPath(context, boxPath);
CGContextAddPath(context, fillPath);
CGContextEOClip(context);
CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.32].CGColor;
CGContextSetShadowWithColor(context, CGSizeMake(0, 1.5), 3, shadowColor);
CGContextBeginTransparencyLayer(context, NULL); {
CGContextAddPath(context, fillPath);
[[UIColor colorWithWhite:0.7 alpha:1.000] setFill];
CGContextFillPath(context);
} CGContextEndTransparencyLayer(context);
} CGContextRestoreGState(context);
// stroke
CGContextSaveGState(context); {
CGContextAddPath(context, strokePath);
[[UIColor colorWithWhite:0.6 alpha:1] setStroke];
CGContextSetLineWidth(context, YYTextCGFloatFromPixel(1));
CGContextStrokePath(context);
} CGContextRestoreGState(context);
CFRelease(boxPath);
CFRelease(fillPath);
CFRelease(strokePath);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
});
return image;
}
#undef kMultiple
#undef kDiameter
#undef kPadding
#undef kSize
@end
@interface _YYTextMagnifierRanged : YYTextMagnifier {
UIImageView *_contentView;
UIImageView *_coverView;
}
@end
@implementation _YYTextMagnifierRanged
#define kMultiple 1.2
#define kSize CGSizeMake(141, 60)
#define kPadding YYTextCGFloatPixelHalf(6.0)
#define kRadius 6.0
#define kHeight 32.0
#define kArrow 14.0
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
_contentView = [UIImageView new];
_contentView.frame = CGRectMake(kPadding, kPadding, kSize.width - 2 * kPadding, kHeight);
_contentView.layer.cornerRadius = kRadius;
_contentView.clipsToBounds = YES;
[self addSubview:_contentView];
_coverView = [UIImageView new];
_coverView.frame = (CGRect){.origin = CGPointZero, .size = kSize};
_coverView.image = [self.class coverImage];
[self addSubview:_coverView];
self.layer.anchorPoint = CGPointMake(0.5, 1.2);
return self;
}
- (instancetype)init {
self = [self initWithFrame:CGRectZero];
self.frame = (CGRect){.size = [self sizeThatFits:CGSizeZero]};
return self;
}
- (YYTextMagnifierType)type {
return YYTextMagnifierTypeRanged;
}
- (CGSize)sizeThatFits:(CGSize)size {
return kSize;
}
- (void)setSnapshot:(UIImage *)snapshot {
if (self.captureFadeAnimation) {
[_contentView.layer removeAnimationForKey:@"contents"];
CABasicAnimation *animation = [CABasicAnimation animation];
animation.duration = kCaptureDisableFadeTime;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[_contentView.layer addAnimation:animation forKey:@"contents"];
}
_contentView.image = snapshot;
}
- (UIImage *)snapshot {
return _contentView.image;
}
- (CGSize)snapshotSize {
CGSize size;
size.width = floor((kSize.width - 2 * kPadding) / kMultiple);
size.height = floor(kHeight / kMultiple);
return size;
}
- (CGSize)fitSize {
return [self sizeThatFits:CGSizeZero];
}
+ (UIImage *)coverImage {
static UIImage *image;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CGSize size = kSize;
CGRect rect = (CGRect) {.size = size, .origin = CGPointZero};
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef boxPath = CGPathCreateWithRect(rect, NULL);
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, kPadding + kRadius, kPadding);
CGPathAddLineToPoint(path, NULL, size.width - kPadding - kRadius, kPadding);
CGPathAddQuadCurveToPoint(path, NULL, size.width - kPadding, kPadding, size.width - kPadding, kPadding + kRadius);
CGPathAddLineToPoint(path, NULL, size.width - kPadding, kHeight);
CGPathAddCurveToPoint(path, NULL, size.width - kPadding, kPadding + kHeight, size.width - kPadding - kRadius, kPadding + kHeight, size.width - kPadding - kRadius, kPadding + kHeight);
CGPathAddLineToPoint(path, NULL, size.width / 2 + kArrow, kPadding + kHeight);
CGPathAddLineToPoint(path, NULL, size.width / 2, kPadding + kHeight + kArrow);
CGPathAddLineToPoint(path, NULL, size.width / 2 - kArrow, kPadding + kHeight);
CGPathAddLineToPoint(path, NULL, kPadding + kRadius, kPadding + kHeight);
CGPathAddQuadCurveToPoint(path, NULL, kPadding, kPadding + kHeight, kPadding, kHeight);
CGPathAddLineToPoint(path, NULL, kPadding, kPadding + kRadius);
CGPathAddQuadCurveToPoint(path, NULL, kPadding, kPadding, kPadding + kRadius, kPadding);
CGPathCloseSubpath(path);
CGMutablePathRef arrowPath = CGPathCreateMutable();
CGPathMoveToPoint(arrowPath, NULL, size.width / 2 - kArrow, YYTextCGFloatPixelFloor(kPadding) + kHeight);
CGPathAddLineToPoint(arrowPath, NULL, size.width / 2 + kArrow, YYTextCGFloatPixelFloor(kPadding) + kHeight);
CGPathAddLineToPoint(arrowPath, NULL, size.width / 2, kPadding + kHeight + kArrow);
CGPathCloseSubpath(arrowPath);
// inner shadow
CGContextSaveGState(context); {
CGFloat blurRadius = 25;
CGSize offset = CGSizeMake(0, 15);
CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.16].CGColor;
CGColorRef opaqueShadowColor = CGColorCreateCopyWithAlpha(shadowColor, 1.0);
CGContextAddPath(context, path);
CGContextClip(context);
CGContextSetAlpha(context, CGColorGetAlpha(shadowColor));
CGContextBeginTransparencyLayer(context, NULL); {
CGContextSetShadowWithColor(context, offset, blurRadius, opaqueShadowColor);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextSetFillColorWithColor(context, opaqueShadowColor);
CGContextAddPath(context, path);
CGContextFillPath(context);
} CGContextEndTransparencyLayer(context);
CGColorRelease(opaqueShadowColor);
} CGContextRestoreGState(context);
// outer shadow
CGContextSaveGState(context); {
CGContextAddPath(context, boxPath);
CGContextAddPath(context, path);
CGContextEOClip(context);
CGColorRef shadowColor = [UIColor colorWithWhite:0 alpha:0.32].CGColor;
CGContextSetShadowWithColor(context, CGSizeMake(0, 1.5), 3, shadowColor);
CGContextBeginTransparencyLayer(context, NULL); {
CGContextAddPath(context, path);
[[UIColor colorWithWhite:0.7 alpha:1.000] setFill];
CGContextFillPath(context);
} CGContextEndTransparencyLayer(context);
} CGContextRestoreGState(context);
// arrow
CGContextSaveGState(context); {
CGContextAddPath(context, arrowPath);
[[UIColor colorWithWhite:1 alpha:0.95] set];
CGContextFillPath(context);
} CGContextRestoreGState(context);
// stroke
CGContextSaveGState(context); {
CGContextAddPath(context, path);
[[UIColor colorWithWhite:0.6 alpha:1] setStroke];
CGContextSetLineWidth(context, YYTextCGFloatFromPixel(1));
CGContextStrokePath(context);
} CGContextRestoreGState(context);
CFRelease(boxPath);
CFRelease(path);
CFRelease(arrowPath);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
});
return image;
}
#undef kMultiple
#undef kSize
#undef kPadding
#undef kRadius
#undef kHeight
#undef kArrow
@end
@implementation YYTextMagnifier
+ (id)magnifierWithType:(YYTextMagnifierType)type {
switch (type) {
case YYTextMagnifierTypeCaret :return [_YYTextMagnifierCaret new];
case YYTextMagnifierTypeRanged :return [_YYTextMagnifierRanged new];
}
return nil;
}
- (id)initWithFrame:(CGRect)frame {
// class cluster
if ([self isMemberOfClass:[YYTextMagnifier class]]) {
@throw [NSException exceptionWithName:NSStringFromClass([self class]) reason:@"Attempting to instantiate an abstract class. Use a concrete subclass instead." userInfo:nil];
return nil;
}
self = [super initWithFrame:frame];
return self;
}
@end