From ff6c2e6ab6d3a1a646612d0597b210b9bec1e65e Mon Sep 17 00:00:00 2001 From: IEoN Date: Tue, 12 Jul 2016 21:35:21 +0100 Subject: [PATCH 1/2] LEON - adding a few useful things to play with: overlay, hit test, etc. --- Sample.xcodeproj/project.pbxproj | 6 +++ Sample/Base.lproj/Main.storyboard | 63 +++++++++++++++------- Sample/MyView.h | 6 ++- Sample/MyView.m | 63 ++++++++++++++++++++-- Sample/MyView.xib | 88 ++++++++++++++++++++----------- Sample/OverlayView.h | 17 ++++++ Sample/OverlayView.m | 34 ++++++++++++ Sample/ViewController.m | 50 +++++++++++++++--- 8 files changed, 265 insertions(+), 62 deletions(-) create mode 100644 Sample/OverlayView.h create mode 100644 Sample/OverlayView.m diff --git a/Sample.xcodeproj/project.pbxproj b/Sample.xcodeproj/project.pbxproj index d8eceb3..44e41dc 100644 --- a/Sample.xcodeproj/project.pbxproj +++ b/Sample.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 357A68201D356A5300E26506 /* MyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 357A681F1D356A5300E26506 /* MyView.xib */; }; + 357A68231D35784600E26506 /* OverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 357A68221D35784600E26506 /* OverlayView.m */; }; 7E58FADF1D33FFF800D9147C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E58FADE1D33FFF800D9147C /* main.m */; }; 7E58FAE21D33FFF800D9147C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E58FAE11D33FFF800D9147C /* AppDelegate.m */; }; 7E58FAE51D33FFF800D9147C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E58FAE41D33FFF800D9147C /* ViewController.m */; }; @@ -40,6 +41,8 @@ /* Begin PBXFileReference section */ 357A681F1D356A5300E26506 /* MyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyView.xib; sourceTree = ""; }; + 357A68211D35784600E26506 /* OverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverlayView.h; sourceTree = ""; }; + 357A68221D35784600E26506 /* OverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OverlayView.m; sourceTree = ""; }; 7E58FADA1D33FFF800D9147C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 7E58FADE1D33FFF800D9147C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 7E58FAE01D33FFF800D9147C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -126,6 +129,8 @@ 7E58FB181D35014E00D9147C /* MyView.h */, 7E58FB191D35014E00D9147C /* MyView.m */, 357A681F1D356A5300E26506 /* MyView.xib */, + 357A68211D35784600E26506 /* OverlayView.h */, + 357A68221D35784600E26506 /* OverlayView.m */, ); path = Sample; sourceTree = ""; @@ -290,6 +295,7 @@ buildActionMask = 2147483647; files = ( 7E58FB131D34E91A00D9147C /* AlertDialog.m in Sources */, + 357A68231D35784600E26506 /* OverlayView.m in Sources */, 7E58FAE51D33FFF800D9147C /* ViewController.m in Sources */, 7E58FAE21D33FFF800D9147C /* AppDelegate.m in Sources */, 7E58FADF1D33FFF800D9147C /* main.m in Sources */, diff --git a/Sample/Base.lproj/Main.storyboard b/Sample/Base.lproj/Main.storyboard index 34fb655..8923e8c 100644 --- a/Sample/Base.lproj/Main.storyboard +++ b/Sample/Base.lproj/Main.storyboard @@ -3,6 +3,8 @@ + + @@ -29,30 +31,55 @@ + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + diff --git a/Sample/MyView.h b/Sample/MyView.h index ce68e07..dc7e88b 100644 --- a/Sample/MyView.h +++ b/Sample/MyView.h @@ -15,11 +15,15 @@ typedef NS_ENUM(NSInteger, ButtonAction) { }; typedef void (^ClickBlock)(ButtonAction action); +typedef void (^DismissBlock)(CGPoint tapPoint); @interface MyView : UIView @property (nonatomic, copy) ClickBlock click; +@property (nonatomic, copy) DismissBlock dismissBlock; -+ (instancetype)myViewWithFrame:(CGRect)frame; ++ (instancetype)myView; + +- (void)show; @end diff --git a/Sample/MyView.m b/Sample/MyView.m index 189721d..340e6e1 100644 --- a/Sample/MyView.m +++ b/Sample/MyView.m @@ -7,9 +7,11 @@ // #import "MyView.h" +#import "OverlayView.h" @interface MyView () +@property (weak, nonatomic) IBOutlet UIView *contentView; @property (weak, nonatomic) IBOutlet UIButton *button; @property (weak, nonatomic) IBOutlet UILabel *titleLabel; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *titleTopSpacing; @@ -18,21 +20,72 @@ @interface MyView () @implementation MyView -+ (instancetype)myViewWithFrame:(CGRect)frame { ++ (instancetype)myView { MyView *view = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:self options:nil] firstObject]; - view.frame = frame; - view.layer.borderWidth = 1; + view.frame = [UIScreen mainScreen].bounds; view.clipsToBounds = YES; - [view configureButton]; + [view configureOverlay]; + [view configureContentView]; + return view; } +- (void)configureOverlay { + OverlayView *overlay = [[OverlayView alloc] initWithFrame:self.bounds]; + overlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.35]; + overlay.tapBlock = ^(CGPoint point) { + if (self.dismissBlock) { + self.dismissBlock(point); + } + [self dismiss]; + }; + [self addSubview:overlay]; + [self sendSubviewToBack:overlay]; +} + - (void)configureButton { + self.button.layer.cornerRadius = 4; [self.button addTarget:self action:@selector(testClick) forControlEvents:UIControlEventTouchUpInside]; } +- (void)configureContentView { + [self configureButton]; + self.contentView.layer.cornerRadius = 4; + self.contentView.clipsToBounds = YES; +} + +- (void)show { + UIWindow *window = [[UIApplication sharedApplication] keyWindow]; + if (!window) { + NSEnumerator *frontToBackWindows = [[[UIApplication sharedApplication] windows] reverseObjectEnumerator]; + for (UIWindow *w in frontToBackWindows) { + if (w.windowLevel == UIWindowLevelNormal) { + window = w; + break; + } + } + } + [window addSubview:self]; + self.center = window.center; + [self fadeIn]; +} + +- (void)fadeIn { + self.alpha = 0; + [UIView animateWithDuration:0.2 animations:^{ + self.alpha = 1; + }]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.2 animations:^{ + self.alpha = 0; + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + - (void)testClick { - NSLog(@"button clicked"); if (self.click) { self.click(ButtonActionPositive); } diff --git a/Sample/MyView.xib b/Sample/MyView.xib index 2384f3b..fa7fc12 100644 --- a/Sample/MyView.xib +++ b/Sample/MyView.xib @@ -3,53 +3,79 @@ + - + - - - - - - + + + + + + + + + - - + + + + + + + + - - + - - - - - - - - - - + + + + + - + - + diff --git a/Sample/OverlayView.h b/Sample/OverlayView.h new file mode 100644 index 0000000..75737f5 --- /dev/null +++ b/Sample/OverlayView.h @@ -0,0 +1,17 @@ +// +// OverlayView.h +// momo_ios +// +// Created by leon on 6/16/16. +// Copyright © 2016 MaiMemo Inc. All rights reserved. +// + +#import + +typedef void (^TapBlock)(CGPoint point); + +@interface OverlayView : UIView + +@property (nonatomic, copy) TapBlock tapBlock; + +@end diff --git a/Sample/OverlayView.m b/Sample/OverlayView.m new file mode 100644 index 0000000..833d137 --- /dev/null +++ b/Sample/OverlayView.m @@ -0,0 +1,34 @@ +// +// OverlayView.m +// momo_ios +// +// Created by leon on 6/16/16. +// Copyright © 2016 MaiMemo Inc. All rights reserved. +// + +#import "OverlayView.h" + +@interface OverlayView () + +@end + +@implementation OverlayView + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + + UIView *hitView = [super hitTest:point withEvent:event]; + if (hitView == self) { + if (self.tapBlock) { + self.tapBlock(point); + } + } + return nil; +} + +- (void)tapped:(UIGestureRecognizer *)tap { + if (self.tapBlock) { + self.tapBlock([tap locationInView:tap.view]); + } +} + +@end diff --git a/Sample/ViewController.m b/Sample/ViewController.m index e5dceb8..0acba1c 100644 --- a/Sample/ViewController.m +++ b/Sample/ViewController.m @@ -12,6 +12,10 @@ @interface ViewController () +@property (weak, nonatomic) IBOutlet UIButton *showAlertButton; +@property (weak, nonatomic) IBOutlet UILabel *label1; +@property (weak, nonatomic) IBOutlet UILabel *label2; + @end @implementation ViewController @@ -28,6 +32,9 @@ @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; + [self.showAlertButton addTarget:self action:@selector(showAlert:) forControlEvents:UIControlEventTouchUpInside]; + self.showAlertButton.layer.cornerRadius = 4; + self.showAlertButton.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.4]; } - (void)didReceiveMemoryWarning { @@ -43,13 +50,6 @@ - (void) viewDidAppear:(BOOL)animated { // AlertDialog *dialog = [[AlertDialog alloc] initWithViewCountroller: self]; // dialog.dialogTitle = [[NSAttributedString alloc] initWithString: @"Fuck" attributes:nil]; // [dialog show]; - MyView *view = [MyView myViewWithFrame:CGRectMake(0, 0, 250, 250)]; - view.center = self.view.center; - view.click = ^(ButtonAction action) { - NSLog(@"just to say hi"); - }; - [self.view addSubview:view]; - } - (void) show { @@ -64,4 +64,40 @@ - (void) dismiss { } + +/** + * initiate view via button click + */ +- (void)showAlert:(UIButton *)button { + MyView *view = [MyView myView]; + view.click = ^(ButtonAction action) { + NSLog(@"button clicked: %zd", action); + }; + + /** + * Avoid retain cycle to define a weak reference of self used in block + * bacuase this block does not get executed right after creation + */ + __weak typeof(self) wself = self; + view.dismissBlock = ^(CGPoint point) { + + /** + * The overlay in MyView will by pass all gesture down while still detecting + * tapping location. Location can then be used to determine whether any underlying view + * should perform side effect. + */ + NSLog(@"dismissed by clicking point %@", NSStringFromCGPoint(point)); + if (CGRectContainsPoint(wself.label1.frame, point)) { + NSLog(@"you hit label 1"); + } else if (CGRectContainsPoint(wself.label2.frame, point)) { + NSLog(@"you hit label 2"); + } else if (CGRectContainsPoint(wself.showAlertButton.frame, point)) { + NSLog(@"you hit button"); + } else { + NSLog(@"you hit nothing"); + } + }; + [view show]; +} + @end From 8f65d95e240a1e8fe9d83211c1e03be9845f2d15 Mon Sep 17 00:00:00 2001 From: IEoN Date: Tue, 12 Jul 2016 21:39:45 +0100 Subject: [PATCH 2/2] leon --- Sample/MyView.m | 3 +++ Sample/MyView.xib | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Sample/MyView.m b/Sample/MyView.m index 340e6e1..7665833 100644 --- a/Sample/MyView.m +++ b/Sample/MyView.m @@ -93,13 +93,16 @@ - (void)testClick { } - (void)animateTitle { + BOOL removing = NO; if (self.titleTopSpacing.constant > 0) { self.titleTopSpacing.constant = -self.titleLabel.frame.size.height; + removing = YES; } else { self.titleTopSpacing.constant = 21; } [UIView animateWithDuration:0.5 animations:^{ [self layoutIfNeeded]; + self.titleLabel.alpha = removing ? 0 : 1; }]; } diff --git a/Sample/MyView.xib b/Sample/MyView.xib index fa7fc12..5ae2034 100644 --- a/Sample/MyView.xib +++ b/Sample/MyView.xib @@ -13,7 +13,7 @@ - +