#import "UIViewAdditions.h" #import #import "UIImage+Gradient.h" #define FIXSIZE_IP6(n) lrintf((n * [UIScreen mainScreen].bounds.size.width / 375.0f)) CGRect fixRect(CGFloat x, CGFloat y, CGFloat width, CGFloat height) { CGRect rect = CGRectMake(FIXSIZE_IP6(x), FIXSIZE_IP6(y), FIXSIZE_IP6(width), FIXSIZE_IP6(height)); return rect; } CGPoint fixPoint(CGFloat x, CGFloat y) { CGPoint point = CGPointMake(FIXSIZE_IP6(x), FIXSIZE_IP6(y)); return point; } CGSize fixSize(CGFloat width,CGFloat height) { CGSize size = CGSizeMake(FIXSIZE_IP6(width), FIXSIZE_IP6(height)); return size; } /////////////////////////////////////////////////////////////////////////////////////////////////// // This code for synthesizing touch events is derived from: // http://cocoawithlove.com/2008/10/synthesizing-touch-event-on-iphone.html @interface GSEventFake : NSObject { @public int ignored1[5]; float x; float y; int ignored2[24]; } @end @implementation GSEventFake @end @interface UIEventFake : NSObject { @public CFTypeRef _event; NSTimeInterval _timestamp; NSMutableSet* _touches; CFMutableDictionaryRef _keyedTouches; } @end @implementation UIEventFake @end @interface UITouch (TTCategory) - (id)initInView:(UIView *)view location:(CGPoint)location; - (void)changeToPhase:(UITouchPhase)phase; @end @implementation UITouch (TTCategory) - (id)initInView:(UIView *)view location:(CGPoint)location { if (self = [super init]) { } return self; } - (void)changeToPhase:(UITouchPhase)phase { } @end @implementation UIEvent (TTCategory) - (id)initWithTouch:(UITouch *)touch { if (self = [super init]) { UIEventFake *selfFake = (UIEventFake*)self; selfFake->_touches = [NSMutableSet setWithObject:touch]; selfFake->_timestamp = [NSDate timeIntervalSinceReferenceDate]; CGPoint location = [touch locationInView:touch.window]; GSEventFake* fakeGSEvent = [[GSEventFake alloc] init]; fakeGSEvent->x = location.x; fakeGSEvent->y = location.y; selfFake->_event = (__bridge CFTypeRef)(fakeGSEvent); CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(dict, (__bridge const void *)(touch.view), (__bridge const void *)(selfFake->_touches)); CFDictionaryAddValue(dict, (__bridge const void *)(touch.window), (__bridge const void *)(selfFake->_touches)); selfFake->_keyedTouches = dict; } return self; } @end static NSString *const kClickActionKey = @"kClickActionKey"; static NSString *const kLongPressActionKey = @"kLongPressActionKey"; @implementation UIView (TTCategory) - (void)setClickAction:(void(^)(void))action { objc_setAssociatedObject(self, (__bridge const void * _Nonnull)(kClickActionKey), action, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (void)setLongPressAction:(void(^)(void))action { objc_setAssociatedObject(self, (__bridge const void * _Nonnull)(kLongPressActionKey), action, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (void(^)(void))longPressAction { return objc_getAssociatedObject(self, (__bridge const void * _Nonnull)(kLongPressActionKey)); } - (void(^)(void))clickAction { return objc_getAssociatedObject(self, (__bridge const void * _Nonnull)(kClickActionKey)); } - (void)mt_AlignCenterXToSuperView { if (self.superview) { self.centerX = self.superview.width * 0.5; } else { #if DEBUG NSAssert(NO , @"call before added to superview"); #endif } } - (void)mt_AlignCenterYToSuperView { if (self.superview) { self.centerY = self.superview.height * 0.5; } else { #if DEBUG NSAssert(NO , @"call before added to superview"); #endif } } - (void)mt_AlignCenterToSuperView { if (self.superview) { self.center = CGPointMake(self.superview.width * 0.5, self.superview.height * 0.5); } else { #if DEBUG NSAssert(NO , @"call before added to superview"); #endif } } - (CGFloat)left { return self.frame.origin.x; } - (void)setLeft:(CGFloat)x { CGRect frame = self.frame; frame.origin.x = x; self.frame = frame; } - (CGFloat)top { return self.frame.origin.y; } - (void)setTop:(CGFloat)y { CGRect frame = self.frame; frame.origin.y = y; self.frame = frame; } - (CGFloat)right { return self.frame.origin.x + self.frame.size.width; } - (void)setRight:(CGFloat)right { CGRect frame = self.frame; frame.origin.x = right - frame.size.width; self.frame = frame; } - (CGFloat)bottom { return self.frame.origin.y + self.frame.size.height; } - (void)setBottom:(CGFloat)bottom { CGRect frame = self.frame; frame.origin.y = bottom - frame.size.height; self.frame = frame; } - (CGFloat)centerX { return self.center.x; } - (void)setCenterX:(CGFloat)centerX { self.center = CGPointMake(centerX, self.center.y); } - (CGFloat)centerY { return self.center.y; } - (void)setCenterY:(CGFloat)centerY { self.center = CGPointMake(self.center.x, centerY); } - (CGFloat)width { return self.frame.size.width; } - (void)setWidth:(CGFloat)width { CGRect frame = self.frame; frame.size.width = width; self.frame = frame; } - (CGFloat)height { return self.frame.size.height; } - (void)setHeight:(CGFloat)height { CGRect frame = self.frame; frame.size.height = height; self.frame = frame; } - (CGFloat)screenX { CGFloat x = 0; for (UIView* view = self; view; view = view.superview) { x += view.left; } return x; } - (CGFloat)screenY { CGFloat y = 0; for (UIView* view = self; view; view = view.superview) { y += view.top; } return y; } - (CGFloat)screenViewX { CGFloat x = 0; for (UIView* view = self; view; view = view.superview) { x += view.left; if ([view isKindOfClass:[UIScrollView class]]) { UIScrollView* scrollView = (UIScrollView*)view; x -= scrollView.contentOffset.x; } } return x; } - (CGFloat)screenViewY { CGFloat y = 0; for (UIView* view = self; view; view = view.superview) { y += view.top; if ([view isKindOfClass:[UIScrollView class]]) { UIScrollView* scrollView = (UIScrollView*)view; y -= scrollView.contentOffset.y; } } return y; } - (CGRect)screenFrame { return CGRectMake(self.screenViewX, self.screenViewY, self.width, self.height); } - (CGPoint)offsetFromView:(UIView*)otherView { CGFloat x = 0, y = 0; for (UIView* view = self; view && view != otherView; view = view.superview) { x += view.left; y += view.top; } return CGPointMake(x, y); } - (void)setX:(CGFloat)x { CGRect frame = self.frame; frame.origin.x = x; self.frame = frame; } - (CGFloat)x { return self.frame.origin.x; } - (void)setY:(CGFloat)y { CGRect frame = self.frame; frame.origin.y = y; self.frame = frame; } - (CGFloat)y { return self.frame.origin.y; } - (void)setSize:(CGSize)size { CGRect frame = self.frame; frame.size = size; self.frame = frame; } - (CGSize)size { return self.frame.size; } - (void)setOrigin:(CGPoint)origin { CGRect frame = self.frame; frame.origin = origin; self.frame = frame; } - (CGPoint)origin { return self.frame.origin; } - (CGFloat)bottomFromSuperView{ return self.superview.height - self.y - self.height; } - (void)addTapWithAction:(void (^)(void))tapAction { [self addTapGestureTarget:self action:@selector(handleTap)]; [self setClickAction:tapAction]; } - (void)addLongPressWithAction:(void (^)(void))longPressAction { UIGestureRecognizer *gr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; [self addGestureRecognizer:gr]; [self setLongPressAction:longPressAction]; } - (void)handleLongPress:(UILongPressGestureRecognizer *)gr { if (gr.state == UIGestureRecognizerStateBegan) { if ([self longPressAction]) { [self longPressAction](); } } } - (void)handleTap { static NSTimeInterval lastActionTime = 0; NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970]; if (currentTime - lastActionTime < 0.5) { // 0.5 快速点击 return; } if ([self clickAction]) { lastActionTime = currentTime; [self clickAction](); } } - (void)setBackgroundGradientColorWithBeginColorHex:(int)beginColorHex endColorHex:(int)endColorHex gradientType:(GradientColorType)gradientType { if ([self isKindOfClass:[UIButton class]]) { UIImage *bgImage = [[UIImage alloc] createImageWithSize:self.size gradientColors:@[COLOR_WITH_RGB(beginColorHex), COLOR_WITH_RGB(endColorHex)] percentage:@[@(0), @(1)] gradientType:(GradientType)gradientType]; UIButton *btn = (UIButton *)self; [btn setBackgroundImage:bgImage forState:UIControlStateNormal]; return; } CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = self.layer.bounds; CGPoint start; CGPoint end; switch (gradientType) { case GradientColorTypeFromTopToBottom: start = CGPointMake(0.0, 0.0); end = CGPointMake(0.0, 1.0); break; case GradientColorTypeFromLeftToRight: start = CGPointMake(0.0, 0.0); end = CGPointMake(1.0, 0.0); break; case GradientColorTypeFromLeftTopToRightBottom: start = CGPointMake(0.0, 0.0); end = CGPointMake(1.0, 1.0); break; case GradientColorTypeFromLeftBottomToRightTop: start = CGPointMake(0.0, 1.0); end = CGPointMake(1.0, 0.0); break; default: break; } // 创建渐变色数组,需要转换为CGColor颜色 gradientLayer.colors = @[(__bridge id)COLOR_WITH_RGB(beginColorHex).CGColor,(__bridge id)COLOR_WITH_RGB(endColorHex).CGColor]; // 设置渐变颜色方向,左上点为(0,0), 右下点为(1,1) gradientLayer.startPoint = start; gradientLayer.endPoint = end; // 设置颜色变化点,取值范围 0.0~1.0 gradientLayer.locations = @[@0.0,@1.0]; gradientLayer.type = kCAGradientLayerAxial; [self.layer insertSublayer:gradientLayer atIndex:0]; } //- (CGFloat)orientationWidth { // //return UIDeviceOrientationIsLandscape(TTDeviceOrientation()) // //? self.height : self.width; //} // //- (CGFloat)orientationHeight { // //return UIDeviceOrientationIsLandscape(TTDeviceOrientation()) // //? self.width : self.height; //} - (UIScrollView*)findFirstScrollView { if ([self isKindOfClass:[UIScrollView class]]) return (UIScrollView*)self; for (UIView* child in self.subviews) { UIScrollView* it = [child findFirstScrollView]; if (it) return it; } return nil; } - (UIView*)firstViewOfClass:(Class)cls { if ([self isKindOfClass:cls]) return self; for (UIView* child in self.subviews) { UIView* it = [child firstViewOfClass:cls]; if (it) return it; } return nil; } - (UIView*)firstParentOfClass:(Class)cls { if ([self isKindOfClass:cls]) { return self; } else if (self.superview) { return [self.superview firstParentOfClass:cls]; } else { return nil; } } - (UIView*)findChildWithDescendant:(UIView*)descendant { for (UIView* view = descendant; view && view != self; view = view.superview) { if (view.superview == self) { return view; } } return nil; } - (void)removeSubviews { while (self.subviews.count) { UIView* child = self.subviews.lastObject; if(child) { child.hidden = YES; [child removeFromSuperview]; } } } - (void)setCorners:(UIRectCorner)corners radius:(CGFloat)radius { UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; maskLayer.frame = self.bounds; maskLayer.path = maskPath.CGPath; self.layer.mask = maskLayer; } - (void)simulateTapAtPoint:(CGPoint)location { UITouch *touch = [[UITouch alloc] initInView:self location:location]; UIEvent *eventDown = [[UIEvent alloc] initWithTouch:touch]; [touch.view touchesBegan:[NSSet setWithObject:touch] withEvent:eventDown]; [touch changeToPhase:UITouchPhaseEnded]; UIEvent *eventUp = [[UIEvent alloc] initWithTouch:touch]; [touch.view touchesEnded:[NSSet setWithObject:touch] withEvent:eventUp]; } - (void)viewAddTopLine { UIView *line = [[UIView alloc] initWithFrame:CGRectIntegral(CGRectMake(0, 0, self.width, 1))]; line.backgroundColor = [UIColor blackColor];//[UIColor colorWithHexValue:0xd8d8dc]; [self addSubview:line]; } - (void)viewAddTopLine:(CGFloat)aOffsetx { UIView *line = [[UIView alloc] initWithFrame:CGRectIntegral(CGRectMake(aOffsetx, 0, self.width-aOffsetx, 1))]; line.backgroundColor = [UIColor blackColor];//[UIColor colorWithHexValue:0xd8d8dc]; [self addSubview:line]; } - (UIView *)viewAddMiddleLine:(CGFloat)aOffsetx { UIView *line = [[UIView alloc] initWithFrame:CGRectIntegral(CGRectMake(aOffsetx, 0, self.width-aOffsetx*2, 1.0))]; line.backgroundColor = COLOR_WITH_RGB(0xeeeeee);//[UIColor colorWithHexValue:0xd8d8dc]; [self addSubview:line]; return line; } - (void)viewAddBottomLine { UIView *line = [[UIView alloc] initWithFrame:CGRectIntegral(CGRectMake(0, self.height-1/[UIScreen mainScreen].scale, SCREEN_WIDTH, 1))]; line.backgroundColor = COLOR_WITH_RGB(0xeeeeee); [self addSubview:line]; } - (UIView *)getViewLine:(CGRect)aRect { UIView *line = [[UIView alloc] initWithFrame:CGRectIntegral(aRect)]; line.backgroundColor = [UIColor blackColor];//[UIColor colorWithHexValue:0xd8d8dc]; return line; } - (UITapGestureRecognizer *)addTapGestureTarget:(id)target action:(SEL)action; { UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:target action:action]; self.userInteractionEnabled = YES; [self addGestureRecognizer:tap]; return tap; } //- (UIView *)tableviewFootView:(CGRect)aRect //{ // UILabel *label = [self labelWithFrame:aRect text:@"网络异常,请检查后重试!" textFont:kFont13 textColor:kGrayColor]; // label.textAlignment = NSTextAlignmentCenter; // return label; //} - (UIView *)addBottomSepetatorLineOffsetX:(CGFloat)offsetX { UIView *line = [UIView lineViewWithWidth:self.width-offsetX * 2]; [self addSubview:line]; line.centerX = self.width * 0.5; line.bottom = self.height; return line; } - (void)addBottomDottedLine { UIView *view = self; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; [shapeLayer setBounds:view.bounds]; [shapeLayer setPosition:CGPointMake(CGRectGetWidth(view.frame) / 2, CGRectGetHeight(view.frame)/2)]; [shapeLayer setStrokeColor:COLOR_WITH_RGB(0xBBBBBB).CGColor]; [shapeLayer setLineWidth:0.5]; // 设置线宽,线间距 [shapeLayer setLineDashPattern:@[@5,@3]]; // 设置路径 CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, NULL, 0, self.height); // if (CGRectGetWidth(view.frame) > CGRectGetHeight(view.frame)) { // CGPathAddLineToPoint(path, NULL, CGRectGetWidth(view.frame),0); // }else{ CGPathAddLineToPoint(path, NULL, self.width, self.height); // } [shapeLayer setPath:path]; CGPathRelease(path); // 把绘制好的虚线添加上来 [view.layer addSublayer:shapeLayer]; } + (UIView *)lineViewWithWidth:(CGFloat)width { UIView *line = [[UIView alloc] init]; line.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.1]; line.height = 0.5; line.width = width; line.centerX = SCREEN_WIDTH * 0.5; return line; } - (void)clearBackgroudColorForClassNames:(NSArray *)classNames { for (UIView *subview in self.subviews) { if ([classNames containsObject:NSStringFromClass(subview.class)]) { subview.backgroundColor = [UIColor clearColor]; } [subview clearBackgroudColorForClassNames:classNames]; } } static char PresentedViewAddress; //被Present的View static char PresentingViewAddress; //正在Present其他视图的view #define AnimateDuartion .25f - (void)presentView:(UIView*)view animated:(BOOL)animated complete:(void(^)(void)) complete{ if (!self.window) { return; } [self.window addSubview:view]; objc_setAssociatedObject(self, &PresentedViewAddress, view, OBJC_ASSOCIATION_RETAIN); objc_setAssociatedObject(view, &PresentingViewAddress, self, OBJC_ASSOCIATION_RETAIN); if (animated) { [self doAlertAnimate:view complete:complete]; }else{ view.center = self.window.center; } } - (UIView *)presentedView{ UIView * view = objc_getAssociatedObject(self, &PresentedViewAddress); return view; } - (void)dismissPresentedView:(BOOL)animated complete:(void(^)(void)) complete{ UIView * view = objc_getAssociatedObject(self, &PresentedViewAddress); if (animated) { [self doHideAnimate:view complete:complete]; }else{ [view removeFromSuperview]; [self cleanAssocaiteObject]; } } - (void)hideSelf:(BOOL)animated complete:(void(^)(void)) complete{ UIView * baseView = objc_getAssociatedObject(self, &PresentingViewAddress); if (!baseView) { return; } [baseView dismissPresentedView:animated complete:complete]; [self cleanAssocaiteObject]; } - (void)onPressBkg:(id)sender{ [self dismissPresentedView:YES complete:nil]; } #pragma mark - Animation - (void)doAlertAnimate:(UIView*)view complete:(void(^)(void)) complete{ CGRect bounds = view.bounds; // 放大 CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"]; scaleAnimation.duration = AnimateDuartion; scaleAnimation.fromValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 1, 1)]; scaleAnimation.toValue = [NSValue valueWithCGRect:bounds]; // 移动 CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; moveAnimation.duration = AnimateDuartion; moveAnimation.fromValue = [NSValue valueWithCGPoint:[self.superview convertPoint:self.center toView:nil]]; moveAnimation.toValue = [NSValue valueWithCGPoint:self.window.center]; CAAnimationGroup *group = [CAAnimationGroup animation]; group.beginTime = CACurrentMediaTime(); group.duration = AnimateDuartion; group.animations = [NSArray arrayWithObjects:scaleAnimation,moveAnimation,nil]; group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // group.delegate = self; group.fillMode = kCAFillModeForwards; group.removedOnCompletion = NO; group.autoreverses = NO; [self hideAllSubView:view]; [view.layer addAnimation:group forKey:@"groupAnimationAlert"]; __weak UIView * wself = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AnimateDuartion * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ view.layer.bounds = bounds; view.layer.position = wself.superview.center; [wself showAllSubView:view]; if (complete) { complete(); } }); } - (void)doHideAnimate:(UIView*)alertView complete:(void(^)(void)) complete{ if (!alertView) { return; } // 缩小 CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"]; scaleAnimation.duration = AnimateDuartion; scaleAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 1, 1)]; CGPoint position = self.center; // 移动 CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; moveAnimation.duration = AnimateDuartion; moveAnimation.toValue = [NSValue valueWithCGPoint:[self.superview convertPoint:self.center toView:nil]]; CAAnimationGroup *group = [CAAnimationGroup animation]; group.beginTime = CACurrentMediaTime(); group.duration = AnimateDuartion; group.animations = [NSArray arrayWithObjects:scaleAnimation,moveAnimation,nil]; group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // group.delegate = self; group.fillMode = kCAFillModeForwards; group.removedOnCompletion = NO; group.autoreverses = NO; alertView.layer.bounds = self.bounds; alertView.layer.position = position; alertView.layer.needsDisplayOnBoundsChange = YES; [self hideAllSubView:alertView]; alertView.backgroundColor = [UIColor clearColor]; [alertView.layer addAnimation:group forKey:@"groupAnimationHide"]; __weak UIView * wself = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(AnimateDuartion * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [alertView removeFromSuperview]; [wself cleanAssocaiteObject]; [wself showAllSubView:alertView]; if (complete) { complete(); } }); } static char *HideViewsAddress = "hideViewsAddress"; - (void)hideAllSubView:(UIView*)view{ for (UIView * subView in view.subviews) { NSMutableArray *array = [[NSMutableArray alloc] init]; if (subView.hidden) { [array addObject:subView]; } objc_setAssociatedObject(self, &HideViewsAddress, array, OBJC_ASSOCIATION_RETAIN); subView.hidden = YES; } } - (void)showAllSubView:(UIView*)view{ NSMutableArray *array = objc_getAssociatedObject(self,&HideViewsAddress); for (UIView * subView in view.subviews) { subView.hidden = [array containsObject:subView]; } } - (void)cleanAssocaiteObject{ objc_setAssociatedObject(self,&PresentedViewAddress,nil,OBJC_ASSOCIATION_RETAIN); objc_setAssociatedObject(self,&PresentingViewAddress,nil,OBJC_ASSOCIATION_RETAIN); objc_setAssociatedObject(self,&HideViewsAddress,nil, OBJC_ASSOCIATION_RETAIN); } - (void)makeCenterToastActivity { // if([self respondsToSelector:@selector(makeToastActivity:)]) // { // [self hideToastActivity]; // [self performSelector:@selector(makeToastActivity:) withObject:CSToastPositionCenter]; // } } @end static const NSString *kTouchUpInsideActionBlockKey = @"kTouchUpInsideActionBlockKey"; @implementation UIButton(Addition) - (void)addTouchUpInsideWithAction:(TouchUpInsideActionBlock)action { objc_setAssociatedObject(self, (__bridge const void * _Nonnull)(kTouchUpInsideActionBlockKey), action, OBJC_ASSOCIATION_COPY); [self addTarget:self action:@selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside]; } - (void)handleTouchUpInside:(UIButton *)sender { TouchUpInsideActionBlock action = objc_getAssociatedObject(self, (__bridge const void * _Nonnull)(kTouchUpInsideActionBlockKey)); if (action) { action(sender); } } - (void)setDisable:(BOOL)disable { self.enabled = !disable; self.alpha = self.enabled ? 1.0 : 0.5; } @end