├── .gitignore ├── ContainerView ├── ContainerDefines.h ├── ContainerScrollDelegate.h ├── ContainerScrollDelegate.m ├── ContainerTypes.h ├── ContainerView.h ├── ContainerView.m ├── ContainerViewController.h └── ContainerViewController.m ├── DemoContainerView ├── DemoContainerView.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── mrusta.xcuserdatad │ │ │ └── IDEFindNavigatorScopes.plist │ └── xcuserdata │ │ └── rustam.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── DemoContainerView │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── IMG_0.imageset │ │ ├── Contents.json │ │ └── IMG_0@3x.jpg │ ├── IMG_1.imageset │ │ ├── Contents.json │ │ └── IMG_1@3x.jpg │ ├── IMG_10.imageset │ │ ├── Contents.json │ │ └── IMG_10@3x.jpg │ ├── IMG_11.imageset │ │ ├── Contents.json │ │ └── IMG_11@3x.jpg │ ├── IMG_12.imageset │ │ ├── Contents.json │ │ └── IMG_12@3x.jpg │ ├── IMG_13.imageset │ │ ├── Contents.json │ │ └── IMG_13@3x.jpg │ ├── IMG_14.imageset │ │ ├── Contents.json │ │ └── IMG_14@3x.jpg │ ├── IMG_15.imageset │ │ ├── Contents.json │ │ └── IMG_15@3x.jpg │ ├── IMG_16.imageset │ │ ├── Contents.json │ │ └── IMG_16@3x.jpg │ ├── IMG_17.imageset │ │ ├── Contents.json │ │ └── IMG_17@3x.jpg │ ├── IMG_18.imageset │ │ ├── Contents.json │ │ └── IMG_18@3x.jpg │ ├── IMG_19.imageset │ │ ├── Contents.json │ │ └── IMG_19@3x.jpg │ ├── IMG_2.imageset │ │ ├── Contents.json │ │ └── IMG_2@3x.jpg │ ├── IMG_20.imageset │ │ ├── Contents.json │ │ └── IMG_20@3x.jpg │ ├── IMG_21.imageset │ │ ├── Contents.json │ │ └── IMG_21@3x.jpg │ ├── IMG_22.imageset │ │ ├── Contents.json │ │ └── IMG_22@3x.jpg │ ├── IMG_23.imageset │ │ ├── Contents.json │ │ └── IMG_23@3x.jpg │ ├── IMG_24.imageset │ │ ├── Contents.json │ │ └── IMG_24@3x.jpg │ ├── IMG_25.imageset │ │ ├── Contents.json │ │ └── IMG_25@3x.jpg │ ├── IMG_26.imageset │ │ ├── Contents.json │ │ └── IMG_26@3x.jpg │ ├── IMG_27.imageset │ │ ├── Contents.json │ │ └── IMG_27@3x.jpg │ ├── IMG_28.imageset │ │ ├── Contents.json │ │ └── IMG_28@3x.jpg │ ├── IMG_29.imageset │ │ ├── Contents.json │ │ └── IMG_29@3x.jpg │ ├── IMG_3.imageset │ │ ├── Contents.json │ │ └── IMG_3@3x.jpg │ ├── IMG_30.imageset │ │ ├── Contents.json │ │ └── IMG_30@3x.jpg │ ├── IMG_31.imageset │ │ ├── Contents.json │ │ └── IMG_31@3x.jpg │ ├── IMG_32.imageset │ │ ├── Contents.json │ │ └── IMG_32@3x.jpg │ ├── IMG_33.imageset │ │ ├── Contents.json │ │ └── IMG_33.jpg │ ├── IMG_34.imageset │ │ ├── Contents.json │ │ └── IMG_34.jpg │ ├── IMG_35.imageset │ │ ├── Contents.json │ │ └── IMG_35@3x.jpg │ ├── IMG_36.imageset │ │ ├── Contents.json │ │ └── IMG_36@3x.jpg │ ├── IMG_37.imageset │ │ ├── Contents.json │ │ └── IMG_37.jpg │ ├── IMG_38.imageset │ │ ├── Contents.json │ │ └── IMG_38.jpg │ ├── IMG_39.imageset │ │ ├── Contents.json │ │ └── IMG_39.jpg │ ├── IMG_4.imageset │ │ ├── Contents.json │ │ └── IMG_4@3x.jpg │ ├── IMG_40.imageset │ │ ├── Contents.json │ │ └── IMG_40.jpg │ ├── IMG_41.imageset │ │ ├── Contents.json │ │ └── IMG_41@3x.jpg │ ├── IMG_42.imageset │ │ ├── Contents.json │ │ └── IMG_42@3x.jpg │ ├── IMG_43.imageset │ │ ├── Contents.json │ │ └── IMG_43.jpg │ ├── IMG_44.imageset │ │ ├── Contents.json │ │ └── IMG_44@3x.jpg │ ├── IMG_45.imageset │ │ ├── Contents.json │ │ └── IMG_45@3x.jpg │ ├── IMG_46.imageset │ │ ├── Contents.json │ │ └── IMG_46@3x.jpg │ ├── IMG_5.imageset │ │ ├── Contents.json │ │ └── IMG_5@3x.jpg │ ├── IMG_6.imageset │ │ ├── Contents.json │ │ └── IMG_6@3x.jpg │ ├── IMG_7.imageset │ │ ├── Contents.json │ │ └── IMG_7@3x.jpg │ ├── IMG_8.imageset │ │ ├── Contents.json │ │ └── IMG_8@3x.jpg │ ├── IMG_9.imageset │ │ ├── Contents.json │ │ └── IMG_9@3x.jpg │ └── header_shadow.imageset │ │ ├── Contents.json │ │ └── header_shadow.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Demo │ ├── DemoHeaderViews │ │ ├── DemoHeaderViews.h │ │ └── DemoHeaderViews.m │ ├── DemoModalViewController.h │ ├── DemoModalViewController.m │ ├── DemoScrollViews │ │ ├── DemoCells │ │ │ ├── DemoCollectionCell.h │ │ │ ├── DemoCollectionCell.m │ │ │ ├── DemoTableCell.h │ │ │ └── DemoTableCell.m │ │ ├── DemoProtocolsCollectionView │ │ │ ├── DemoCollectionDataSource.h │ │ │ ├── DemoCollectionDataSource.m │ │ │ ├── DemoCollectionDelegate.h │ │ │ └── DemoCollectionDelegate.m │ │ ├── DemoProtocolsTableView │ │ │ ├── DemoTableDataSource.h │ │ │ ├── DemoTableDataSource.m │ │ │ ├── DemoTableDelegate.h │ │ │ └── DemoTableDelegate.m │ │ ├── DemoScrollViews.h │ │ └── DemoScrollViews.m │ ├── DemoViewController.h │ └── DemoViewController.m │ ├── Info.plist │ ├── Resources │ ├── ProximaNova-Extrabld.otf │ └── ProximaNova-Regular.otf │ └── main.m ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | DemoContainerView/DemoContainerView.xcodeproj/xcuserdata/mrusta.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 2 | DemoContainerView/DemoContainerView.xcodeproj/xcuserdata/mrusta.xcuserdatad/xcschemes/xcschememanagement.plist 3 | -------------------------------------------------------------------------------- /ContainerView/ContainerDefines.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 12.08.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | #import 7 | 8 | 9 | 10 | /// APP 11 | #define APP ([UIApplication sharedApplication]) 12 | #define WINDOW ((UIWindow *)APP.delegate.window) 13 | 14 | /// ROOT 15 | #define ROOT_VC (APP.keyWindow.rootViewController) 16 | 17 | /// NAV 18 | #define NAV_ADDED ([ROOT_VC isKindOfClass:[UINavigationController class]]) 19 | 20 | #define NETWORK_INDICATOR_ON(a) (APP.networkActivityIndicatorVisible = a) 21 | 22 | /// STATUS BAR 23 | #define STATUSBAR_STYLE(a) ([APP setStatusBarStyle:(UIStatusBarStyle)a animated:YES]) 24 | 25 | 26 | /// SIZE 27 | #define FRAME ((CGRect)WINDOW.frame) 28 | 29 | #define SCREEN_STATUS_HEIGHT [UIApplication sharedApplication].statusBarFrame.size.height 30 | 31 | #define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) 32 | #define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height) 33 | #define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT)) 34 | #define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT)) 35 | 36 | #define SCREEN_PORTRAIT (SCREEN_WIDTH < SCREEN_HEIGHT) 37 | 38 | /// DEVICE 39 | #define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 40 | #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 41 | #define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0) 42 | 43 | #define IS_IPHONE_4 (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0) 44 | #define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0) 45 | #define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0) 46 | #define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0) 47 | #define IS_IPHONE_X (IS_IPHONE && SCREEN_MAX_LENGTH == 812.0) 48 | #define IS_BIG_IPHONE (IS_IPHONE && SCREEN_MAX_LENGTH > 568.0) 49 | 50 | #define IPHONE_X_PADDING_TOP (IS_IPHONE_X ? 24 :0) 51 | #define IPHONE_X_PADDING_BOTTOM (IS_IPHONE_X ? 34 :0) 52 | 53 | /// COLOR 54 | #define RGBA(r,g,b,a) ([UIColor colorWithRed:(CGFloat)r / 255.0 green:(CGFloat)g / 255.0 blue:(CGFloat)b / 255.0 alpha:(CGFloat)a]) 55 | #define RGB(r,g,b) RGBA(r,g,b, 1.0) 56 | #define HTMLRGBA(rgb,a) RGBA( ((rgb >> 16) & 0xff),((rgb >> 8) & 0xff),((rgb) & 0xff),a) 57 | #define HTMLRGB(rgb) HTMLRGBA(rgb, 1.0) 58 | 59 | #define GRAYLEVEL(l) RGB(l,l,l) 60 | 61 | #define BLACK_COLOR [UIColor blackColor] 62 | #define WHITE_COLOR [UIColor whiteColor] 63 | #define RED_COLOR [UIColor redColor] 64 | #define CLR_COLOR [UIColor clearColor] 65 | 66 | /// FONTS 67 | #define FONT_S(s) [UIFont systemFontOfSize:s] 68 | #define FONT_BS(s) [UIFont boldSystemFontOfSize:s] 69 | 70 | /// ANIMATION 71 | #define ANIMATION(d,a) [UIView animateWithDuration:d animations:a completion:nil] 72 | #define ANIMATIONCOMP(d,a,c) [UIView animateWithDuration:d animations:a completion:c] 73 | #define ANIMATION_SPRING(d,a) [UIView animateWithDuration:d delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:6.0 options:UIViewAnimationOptionAllowUserInteraction animations:a completion:nil] 74 | #define ANIMATION_SPRINGCOMP(d,a,c) [UIView animateWithDuration:d delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:6.0 options:UIViewAnimationOptionAllowUserInteraction animations:a completion:c] 75 | 76 | 77 | /// STRING 78 | #define SFMT(str, ...) [NSString stringWithFormat:str, ##__VA_ARGS__] 79 | #define PRINT(str, ...) printf("%s\n",[NSString stringWithFormat:str, ##__VA_ARGS__].UTF8String) 80 | 81 | /// IMAGE 82 | #define IMG(name) [UIImage imageNamed:name] 83 | 84 | 85 | /// GCD 86 | #define GCD_SYNC_MAIN_BEGIN dispatch_sync(dispatch_get_main_queue(), ^ 87 | #define GCD_ASYNC_MAIN_BEGIN dispatch_async(dispatch_get_main_queue(), ^ 88 | #define GCD_MAIN_END }); 89 | 90 | #define GCD_SYNC_GLOBAL_BEGIN(PRIORITY) dispatch_sync(dispatch_get_global_queue(PRIORITY, 0), ^ 91 | #define GCD_ASYNC_GLOBAL_BEGIN(PRIORITY) dispatch_async(dispatch_get_global_queue(PRIORITY, 0), ^ 92 | #define GCD_GLOBAL_END }); 93 | 94 | 95 | /// CUSTOM 96 | #define COORDINATE_SAN_FRANCISCO (MKCoordinateRegionMakeWithDistance( (CLLocationCoordinate2D) { 37.773972, -122.431297 }, 25000, 25000)) 97 | 98 | #define CUSTOM_TOP 60.0 99 | #define CUSTOM_BOTTOM (92) 100 | #define CUSTOM_MIDDLE (0.5) 101 | 102 | #define CUSTOM_HEADER_HEIGHT 64.0 103 | 104 | #define FRAME_SCROLLVIEW CGRectMake ( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT -CUSTOM_TOP -IPHONE_X_PADDING_TOP ) 105 | 106 | 107 | -------------------------------------------------------------------------------- /ContainerView/ContainerScrollDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | #import "ContainerTypes.h" 7 | #import "ContainerView.h" 8 | 9 | @interface ContainerScrollDelegate : NSObject 10 | 11 | @property (strong, nonatomic) ContainerView *containerView; 12 | @property (strong, nonatomic) void(^blockTransform)(CGFloat); 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ContainerView/ContainerScrollDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "ContainerScrollDelegate.h" 6 | #import "ContainerDefines.h" 7 | 8 | @implementation ContainerScrollDelegate { 9 | BOOL bordersRunContainer; 10 | BOOL onceEnded; 11 | BOOL bottomDeceleratingDisable; 12 | BOOL onceScrollingBeginDragging; 13 | BOOL scrollBegin; 14 | CGFloat startScrollPosition; 15 | CGAffineTransform selfTransform; 16 | } 17 | 18 | 19 | 20 | #pragma mark - Scroll Delegate 21 | 22 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 23 | { 24 | CGFloat velocityInViewY = [scrollView.panGestureRecognizer velocityInView: WINDOW].y; 25 | CGFloat translationInViewY = [scrollView.panGestureRecognizer translationInView:WINDOW].y; 26 | 27 | if((scrollView.panGestureRecognizer.state) && (scrollView.contentOffset.y <= 0)) { 28 | scrollView.showsVerticalScrollIndicator = NO; 29 | scrollView.contentOffset = CGPointMake( scrollView.contentOffset.x, 0 ); 30 | } else { 31 | scrollView.showsVerticalScrollIndicator = YES; 32 | } 33 | 34 | bordersRunContainer = ( (scrollView.contentOffset.y == 0) && (0 < velocityInViewY)); 35 | 36 | selfTransform = self.containerView.transform; 37 | 38 | 39 | // if(NAV_ADDED) { 40 | // UINavigationController *nvc = (UINavigationController *)ROOT_VC; 41 | // if(!nvc.navigationBarHidden) { 42 | // top = (top + nvc.navigationBar.height); 43 | // } 44 | // } 45 | 46 | 47 | CGFloat top = self.containerView.containerTop; 48 | 49 | if(scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) 50 | onceScrollingBeginDragging = NO; 51 | 52 | if(bordersRunContainer) { 53 | 54 | onceEnded = NO; 55 | onceScrollingBeginDragging = NO; 56 | 57 | selfTransform.ty = ((top - startScrollPosition) + translationInViewY ); 58 | if(selfTransform.ty < top) selfTransform.ty = top; 59 | 60 | if(scrollBegin) 61 | { 62 | ANIMATION_SPRING(.325, ^(void) { 63 | self.containerView.transform = self->selfTransform; 64 | }); 65 | 66 | scrollBegin = NO; 67 | 68 | } else { 69 | self.containerView.transform = selfTransform; 70 | } 71 | } 72 | else 73 | { 74 | if((top == selfTransform.ty) && !onceScrollingBeginDragging) { 75 | onceScrollingBeginDragging = YES; 76 | 77 | CGFloat headerHeight = (self.containerView.headerView) ?self.containerView.headerView.frame.size.height :0; 78 | CGFloat top = (self.containerView.containerTop == 0) ? CUSTOM_TOP : self.containerView.containerTop; 79 | CGFloat iphnX = IPHONE_X_PADDING_TOP; 80 | 81 | CGFloat height = (SCREEN_HEIGHT - (top + headerHeight + iphnX )); 82 | 83 | if(scrollView.frame.size.height != height) { 84 | 85 | ANIMATION_SPRING( .45, ^(void) { 86 | scrollView.frame = CGRectMake( 87 | scrollView.frame.origin.x, headerHeight , 88 | scrollView.frame.size.width, height 89 | ); 90 | }); 91 | } 92 | } 93 | 94 | if(top < selfTransform.ty) 95 | { 96 | if (velocityInViewY < 0. ) 97 | { 98 | if(self.containerView.containerPosition == ContainerMoveTypeTop) { 99 | scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, 0 ); 100 | } 101 | 102 | selfTransform = self.containerView.transform; 103 | selfTransform.ty = ((top - startScrollPosition) + translationInViewY ); 104 | 105 | if(selfTransform.ty < top) selfTransform.ty = top; 106 | 107 | self.containerView.transform = selfTransform; 108 | } 109 | } 110 | } 111 | 112 | if(self.blockTransform) self.blockTransform(selfTransform.ty); 113 | } 114 | 115 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 116 | { 117 | startScrollPosition = scrollView.contentOffset.y; 118 | 119 | if(bottomDeceleratingDisable) return; 120 | 121 | scrollBegin = YES; 122 | if(startScrollPosition < 0) startScrollPosition = 0; 123 | } 124 | 125 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 126 | { 127 | if(bottomDeceleratingDisable) return; 128 | CGFloat velocityInViewY = [scrollView.panGestureRecognizer velocityInView:WINDOW].y; 129 | 130 | if(!self.containerView) return; 131 | 132 | if(!onceEnded) 133 | { 134 | onceEnded = YES; 135 | [self.containerView containerMoveForVelocityInView:velocityInViewY]; 136 | } 137 | } 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /ContainerView/ContainerTypes.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | 7 | typedef NS_ENUM(NSUInteger, ContainerStyle) { 8 | ContainerStyleDefault = 0, 9 | ContainerStyleLight, 10 | ContainerStyleExtraLight, 11 | ContainerStyleDark, 12 | }; 13 | 14 | typedef NS_ENUM(NSUInteger, ContainerMoveType) { 15 | ContainerMoveTypeTop = 0, 16 | ContainerMoveTypeMiddle, 17 | ContainerMoveTypeBottom, 18 | ContainerMoveTypeHide, 19 | }; 20 | 21 | typedef NS_ENUM(NSUInteger, SelectType) { 22 | SelectTypeSettings = 0, 23 | SelectTypeMap, 24 | SelectTypePhotos, 25 | }; 26 | 27 | 28 | -------------------------------------------------------------------------------- /ContainerView/ContainerView.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 08.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | #import "ContainerTypes.h" 7 | #import "ContainerDefines.h" 8 | 9 | 10 | @protocol ContainerViewDelegate 11 | @optional 12 | - (void)changeContainerMove:(ContainerMoveType)containerMove containerY:(CGFloat)containerY animated:(BOOL)animated; 13 | @end 14 | 15 | 16 | 17 | @interface ContainerView : UIView 18 | 19 | @property (nonatomic, weak) id delegate; 20 | 21 | 22 | 23 | @property (nonatomic) BOOL portrait; 24 | 25 | @property (nonatomic) BOOL firstAddedTop; 26 | @property (nonatomic) BOOL firstAddedMiddle; 27 | @property (nonatomic) BOOL firstAddedBottom; 28 | 29 | - (CGFloat)getContainerBottom; 30 | - (CGFloat)getContainerMiddle; 31 | 32 | /** 33 | @brief This view sets a custom header for the container. 34 | */ 35 | @property (strong, nonatomic) UIView *headerView; 36 | 37 | /** 38 | @brief This option indicates whether to add a button when the container is at the bottom to animate the container upwards. 39 | */ 40 | @property (nonatomic) BOOL containerBottomButtonToMoveTop; 41 | 42 | /** 43 | @brief When moving the container, by default there are 2 positions (this is moving up and down). This parameter adds 3 position (move to the middle) 44 | */ 45 | @property (nonatomic) BOOL containerAllowMiddlePosition; 46 | 47 | /** 48 | @brief This parameter sets the shadow for the container. 49 | */ 50 | @property (nonatomic) BOOL containerShadow; 51 | 52 | 53 | /** 54 | @brief This parameter sets the new position value for the up move type. 55 | */ 56 | @property (nonatomic) CGFloat containerTop; 57 | 58 | /** 59 | @brief This parameter sets the new position value for the type of movement to the middle position. 60 | */ 61 | @property (nonatomic) CGFloat containerMiddle; 62 | 63 | /** 64 | @brief This parameter sets the new position value for the type of movement to the middle position. 65 | */ 66 | @property (nonatomic) CGFloat containerBottom; 67 | 68 | /** 69 | @brief This method for changing the rounding radius 70 | */ 71 | @property (nonatomic) CGFloat containerCornerRadius; 72 | 73 | 74 | 75 | /** 76 | @brief This parameter indicates which type of move was last. 77 | */ 78 | @property (nonatomic) ContainerMoveType containerPosition; 79 | 80 | /** 81 | @brief This parameter indicates which container style 82 | */ 83 | @property (nonatomic) ContainerStyle containerStyle; 84 | 85 | 86 | /** 87 | @brief This method to add a blur to the background of the container. 88 |   89 | @param styleType There are 3 types of blur. Blur with hues of 90 | 1) black, 91 | 2) white, 92 | 3) white with low blur concentrations. 93 | 4) The last attribute turns off the blur, for a normal change of the background color. 94 | */ 95 | - (void)changeBlurStyle:(ContainerStyle)styleType; 96 | 97 | - (void)transitionToSizeTop:(CGFloat)top middle:(CGFloat)middle bottom:(CGFloat)bottom size:(CGSize)size; 98 | 99 | - (void)containerMoveForVelocityInView:(CGFloat)velocityInViewY; 100 | 101 | /** 102 | @brief This method for animated container movement, at fixed positions 103 |   104 | @param moveType There are 4 types of movement. Moving 1) up, 2) middle, 3) down, 4) hiding in the most down beyond the limits of visibility 105 | */ 106 | - (void)containerMove:(ContainerMoveType)moveType; 107 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated; 108 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion; 109 | 110 | /** 111 | @brief This method for animated container movement, by user position. 112 | 113 | @param position Custom position 114 | */ 115 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType; 116 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated; 117 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion; 118 | 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /ContainerView/ContainerView.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 08.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "ContainerView.h" 6 | 7 | @interface ContainerView () { 8 | CGFloat _containerTop; 9 | CGFloat _containerMiddle; 10 | CGFloat _containerBottom; 11 | CGFloat _savePositionContainer; 12 | CGFloat _containerCornerRadius; 13 | BOOL _containerAllowMiddlePosition; 14 | BOOL _containerBottomButtonToMoveTop; 15 | BOOL _containerShadow; 16 | UIView * _headerView; 17 | } 18 | 19 | 20 | 21 | @property (strong, nonatomic) UIButton *bottomButtonToMoveTop; 22 | 23 | @property (strong, nonatomic) UIScrollView *scrollView; 24 | 25 | 26 | @property (strong, nonatomic) UIVisualEffectView *visualEffectViewOrigin; 27 | @property (strong, nonatomic) UIView *visualEffectView; 28 | 29 | @end 30 | 31 | 32 | @implementation ContainerView 33 | 34 | - (id)initWithFrame:(CGRect)rect 35 | { 36 | self = [super initWithFrame:rect]; 37 | if(self) [self initContainer]; 38 | return self; 39 | } 40 | 41 | - (void)initContainer 42 | { 43 | [self initContainerSize:CGSizeMake(SCREEN_WIDTH,SCREEN_HEIGHT)]; 44 | 45 | self.backgroundColor = CLR_COLOR; 46 | self.clipsToBounds = NO; 47 | //self.layer.masksToBounds = NO; 48 | 49 | self.layer.shadowOffset = CGSizeMake(0, 5); 50 | self.layer.shadowOpacity = 0.75; 51 | self.layer.shadowRadius = 5; 52 | self.layer.shadowColor = RGB(44, 62, 80).CGColor; 53 | 54 | 55 | 56 | _containerAllowMiddlePosition = NO; 57 | _containerShadow = YES; 58 | 59 | UIPanGestureRecognizer * 60 | containerPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognized:)]; 61 | containerPan.delegate = self; 62 | [self addGestureRecognizer:containerPan]; 63 | 64 | 65 | // TODO: Implement these. 66 | // if (NAV_ADDED) { 67 | // UINavigationController * nav = (UINavigationController *)ROOT_VC; 68 | // if(!nav.navigationBarHidden) { 69 | // if(!nav.navigationBar.translucent) { 70 | // 71 | // } 72 | // if (@available(iOS 11.0, *)) { 73 | // if(!nav.navigationBar.prefersLargeTitles) { 74 | // 75 | // } 76 | // } 77 | // } 78 | // } 79 | 80 | 81 | self.transform = CGAffineTransformMakeTranslation( 0, self.containerBottom - IPHONE_X_PADDING_BOTTOM); 82 | self.containerPosition = ContainerMoveTypeBottom; 83 | 84 | if(!_visualEffectView) { 85 | _visualEffectView = [[UIView alloc] initWithFrame: CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; 86 | _visualEffectView.clipsToBounds = YES; 87 | _visualEffectView.autoresizingMask = 88 | (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | 89 | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin); 90 | [self addSubview:_visualEffectView]; 91 | 92 | if(!_visualEffectViewOrigin) 93 | { 94 | UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; 95 | _visualEffectViewOrigin = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; 96 | _visualEffectViewOrigin.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); 97 | _visualEffectViewOrigin.autoresizingMask = 98 | (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | 99 | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin); 100 | [_visualEffectView addSubview: _visualEffectViewOrigin]; 101 | } 102 | _visualEffectView.backgroundColor = WHITE_COLOR; 103 | _visualEffectViewOrigin.hidden = YES; 104 | } 105 | } 106 | 107 | /// Add Subview - Search ScrollView 108 | - (void)addSubview:(UIView *)subview { 109 | if(subview == self.visualEffectView) { 110 | [super addSubview:subview]; 111 | } else { 112 | if(self.headerView) [self.visualEffectView insertSubview:subview belowSubview:self.headerView]; 113 | else [self.visualEffectView addSubview:subview]; 114 | } 115 | 116 | if([subview isKindOfClass:[UIScrollView class]]) { 117 | 118 | if(_bottomButtonToMoveTop) { 119 | [_bottomButtonToMoveTop removeFromSuperview]; 120 | _bottomButtonToMoveTop = nil; 121 | } 122 | 123 | if(_containerBottomButtonToMoveTop) { 124 | [self addSubview:self.bottomButtonToMoveTop]; 125 | } 126 | 127 | self.scrollView = (UIScrollView *)subview; 128 | if (@available(iOS 11.0, *)) { 129 | self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; 130 | } 131 | 132 | self.scrollView.scrollEnabled = (self.containerPosition == ContainerMoveTypeTop); 133 | 134 | self.scrollView.indicatorStyle = 135 | (self.containerStyle == ContainerStyleDark) ? UIScrollViewIndicatorStyleWhite :UIScrollViewIndicatorStyleDefault; 136 | 137 | [self changeCornerRadius:_containerCornerRadius]; 138 | } 139 | } 140 | 141 | - (void)setContainerBottomButtonToMoveTop:(BOOL)newValue { 142 | _containerBottomButtonToMoveTop = newValue; 143 | if(newValue) { 144 | [self addSubview: self.bottomButtonToMoveTop]; 145 | } else if (!newValue && _bottomButtonToMoveTop) { 146 | [_bottomButtonToMoveTop removeFromSuperview]; 147 | _bottomButtonToMoveTop = nil; 148 | } 149 | } 150 | 151 | - (BOOL)containerBottomButtonToMoveTop { 152 | return _containerBottomButtonToMoveTop; 153 | } 154 | 155 | - (void)setContainerCornerRadius:(CGFloat)containerCornerRadius { 156 | [self changeCornerRadius:containerCornerRadius]; 157 | } 158 | 159 | - (CGFloat)containerCornerRadius { 160 | return _containerCornerRadius; 161 | } 162 | 163 | - (void)changeCornerRadius:(CGFloat)newValue { 164 | _containerCornerRadius = newValue; 165 | 166 | self.layer.cornerRadius = _containerCornerRadius; 167 | 168 | if (self.visualEffectView) 169 | self.visualEffectView.layer.cornerRadius = _containerCornerRadius; 170 | 171 | [self calculationScrollViewHeight:0]; 172 | } 173 | 174 | 175 | 176 | 177 | 178 | - (UIButton *)bottomButtonToMoveTop { 179 | 180 | if(!_bottomButtonToMoveTop) 181 | { 182 | UIButton * 183 | btn = [UIButton buttonWithType:UIButtonTypeCustom]; 184 | [btn addTarget:self action:@selector(containerBottomButtonAction) forControlEvents:UIControlEventTouchUpInside]; 185 | 186 | //[btn addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(containerBottomButtonAction)]]; 187 | //[btn addGestureRecognizer: [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(containerBottomButtonAction)]]; 188 | 189 | btn.frame = CGRectMake( 0, 0, SCREEN_WIDTH, (SCREEN_HEIGHT - self.containerBottom + IPHONE_X_PADDING_BOTTOM) ); 190 | btn.backgroundColor = CLR_COLOR; 191 | _bottomButtonToMoveTop = btn; 192 | } 193 | 194 | return _bottomButtonToMoveTop; 195 | } 196 | - (void)containerBottomButtonAction { 197 | if(self.containerPosition == ContainerMoveTypeBottom) { 198 | [self containerMove:ContainerMoveTypeTop]; 199 | } 200 | } 201 | 202 | 203 | - (void)initContainerSize:(CGSize)size { 204 | 205 | if(size.width < size.height) { 206 | self.portrait = YES; 207 | self.frame = CGRectMake( 0 , self.frame.origin.y, size.width, size.height + 50); 208 | } else { 209 | self.portrait = NO; 210 | self.frame = CGRectMake( (IS_IPHONE_X ? 44 :15), self.frame.origin.y, (size.height - 20), size.height + 50); 211 | } 212 | } 213 | 214 | - (void)transitionToSizeTop:(CGFloat)top middle:(CGFloat)middle bottom:(CGFloat)bottom size:(CGSize)size { 215 | 216 | _containerTop = top; 217 | _containerMiddle = middle; 218 | _containerBottom = bottom; 219 | 220 | [self initContainerSize:size]; 221 | 222 | [self calculationScrollViewHeight:0]; 223 | 224 | [self containerMove:self.containerPosition]; 225 | } 226 | 227 | /// Top 228 | - (void)setContainerTop:(CGFloat)containerTop { 229 | if(!_firstAddedTop) _firstAddedTop = YES; 230 | _containerTop = containerTop; 231 | } 232 | 233 | - (CGFloat)containerTop { 234 | if(!_containerTop) _containerTop = CUSTOM_TOP; 235 | return _containerTop; 236 | } 237 | 238 | /// Middle 239 | - (void)setContainerMiddle:(CGFloat)containerMiddle { 240 | if(!_firstAddedMiddle) _firstAddedMiddle = YES; 241 | _containerMiddle = containerMiddle; 242 | } 243 | 244 | - (CGFloat)getContainerMiddle { 245 | return (_containerMiddle); 246 | } 247 | 248 | - (CGFloat)containerMiddle { 249 | if(!_containerMiddle) _containerMiddle = CUSTOM_MIDDLE; 250 | 251 | CGFloat bottom = SCREEN_HEIGHT - _containerBottom; 252 | CGFloat middle = (((bottom - _containerTop) * _containerMiddle) + _containerTop); 253 | 254 | return middle;// ((self.frame.size.height - 50) *_containerMiddle); 255 | } 256 | 257 | /// Bottom 258 | - (void)setContainerBottom:(CGFloat)containerBottom { 259 | if(!_firstAddedBottom) _firstAddedBottom = YES; 260 | _containerBottom = containerBottom; 261 | if(_bottomButtonToMoveTop) { 262 | _bottomButtonToMoveTop.frame = CGRectMake( _bottomButtonToMoveTop.frame.origin.x, _bottomButtonToMoveTop.frame.origin.y, 263 | _bottomButtonToMoveTop.frame.size.width, containerBottom ); 264 | } 265 | } 266 | 267 | - (CGFloat)getContainerBottom { 268 | return (_containerBottom); 269 | } 270 | 271 | - (CGFloat)containerBottom { 272 | if(!_containerBottom) _containerBottom = CUSTOM_BOTTOM; 273 | return ((self.frame.size.height - 50) -_containerBottom); 274 | } 275 | 276 | 277 | /// Enabled Move Middle 278 | - (void)setContainerAllowMiddlePosition:(BOOL)containerAllowMiddlePosition { 279 | _containerAllowMiddlePosition = containerAllowMiddlePosition; 280 | [self containerMove: (containerAllowMiddlePosition) ?ContainerMoveTypeMiddle :ContainerMoveTypeBottom]; 281 | } 282 | 283 | - (BOOL)containerAllowMiddlePosition { 284 | return _containerAllowMiddlePosition; 285 | } 286 | 287 | 288 | /// Shadow 289 | - (void)setContainerShadow:(BOOL)containerShadow { 290 | _containerShadow = containerShadow; 291 | 292 | if(containerShadow) { 293 | self.layer.shadowOffset = CGSizeMake(0, 5); 294 | self.layer.shadowOpacity = 0.75; 295 | self.layer.shadowRadius = 5; 296 | } else { 297 | self.layer.shadowOffset = CGSizeMake(0, 0); 298 | self.layer.shadowOpacity = 0.; 299 | self.layer.shadowRadius = 0; 300 | } 301 | } 302 | 303 | - (BOOL)containerShadow { 304 | return _containerShadow; 305 | } 306 | 307 | 308 | /// Header 309 | - (void)setHeaderView:(UIView *)hv { 310 | 311 | if(hv) { 312 | if(_headerView) [self removeHeaderView]; 313 | _headerView = hv; 314 | CGFloat width = SCREEN_PORTRAIT ?SCREEN_WIDTH :(SCREEN_HEIGHT - 20); 315 | _headerView.frame = CGRectMake( _headerView.frame.origin.x, _headerView.frame.origin.y, width, _headerView.frame.size.height ); 316 | _headerView.autoresizingMask = 317 | (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin); 318 | [self addSubview:_headerView]; 319 | } else { 320 | [self removeHeaderView]; 321 | } 322 | [self calculationScrollViewHeight:0]; 323 | } 324 | 325 | - (UIView *)headerView { 326 | return _headerView; 327 | } 328 | 329 | - (void)removeHeaderView { 330 | if(_headerView) { 331 | [_headerView removeFromSuperview]; 332 | } 333 | _headerView = nil; 334 | } 335 | 336 | 337 | /// Calculation ScrollView 338 | - (void)calculationScrollViewHeight:(CGFloat)containerPositionBottom { 339 | if(self.scrollView) { 340 | CGFloat headerHeight = 0; 341 | CGFloat top = self.containerTop; 342 | CGFloat iphnXpaddingTop = IPHONE_X_PADDING_TOP; 343 | CGFloat iphnXpaddingBottom = IPHONE_X_PADDING_BOTTOM; 344 | CGFloat scrollIndicatorInsetsBottom = 0; 345 | 346 | if(_headerView) { 347 | headerHeight = _headerView.frame.size.height; 348 | if(_headerView.frame.size.height < (0.66 * self.containerCornerRadius)) { 349 | scrollIndicatorInsetsBottom = ((0.66 * self.containerCornerRadius) - _headerView.frame.size.height); 350 | } 351 | } else { 352 | scrollIndicatorInsetsBottom = (0.66 * self.containerCornerRadius); 353 | } 354 | 355 | CGFloat width = (self.portrait) ?(SCREEN_WIDTH) :(SCREEN_HEIGHT - 20); 356 | CGFloat height = (SCREEN_HEIGHT + containerPositionBottom - (top + headerHeight + iphnXpaddingTop)); 357 | 358 | self.scrollView.frame = CGRectMake(self.scrollView.frame.origin.x, headerHeight, width, height); 359 | 360 | self.scrollView.scrollIndicatorInsets = UIEdgeInsetsMake( scrollIndicatorInsetsBottom, 0, (self.portrait) ? iphnXpaddingBottom : 0 , 0); 361 | } 362 | } 363 | 364 | 365 | /// Gesture 366 | - (void)panGestureRecognized:(UIPanGestureRecognizer *)recognizer { 367 | 368 | if (recognizer.state == UIGestureRecognizerStateBegan) { 369 | _savePositionContainer = self.transform.ty; 370 | } 371 | else if (recognizer.state == UIGestureRecognizerStateChanged) { 372 | CGAffineTransform 373 | _transform = self.transform; 374 | _transform.ty = (_savePositionContainer + [recognizer translationInView: self].y ); 375 | if (_transform.ty < 0) { 376 | _transform.ty = 0; 377 | } else if( _transform.ty < self.containerTop) { 378 | _transform.ty = ( self.containerTop / 2) + (_transform.ty / 2); 379 | 380 | CGFloat containerPositionBottom = (self.containerPosition == ContainerMoveTypeBottom) ?(self.containerTop + 5) :0; 381 | 382 | if( (self.scrollView.contentOffset.y + self.scrollView.frame.size.height + containerPositionBottom) < (int)self.scrollView.contentSize.height) { 383 | [self calculationScrollViewHeight:(_transform.ty + 5)]; 384 | } 385 | 386 | self.transform = _transform; 387 | } else { 388 | self.transform = _transform; 389 | } 390 | 391 | if ([self.delegate respondsToSelector:@selector(changeContainerMove:containerY:animated:)]) { 392 | [self.delegate changeContainerMove:ContainerMoveTypeTop containerY:self.transform.ty animated:NO]; 393 | } 394 | 395 | self.bottomButtonToMoveTop.hidden = YES; 396 | } 397 | else if (recognizer.state == UIGestureRecognizerStateEnded) { 398 | CGFloat velocityInViewY = [recognizer velocityInView:self].y; 399 | [self containerMoveForVelocityInView:velocityInViewY]; 400 | } 401 | } 402 | 403 | /// Container Move 404 | - (void)containerMoveForVelocityInView:(CGFloat)velocityInViewY { 405 | 406 | ContainerMoveType moveType; 407 | 408 | if( self.containerAllowMiddlePosition ) { 409 | if( self.transform.ty < self.containerMiddle ) { 410 | if(velocityInViewY < 0) { 411 | moveType = ContainerMoveTypeTop; 412 | } else { 413 | moveType = (2500 < velocityInViewY) ?ContainerMoveTypeBottom :ContainerMoveTypeMiddle; 414 | } 415 | } else { 416 | if(velocityInViewY < 0) { 417 | moveType = (velocityInViewY < (-2000)) ?ContainerMoveTypeTop :ContainerMoveTypeMiddle; 418 | } else { 419 | moveType = ContainerMoveTypeBottom; 420 | } 421 | } 422 | } else { 423 | if( self.transform.ty < self.containerTop ) { 424 | moveType = (750 < velocityInViewY) ?ContainerMoveTypeBottom :ContainerMoveTypeTop; 425 | } else { 426 | moveType = (velocityInViewY < 0) ?ContainerMoveTypeTop :ContainerMoveTypeBottom; 427 | } 428 | } 429 | [self containerMove:moveType]; 430 | 431 | } 432 | 433 | 434 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 435 | shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 436 | return NO; 437 | } 438 | 439 | 440 | - (void)changeBlurStyle:(ContainerStyle)styleType { 441 | 442 | self.containerStyle = styleType; 443 | 444 | self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleDefault; 445 | 446 | CGFloat alpha = 0.5; 447 | UIColor *graberColor = GRAYLEVEL(180); 448 | UIColor *separatorColor = [graberColor copy]; 449 | 450 | if((styleType == ContainerStyleDark) || 451 | (styleType == ContainerStyleDefault)) { 452 | graberColor = RGB(235, 239, 245); 453 | separatorColor = GRAYLEVEL(222); 454 | } 455 | 456 | if (styleType == ContainerStyleDark) alpha = 0.2; 457 | else if (styleType == ContainerStyleDefault) alpha = 1.0; 458 | 459 | if(styleType == ContainerStyleDark) { 460 | self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; 461 | } 462 | 463 | if(styleType != ContainerStyleDefault) { 464 | self.visualEffectView.backgroundColor = CLR_COLOR; 465 | self.visualEffectViewOrigin.hidden = NO; 466 | 467 | UIBlurEffectStyle effect; 468 | if (styleType == ContainerStyleLight) effect = UIBlurEffectStyleLight; 469 | else if (styleType == ContainerStyleExtraLight) effect = UIBlurEffectStyleExtraLight; 470 | else effect = UIBlurEffectStyleDark; 471 | 472 | self.visualEffectViewOrigin.effect = [UIBlurEffect effectWithStyle:effect]; 473 | } else { 474 | self.visualEffectView.backgroundColor = WHITE_COLOR; 475 | self.visualEffectViewOrigin.hidden = YES; 476 | } 477 | } 478 | 479 | 480 | #pragma mark - ContainerMove 481 | 482 | - (void)containerMove:(ContainerMoveType)moveType { 483 | [self containerMove:moveType animated:YES completion:nil]; 484 | } 485 | 486 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated { 487 | [self containerMove:moveType animated:animated completion:nil]; 488 | } 489 | 490 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion { 491 | 492 | self.containerPosition = moveType; 493 | 494 | CGFloat position = 0; 495 | 496 | switch (moveType) { 497 | case ContainerMoveTypeTop: position = self.containerTop + IPHONE_X_PADDING_TOP; break; 498 | case ContainerMoveTypeMiddle: position = self.containerMiddle; break; 499 | case ContainerMoveTypeBottom: position = self.containerBottom - IPHONE_X_PADDING_BOTTOM; break; 500 | case ContainerMoveTypeHide: position = SCREEN_HEIGHT; break; 501 | } 502 | 503 | [self containerMovePosition:position moveType:moveType animated:animated completion:completion]; 504 | } 505 | 506 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType { 507 | [self containerMoveCustomPosition:position moveType:moveType animated:YES completion:nil]; 508 | } 509 | 510 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated { 511 | [self containerMoveCustomPosition:position moveType:moveType animated:animated completion:nil]; 512 | } 513 | 514 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion { 515 | [self calculationScrollViewHeight:0]; 516 | 517 | self.containerPosition = moveType; 518 | [self containerMovePosition:position moveType:moveType animated:animated completion:completion]; 519 | } 520 | 521 | - (void)containerMovePosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion { 522 | 523 | if(_bottomButtonToMoveTop) self.bottomButtonToMoveTop.hidden = (moveType != ContainerMoveTypeBottom); 524 | 525 | self.scrollView.scrollEnabled = (moveType == ContainerMoveTypeTop); 526 | 527 | CGFloat containerPositionBottom = (self.containerPosition == ContainerMoveTypeBottom) ?(self.containerTop + 5) :0; 528 | 529 | CGAffineTransform _transform = CGAffineTransformMakeTranslation( 0, position); 530 | 531 | if ([self.delegate respondsToSelector:@selector(changeContainerMove:containerY:animated:)]) { 532 | [self.delegate changeContainerMove:moveType containerY:_transform.ty animated:animated]; 533 | } 534 | 535 | if(animated) { 536 | ANIMATION_SPRINGCOMP(.45, ^(void) { 537 | self.transform = _transform; 538 | }, ^(BOOL fin) { 539 | 540 | if(self.scrollView) { 541 | if( (self.scrollView.contentOffset.y + self.scrollView.frame.size.height + containerPositionBottom) < self.scrollView.contentSize.height) { 542 | [self calculationScrollViewHeight:containerPositionBottom]; 543 | } 544 | } 545 | if(completion) completion(); 546 | }); 547 | } else { 548 | self.transform = _transform; 549 | if(completion) completion(); 550 | } 551 | } 552 | 553 | 554 | 555 | @end 556 | -------------------------------------------------------------------------------- /ContainerView/ContainerViewController.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Рустам Мотыгуллин on 17.08.2018. 3 | // Copyright © 2018 GetTransfer. All rights reserved. 4 | 5 | #import 6 | #import "ContainerView.h" 7 | 8 | 9 | 10 | @interface ContainerViewController : UIViewController 11 | 12 | 13 | @property (strong, nonatomic) UIView *bottomView; 14 | @property (strong, nonatomic) UIButton *shadowButton; 15 | @property (strong, nonatomic) ContainerView *containerView; 16 | 17 | @property (nonatomic, weak) id delegate; 18 | 19 | 20 | /** 21 | @brief This view sets a custom header for the container. 22 | */ 23 | @property (strong, nonatomic) UIView *headerView; 24 | 25 | 26 | 27 | /** 28 | @brief This parameter indicates which type of move was last. 29 | */ 30 | @property (nonatomic, readonly) ContainerMoveType containerPosition; 31 | 32 | /** 33 | @brief This parameter to add a blur to the background of the container. 34 |   35 | There are 3 types of blur. Blur with hues of 36 | 1) black, 37 | 2) white, 38 | 3) white with low blur concentrations. 39 | 4) The last attribute turns off the blur, for a normal change of the background color. 40 | */ 41 | @property (nonatomic) ContainerStyle containerStyle; 42 | 43 | /** 44 | @brief This parameter for changing the rounding radius 45 | */ 46 | @property (nonatomic) CGFloat containerCornerRadius; 47 | 48 | /** 49 | @brief When moving the container, by default there are 2 positions (this is moving up and down). This parameter adds 3 position (move to the middle) 50 | */ 51 | @property (nonatomic) BOOL containerAllowMiddlePosition; 52 | 53 | 54 | 55 | /** 56 | @brief This parameter indicates whether to add a button when the container is at the bottom to animate the container upwards. 57 | */ 58 | @property (nonatomic) BOOL containerBottomButtonToMoveTop; 59 | 60 | 61 | /** 62 | @brief This parameter sets the shadow under container 63 | */ 64 | @property (nonatomic) BOOL containerShadowView; 65 | 66 | /** 67 | @brief This parameter sets the shadow in container 68 | */ 69 | @property (nonatomic) BOOL containerShadow; 70 | 71 | 72 | /** 73 | @brief This parameter allows you to zoom in on the screen under ContainerView. 74 | */ 75 | @property (nonatomic) BOOL containerZoom; 76 | 77 | /** 78 | @brief This parameter sets the new position value for the up move type. 79 | */ 80 | @property (nonatomic) CGFloat containerTop; 81 | 82 | /** 83 | @brief This parameter sets the new position value for the type of movement to the middle position. 84 | */ 85 | @property (nonatomic) CGFloat containerMiddle; 86 | 87 | /** 88 | @brief This parameter sets the new position value for the type of movement to the middle position. 89 | */ 90 | @property (nonatomic) CGFloat containerBottom; 91 | 92 | 93 | /** 94 | @brief This method for animated container movement, at fixed positions 95 |   96 | @param moveType There are 4 types of movement. Moving 1) up, 2) middle, 3) down, 4) hiding in the most down beyond the limits of visibility 97 | */ 98 | - (void)containerMove:(ContainerMoveType)moveType; 99 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated; 100 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion; 101 | 102 | /** 103 | @brief This method for animated container movement, by user position. 104 | 105 | @param position Custom position 106 | */ 107 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType; 108 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated; 109 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion; 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /ContainerView/ContainerViewController.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Рустам Мотыгуллин on 17.08.2018. 3 | // Copyright © 2018 GetTransfer. All rights reserved. 4 | 5 | #import "ContainerViewController.h" 6 | 7 | 8 | @interface ContainerViewController () { 9 | BOOL bordersRunContainer; 10 | BOOL onceEnded; 11 | BOOL bottomDeceleratingDisable; 12 | BOOL onceScrollingBeginDragging; 13 | BOOL scrollBegin; 14 | CGFloat startScrollPosition; 15 | CGAffineTransform selfTransform; 16 | BOOL _containerShadowView; 17 | BOOL _containerZoom; 18 | } 19 | 20 | @end 21 | 22 | @implementation ContainerViewController 23 | 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | 28 | self.automaticallyAdjustsScrollViewInsets = NO; 29 | 30 | [self.view insertSubview:self.bottomView atIndex:0]; 31 | [self.view addSubview:self.shadowButton]; 32 | 33 | 34 | self.containerShadowView = YES; 35 | self.containerZoom = YES; 36 | 37 | [self.view addSubview:self.containerView]; 38 | } 39 | 40 | - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { 41 | [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 42 | 43 | BOOL addedTop = self.containerView.firstAddedTop; 44 | BOOL addedMiddle = self.containerView.firstAddedMiddle; 45 | BOOL addedBottom = self.containerView.firstAddedBottom; 46 | 47 | CGFloat top = addedTop ? self.containerTop : CUSTOM_TOP; 48 | CGFloat middle = addedMiddle ? [self.containerView getContainerMiddle] : CUSTOM_MIDDLE; 49 | CGFloat bottom = addedBottom ? [self.containerView getContainerBottom] : CUSTOM_BOTTOM; 50 | 51 | [self.containerView transitionToSizeTop:top middle:middle bottom:bottom size:size]; 52 | } 53 | 54 | #pragma mark - Create 55 | 56 | 57 | - (ContainerView *)containerView { 58 | 59 | if(!_containerView) { 60 | ContainerView * 61 | container = [[ContainerView alloc] initWithFrame: CGRectMake( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT +50 )]; 62 | container.delegate = self; 63 | _containerView = container; 64 | } 65 | return _containerView; 66 | } 67 | 68 | - (UIView *)bottomView { 69 | if(!_bottomView) { 70 | 71 | UIView * 72 | view = [[UIView alloc]initWithFrame:self.view.bounds]; 73 | view.backgroundColor = [UIColor clearColor]; 74 | view.clipsToBounds = YES; 75 | view.autoresizingMask = 76 | (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | 77 | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin); 78 | _bottomView = view; 79 | for( UIView * v in self.view.subviews ) { 80 | [_bottomView addSubview:v]; 81 | } 82 | } 83 | return _bottomView; 84 | } 85 | 86 | - (UIButton *)shadowButton { 87 | 88 | if(!_shadowButton) { 89 | UIButton * 90 | shadow = [UIButton buttonWithType:UIButtonTypeCustom]; 91 | [shadow addTarget:self action:@selector(shadowButtonAction) forControlEvents:UIControlEventTouchUpInside]; 92 | shadow.frame = FRAME; 93 | shadow.backgroundColor = [UIColor blackColor]; 94 | shadow.alpha = 0; 95 | shadow.autoresizingMask = 96 | (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin); 97 | _shadowButton = shadow; 98 | 99 | [self.view addSubview:_shadowButton]; 100 | } 101 | return _shadowButton; 102 | } 103 | 104 | #pragma mark - ContainerView Delegate 105 | 106 | - (void)changeContainerMove:(ContainerMoveType)containerMove containerY:(CGFloat)containerY animated:(BOOL)animated { 107 | 108 | if(containerMove == ContainerMoveTypeBottom) { 109 | [self.view endEditing:YES]; 110 | } 111 | 112 | if(animated) { 113 | ANIMATION_SPRING(.45,^(void){ 114 | [self changeScalesImageAndShadowLevel:containerY]; 115 | }); 116 | } else { 117 | [self changeScalesImageAndShadowLevel:containerY]; 118 | } 119 | } 120 | 121 | 122 | 123 | #pragma mark - Getter Setter 124 | 125 | - (void)setDelegate:(id)delegate { 126 | self.containerView.delegate = delegate; 127 | } 128 | 129 | - (id)delegate { 130 | return self.containerView.delegate; 131 | } 132 | 133 | - (void)setHeaderView:(UIView *)headerView { 134 | self.containerView.headerView = headerView; 135 | } 136 | 137 | - (UIView *)headerView { 138 | return self.containerView.headerView; 139 | } 140 | 141 | 142 | - (void)setContainerShadow:(BOOL)containerShadow { 143 | self.containerView.containerShadow =containerShadow; 144 | } 145 | - (BOOL)containerShadow { 146 | return self.containerView.containerShadow; 147 | } 148 | 149 | 150 | 151 | - (void)setContainerBottomButtonToMoveTop:(BOOL)containerBottomButtonToMoveTop { 152 | self.containerView.containerBottomButtonToMoveTop = containerBottomButtonToMoveTop; 153 | } 154 | 155 | - (BOOL)containerBottomButtonToMoveTop { 156 | return self.containerView.containerBottomButtonToMoveTop; 157 | } 158 | 159 | 160 | - (void)setContainerShadowView:(BOOL)value { 161 | _shadowButton.hidden = (!value); 162 | _containerShadowView = value; 163 | } 164 | 165 | - (BOOL)containerShadowView { 166 | return _shadowButton != nil; 167 | } 168 | 169 | - (void)shadowButtonAction { 170 | [self containerMove:ContainerMoveTypeBottom]; 171 | } 172 | 173 | 174 | - (void)setContainerZoom:(BOOL)containerZoom { 175 | _containerZoom = containerZoom; 176 | } 177 | 178 | - (BOOL)containerZoom { 179 | return _containerZoom; 180 | } 181 | 182 | - (void)setContainerAllowMiddlePosition:(BOOL)containerAllowMiddlePosition { 183 | self.containerView.containerAllowMiddlePosition = containerAllowMiddlePosition; 184 | } 185 | 186 | - (BOOL)containerAllowMiddlePosition { 187 | return self.containerView.containerAllowMiddlePosition; 188 | } 189 | 190 | - (void)setContainerStyle:(ContainerStyle)containerStyle { 191 | [self.containerView changeBlurStyle:containerStyle]; 192 | } 193 | 194 | - (ContainerStyle)containerStyle { 195 | return self.containerView.containerStyle; 196 | } 197 | 198 | 199 | - (void)setContainerCornerRadius:(CGFloat)containerCornerRadius { 200 | self.containerView.containerCornerRadius = containerCornerRadius; 201 | } 202 | 203 | - (CGFloat)containerCornerRadius { 204 | return self.containerView.containerCornerRadius; 205 | } 206 | 207 | 208 | 209 | #pragma mark - Container Set/Get Top/Middle/Bottom position 210 | 211 | 212 | 213 | - (void)setContainerTop:(CGFloat)containerTop { 214 | self.containerView.containerTop = containerTop; 215 | } 216 | 217 | - (CGFloat)containerTop { 218 | return self.containerView.containerTop; 219 | } 220 | 221 | 222 | - (void)setContainerMiddle:(CGFloat)containerMiddle { 223 | self.containerView.containerMiddle = containerMiddle; 224 | } 225 | 226 | - (CGFloat)containerMiddle { 227 | return self.containerView.containerMiddle; 228 | } 229 | 230 | - (void)setContainerBottom:(CGFloat)containerBottom { 231 | self.containerView.containerBottom = containerBottom; 232 | } 233 | 234 | - (CGFloat)containerBottom { 235 | return self.containerView.containerBottom; 236 | } 237 | 238 | 239 | 240 | #pragma mark - Container Move 241 | 242 | - (ContainerMoveType)containerPosition { 243 | return self.containerView.containerPosition; 244 | } 245 | 246 | - (void)containerMove:(ContainerMoveType)moveType { 247 | [self.containerView containerMove:moveType]; 248 | } 249 | 250 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated { 251 | [self.containerView containerMove:moveType animated:animated]; 252 | } 253 | 254 | - (void)containerMove:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion { 255 | [self.containerView containerMove:moveType animated:animated completion:completion]; 256 | } 257 | 258 | 259 | 260 | 261 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType { 262 | [self.containerView containerMoveCustomPosition:position moveType:moveType]; 263 | } 264 | 265 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated { 266 | [self.containerView containerMoveCustomPosition:position moveType:moveType animated:animated]; 267 | } 268 | 269 | - (void)containerMoveCustomPosition:(CGFloat)position moveType:(ContainerMoveType)moveType animated:(BOOL)animated completion:(void (^)(void))completion { 270 | [self.containerView containerMoveCustomPosition:position moveType:moveType animated:animated completion:completion]; 271 | } 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | #pragma mark - Change ShadowLevel 282 | 283 | - (void)changeScalesImageAndShadowLevel:(CGFloat)containerFrameY { 284 | 285 | CGFloat selfCenter = self.containerView.containerMiddle; 286 | 287 | 288 | if(containerFrameY < selfCenter) { 289 | 290 | CGFloat procent = (((selfCenter - containerFrameY) / selfCenter) / 2); 291 | 292 | CGAffineTransform transform = CGAffineTransformMakeScale( 1. - (procent / 5), 1. - (procent / 5)); 293 | 294 | if(self.containerZoom) { 295 | self.bottomView.transform = transform; 296 | self.bottomView.layer.cornerRadius = (procent * 24); 297 | } else { 298 | self.bottomView.transform = CGAffineTransformIdentity; 299 | self.bottomView.layer.cornerRadius = 0; 300 | } 301 | 302 | self.shadowButton.alpha = procent; 303 | 304 | CGFloat height; 305 | if(self.containerView.portrait) 306 | height = (containerFrameY + self.containerView.containerCornerRadius +5); 307 | else height = SCREEN_HEIGHT; 308 | 309 | self.shadowButton.frame = CGRectMake( self.shadowButton.frame.origin.x,self.shadowButton.frame.origin.y, self.shadowButton.frame.size.width, height); 310 | } else { 311 | self.bottomView.transform = CGAffineTransformIdentity; 312 | self.bottomView.layer.cornerRadius = 0; 313 | 314 | self.shadowButton.alpha = 0.; 315 | self.shadowButton.frame = CGRectMake( self.shadowButton.frame.origin.x, self.shadowButton.frame.origin.y, self.shadowButton.frame.size.width, SCREEN_HEIGHT); 316 | } 317 | } 318 | 319 | 320 | 321 | 322 | #pragma mark - Scroll Delegate 323 | 324 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 325 | { 326 | CGFloat velocityInViewY = [scrollView.panGestureRecognizer velocityInView: self.view].y; 327 | CGFloat translationInViewY = [scrollView.panGestureRecognizer translationInView:self.view].y; 328 | 329 | if(scrollView.panGestureRecognizer.state == UIGestureRecognizerStateChanged) { 330 | [self.view endEditing:YES]; 331 | } 332 | 333 | if((scrollView.panGestureRecognizer.state) && (scrollView.contentOffset.y <= 0)) { 334 | scrollView.showsVerticalScrollIndicator = NO; 335 | scrollView.contentOffset = CGPointMake( scrollView.contentOffset.x, 0 ); 336 | } else { 337 | scrollView.showsVerticalScrollIndicator = YES; 338 | } 339 | 340 | bordersRunContainer = ( (scrollView.contentOffset.y == 0) && (0 < velocityInViewY)); 341 | 342 | selfTransform = self.containerView.transform; 343 | 344 | 345 | // TODO: Implement these. 346 | // if (NAV_ADDED) { 347 | // UINavigationController * nav = (UINavigationController *)ROOT_VC; 348 | // if(!nav.navigationBarHidden) { 349 | // if(!nav.navigationBar.translucent) { 350 | // 351 | // } 352 | // if (@available(iOS 11.0, *)) { 353 | // if(!nav.navigationBar.prefersLargeTitles) { 354 | // 355 | // } 356 | // } 357 | // } 358 | // } 359 | 360 | 361 | CGFloat top = self.containerView.containerTop; 362 | top += IPHONE_X_PADDING_TOP; 363 | 364 | 365 | if(scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) 366 | onceScrollingBeginDragging = NO; 367 | 368 | if(bordersRunContainer) { 369 | 370 | onceEnded = NO; 371 | onceScrollingBeginDragging = NO; 372 | 373 | selfTransform.ty = ((top - startScrollPosition) + translationInViewY ); 374 | if(selfTransform.ty < top) selfTransform.ty = top; 375 | 376 | if(scrollBegin) 377 | { 378 | ANIMATION_SPRING(.325, ^(void) { 379 | self.containerView.transform = self->selfTransform; 380 | }); 381 | 382 | scrollBegin = NO; 383 | 384 | } else { 385 | self.containerView.transform = selfTransform; 386 | } 387 | } 388 | else 389 | { 390 | if((top == selfTransform.ty) && !onceScrollingBeginDragging) { 391 | onceScrollingBeginDragging = YES; 392 | 393 | CGFloat headerHeight = (self.containerView.headerView) ?self.containerView.headerView.frame.size.height :0; 394 | CGFloat top = (self.containerView.containerTop == 0) ? CUSTOM_TOP : self.containerView.containerTop; 395 | CGFloat iphnX = IPHONE_X_PADDING_TOP; 396 | 397 | CGFloat height = (SCREEN_HEIGHT - (top + headerHeight + iphnX )); 398 | 399 | if(scrollView.frame.size.height != height) { 400 | 401 | ANIMATION_SPRING( .45, ^(void) { 402 | scrollView.frame = CGRectMake( 403 | scrollView.frame.origin.x, headerHeight , 404 | scrollView.frame.size.width, height 405 | ); 406 | }); 407 | } 408 | } 409 | 410 | 411 | if(top < selfTransform.ty) 412 | { 413 | if (velocityInViewY < 0. ) 414 | { 415 | if(self.containerView.containerPosition == ContainerMoveTypeTop) { 416 | scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, 0 ); 417 | } 418 | 419 | selfTransform = self.containerView.transform; 420 | selfTransform.ty = ((top - startScrollPosition) + translationInViewY ); 421 | 422 | if(selfTransform.ty < top) selfTransform.ty = top; 423 | 424 | self.containerView.transform = selfTransform; 425 | } 426 | } 427 | } 428 | 429 | 430 | [self changeScalesImageAndShadowLevel:selfTransform.ty]; 431 | 432 | } 433 | 434 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 435 | { 436 | startScrollPosition = scrollView.contentOffset.y; 437 | 438 | if(bottomDeceleratingDisable) return; 439 | 440 | scrollBegin = YES; 441 | if(startScrollPosition < 0) startScrollPosition = 0; 442 | } 443 | 444 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 445 | { 446 | if(bottomDeceleratingDisable) return; 447 | CGFloat velocityInViewY = [scrollView.panGestureRecognizer velocityInView:WINDOW].y; 448 | 449 | if(!self.containerView) return; 450 | 451 | if(!onceEnded) 452 | { 453 | onceEnded = YES; 454 | [self.containerView containerMoveForVelocityInView:velocityInViewY]; 455 | } 456 | } 457 | 458 | 459 | @end 460 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4617423021AC949200730CC5 /* DemoModalViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4617422F21AC949200730CC5 /* DemoModalViewController.m */; }; 11 | 4620C5FD219F8D480029326D /* DemoHeaderViews.m in Sources */ = {isa = PBXBuildFile; fileRef = 4620C5FC219F8D480029326D /* DemoHeaderViews.m */; }; 12 | 46343B8020F28E4B00EF63F7 /* ProximaNova-Extrabld.otf in Resources */ = {isa = PBXBuildFile; fileRef = 46343B7E20F28E4B00EF63F7 /* ProximaNova-Extrabld.otf */; }; 13 | 46343B8120F28E4B00EF63F7 /* ProximaNova-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 46343B7F20F28E4B00EF63F7 /* ProximaNova-Regular.otf */; }; 14 | 4648BFCC210E3FA60007D083 /* DemoTableDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4648BFCB210E3FA60007D083 /* DemoTableDelegate.m */; }; 15 | 4648BFCF210E3FC60007D083 /* DemoCollectionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4648BFCE210E3FC60007D083 /* DemoCollectionDelegate.m */; }; 16 | 4689A7B920EC081A00BC7C8A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689A7B820EC081A00BC7C8A /* AppDelegate.m */; }; 17 | 4689A7BC20EC081A00BC7C8A /* DemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689A7BB20EC081A00BC7C8A /* DemoViewController.m */; }; 18 | 4689A7BF20EC081A00BC7C8A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4689A7BD20EC081A00BC7C8A /* Main.storyboard */; }; 19 | 4689A7C120EC081C00BC7C8A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4689A7C020EC081C00BC7C8A /* Assets.xcassets */; }; 20 | 4689A7C420EC081C00BC7C8A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4689A7C220EC081C00BC7C8A /* LaunchScreen.storyboard */; }; 21 | 4689A7C720EC081C00BC7C8A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689A7C620EC081C00BC7C8A /* main.m */; }; 22 | 4689A7DC20EC08DE00BC7C8A /* DemoTableDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 4689A7D720EC08DE00BC7C8A /* DemoTableDataSource.m */; }; 23 | 46A1F41C21A5ED1500541435 /* DemoTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 46A1F41B21A5ED1500541435 /* DemoTableCell.m */; }; 24 | 46A1F41F21A5ED8F00541435 /* DemoCollectionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 46A1F41E21A5ED8F00541435 /* DemoCollectionCell.m */; }; 25 | 46C519292126267B00A6F607 /* ContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 46C519262126267B00A6F607 /* ContainerView.m */; }; 26 | 46C5192A2126267B00A6F607 /* ContainerScrollDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 46C519272126267B00A6F607 /* ContainerScrollDelegate.m */; }; 27 | 4A0ACB2521AC517B00465221 /* DemoScrollViews.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A0ACB2421AC517B00465221 /* DemoScrollViews.m */; }; 28 | 4A164E9221B1418B0056DCF4 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 4A164E9121B1418B0056DCF4 /* README.md */; }; 29 | 4A164E9421B1418F0056DCF4 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 4A164E9321B1418F0056DCF4 /* LICENSE */; }; 30 | 4A94AE7A21A3F6C90045A212 /* ContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A94AE7821A3F6C90045A212 /* ContainerViewController.m */; }; 31 | 4A9527E520F8EB4D000DFDFB /* DemoCollectionDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A9527E320F8EB4D000DFDFB /* DemoCollectionDataSource.m */; }; 32 | /* End PBXBuildFile section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 4617422E21AC949200730CC5 /* DemoModalViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoModalViewController.h; sourceTree = ""; }; 36 | 4617422F21AC949200730CC5 /* DemoModalViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoModalViewController.m; sourceTree = ""; }; 37 | 4620C5FB219F8D480029326D /* DemoHeaderViews.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoHeaderViews.h; sourceTree = ""; }; 38 | 4620C5FC219F8D480029326D /* DemoHeaderViews.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoHeaderViews.m; sourceTree = ""; }; 39 | 46343B7E20F28E4B00EF63F7 /* ProximaNova-Extrabld.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ProximaNova-Extrabld.otf"; sourceTree = ""; }; 40 | 46343B7F20F28E4B00EF63F7 /* ProximaNova-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ProximaNova-Regular.otf"; sourceTree = ""; }; 41 | 4648BFCA210E3FA60007D083 /* DemoTableDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoTableDelegate.h; sourceTree = ""; }; 42 | 4648BFCB210E3FA60007D083 /* DemoTableDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoTableDelegate.m; sourceTree = ""; }; 43 | 4648BFCD210E3FC60007D083 /* DemoCollectionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoCollectionDelegate.h; sourceTree = ""; }; 44 | 4648BFCE210E3FC60007D083 /* DemoCollectionDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoCollectionDelegate.m; sourceTree = ""; }; 45 | 4689A7B420EC081A00BC7C8A /* DemoContainerView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoContainerView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 4689A7B720EC081A00BC7C8A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 47 | 4689A7B820EC081A00BC7C8A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 48 | 4689A7BA20EC081A00BC7C8A /* DemoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; }; 49 | 4689A7BB20EC081A00BC7C8A /* DemoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoViewController.m; sourceTree = ""; }; 50 | 4689A7BE20EC081A00BC7C8A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 51 | 4689A7C020EC081C00BC7C8A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52 | 4689A7C320EC081C00BC7C8A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 53 | 4689A7C520EC081C00BC7C8A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | 4689A7C620EC081C00BC7C8A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | 4689A7D620EC08DE00BC7C8A /* DemoTableDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoTableDataSource.h; sourceTree = ""; }; 56 | 4689A7D720EC08DE00BC7C8A /* DemoTableDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoTableDataSource.m; sourceTree = ""; }; 57 | 46A1F41A21A5ED1500541435 /* DemoTableCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoTableCell.h; sourceTree = ""; }; 58 | 46A1F41B21A5ED1500541435 /* DemoTableCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoTableCell.m; sourceTree = ""; }; 59 | 46A1F41D21A5ED8F00541435 /* DemoCollectionCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoCollectionCell.h; sourceTree = ""; }; 60 | 46A1F41E21A5ED8F00541435 /* DemoCollectionCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoCollectionCell.m; sourceTree = ""; }; 61 | 46C519232126267A00A6F607 /* ContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerView.h; sourceTree = ""; }; 62 | 46C519242126267B00A6F607 /* ContainerDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerDefines.h; sourceTree = ""; }; 63 | 46C519252126267B00A6F607 /* ContainerScrollDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerScrollDelegate.h; sourceTree = ""; }; 64 | 46C519262126267B00A6F607 /* ContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContainerView.m; sourceTree = ""; }; 65 | 46C519272126267B00A6F607 /* ContainerScrollDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContainerScrollDelegate.m; sourceTree = ""; }; 66 | 46C519282126267B00A6F607 /* ContainerTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerTypes.h; sourceTree = ""; }; 67 | 4A0ACB2321AC517B00465221 /* DemoScrollViews.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoScrollViews.h; sourceTree = ""; }; 68 | 4A0ACB2421AC517B00465221 /* DemoScrollViews.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoScrollViews.m; sourceTree = ""; }; 69 | 4A164E9121B1418B0056DCF4 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 70 | 4A164E9321B1418F0056DCF4 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 71 | 4A94AE7821A3F6C90045A212 /* ContainerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContainerViewController.m; sourceTree = ""; }; 72 | 4A94AE7921A3F6C90045A212 /* ContainerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerViewController.h; sourceTree = ""; }; 73 | 4A9527E320F8EB4D000DFDFB /* DemoCollectionDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoCollectionDataSource.m; sourceTree = ""; }; 74 | 4A9527E420F8EB4D000DFDFB /* DemoCollectionDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoCollectionDataSource.h; sourceTree = ""; }; 75 | /* End PBXFileReference section */ 76 | 77 | /* Begin PBXFrameworksBuildPhase section */ 78 | 4689A7B120EC081A00BC7C8A /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXFrameworksBuildPhase section */ 86 | 87 | /* Begin PBXGroup section */ 88 | 4620C5FE219F8D8C0029326D /* DemoHeaderViews */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 4620C5FB219F8D480029326D /* DemoHeaderViews.h */, 92 | 4620C5FC219F8D480029326D /* DemoHeaderViews.m */, 93 | ); 94 | path = DemoHeaderViews; 95 | sourceTree = ""; 96 | }; 97 | 4648BFD0210E545F0007D083 /* DemoProtocolsTableView */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 4648BFCA210E3FA60007D083 /* DemoTableDelegate.h */, 101 | 4648BFCB210E3FA60007D083 /* DemoTableDelegate.m */, 102 | 4689A7D620EC08DE00BC7C8A /* DemoTableDataSource.h */, 103 | 4689A7D720EC08DE00BC7C8A /* DemoTableDataSource.m */, 104 | ); 105 | path = DemoProtocolsTableView; 106 | sourceTree = ""; 107 | }; 108 | 4648BFD1210E54650007D083 /* DemoProtocolsCollectionView */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 4648BFCD210E3FC60007D083 /* DemoCollectionDelegate.h */, 112 | 4648BFCE210E3FC60007D083 /* DemoCollectionDelegate.m */, 113 | 4A9527E420F8EB4D000DFDFB /* DemoCollectionDataSource.h */, 114 | 4A9527E320F8EB4D000DFDFB /* DemoCollectionDataSource.m */, 115 | ); 116 | path = DemoProtocolsCollectionView; 117 | sourceTree = ""; 118 | }; 119 | 4689A7AB20EC081A00BC7C8A = { 120 | isa = PBXGroup; 121 | children = ( 122 | 4A164E9121B1418B0056DCF4 /* README.md */, 123 | 4A164E9321B1418F0056DCF4 /* LICENSE */, 124 | 46C519222126264600A6F607 /* ContainerView */, 125 | 4689A7B620EC081A00BC7C8A /* DemoContainerView */, 126 | 4689A7B520EC081A00BC7C8A /* Products */, 127 | ); 128 | sourceTree = ""; 129 | }; 130 | 4689A7B520EC081A00BC7C8A /* Products */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 4689A7B420EC081A00BC7C8A /* DemoContainerView.app */, 134 | ); 135 | name = Products; 136 | sourceTree = ""; 137 | }; 138 | 4689A7B620EC081A00BC7C8A /* DemoContainerView */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 4689A7B720EC081A00BC7C8A /* AppDelegate.h */, 142 | 4689A7B820EC081A00BC7C8A /* AppDelegate.m */, 143 | 46E356C121261C2400850BD8 /* Demo */, 144 | 46EA455920FD258F00C0FAE0 /* Resources */, 145 | 4689A7BD20EC081A00BC7C8A /* Main.storyboard */, 146 | 4689A7C020EC081C00BC7C8A /* Assets.xcassets */, 147 | 4689A7C220EC081C00BC7C8A /* LaunchScreen.storyboard */, 148 | 4689A7C520EC081C00BC7C8A /* Info.plist */, 149 | 46EA455A20FD298000C0FAE0 /* Supporting Files */, 150 | ); 151 | path = DemoContainerView; 152 | sourceTree = ""; 153 | }; 154 | 46C519222126264600A6F607 /* ContainerView */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 46C519242126267B00A6F607 /* ContainerDefines.h */, 158 | 46C519282126267B00A6F607 /* ContainerTypes.h */, 159 | 46C519252126267B00A6F607 /* ContainerScrollDelegate.h */, 160 | 46C519272126267B00A6F607 /* ContainerScrollDelegate.m */, 161 | 4A94AE7921A3F6C90045A212 /* ContainerViewController.h */, 162 | 4A94AE7821A3F6C90045A212 /* ContainerViewController.m */, 163 | 46C519232126267A00A6F607 /* ContainerView.h */, 164 | 46C519262126267B00A6F607 /* ContainerView.m */, 165 | ); 166 | name = ContainerView; 167 | path = ../ContainerView; 168 | sourceTree = ""; 169 | }; 170 | 46E356C121261C2400850BD8 /* Demo */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | 4620C5FE219F8D8C0029326D /* DemoHeaderViews */, 174 | 4A0ACB2221AC515100465221 /* DemoScrollViews */, 175 | 4689A7BA20EC081A00BC7C8A /* DemoViewController.h */, 176 | 4689A7BB20EC081A00BC7C8A /* DemoViewController.m */, 177 | 4617422E21AC949200730CC5 /* DemoModalViewController.h */, 178 | 4617422F21AC949200730CC5 /* DemoModalViewController.m */, 179 | ); 180 | path = Demo; 181 | sourceTree = ""; 182 | }; 183 | 46EA455920FD258F00C0FAE0 /* Resources */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 46343B7E20F28E4B00EF63F7 /* ProximaNova-Extrabld.otf */, 187 | 46343B7F20F28E4B00EF63F7 /* ProximaNova-Regular.otf */, 188 | ); 189 | path = Resources; 190 | sourceTree = ""; 191 | }; 192 | 46EA455A20FD298000C0FAE0 /* Supporting Files */ = { 193 | isa = PBXGroup; 194 | children = ( 195 | 4689A7C620EC081C00BC7C8A /* main.m */, 196 | ); 197 | name = "Supporting Files"; 198 | sourceTree = ""; 199 | }; 200 | 4A0ACB2221AC515100465221 /* DemoScrollViews */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | 4A0ACB2621AC528300465221 /* DemoCells */, 204 | 4648BFD0210E545F0007D083 /* DemoProtocolsTableView */, 205 | 4648BFD1210E54650007D083 /* DemoProtocolsCollectionView */, 206 | 4A0ACB2321AC517B00465221 /* DemoScrollViews.h */, 207 | 4A0ACB2421AC517B00465221 /* DemoScrollViews.m */, 208 | ); 209 | path = DemoScrollViews; 210 | sourceTree = ""; 211 | }; 212 | 4A0ACB2621AC528300465221 /* DemoCells */ = { 213 | isa = PBXGroup; 214 | children = ( 215 | 46A1F41A21A5ED1500541435 /* DemoTableCell.h */, 216 | 46A1F41B21A5ED1500541435 /* DemoTableCell.m */, 217 | 46A1F41D21A5ED8F00541435 /* DemoCollectionCell.h */, 218 | 46A1F41E21A5ED8F00541435 /* DemoCollectionCell.m */, 219 | ); 220 | path = DemoCells; 221 | sourceTree = ""; 222 | }; 223 | /* End PBXGroup section */ 224 | 225 | /* Begin PBXNativeTarget section */ 226 | 4689A7B320EC081A00BC7C8A /* DemoContainerView */ = { 227 | isa = PBXNativeTarget; 228 | buildConfigurationList = 4689A7CA20EC081C00BC7C8A /* Build configuration list for PBXNativeTarget "DemoContainerView" */; 229 | buildPhases = ( 230 | 4689A7B020EC081A00BC7C8A /* Sources */, 231 | 4689A7B120EC081A00BC7C8A /* Frameworks */, 232 | 4689A7B220EC081A00BC7C8A /* Resources */, 233 | ); 234 | buildRules = ( 235 | ); 236 | dependencies = ( 237 | ); 238 | name = DemoContainerView; 239 | productName = containerView; 240 | productReference = 4689A7B420EC081A00BC7C8A /* DemoContainerView.app */; 241 | productType = "com.apple.product-type.application"; 242 | }; 243 | /* End PBXNativeTarget section */ 244 | 245 | /* Begin PBXProject section */ 246 | 4689A7AC20EC081A00BC7C8A /* Project object */ = { 247 | isa = PBXProject; 248 | attributes = { 249 | LastUpgradeCheck = 0940; 250 | ORGANIZATIONNAME = mrusta; 251 | TargetAttributes = { 252 | 4689A7B320EC081A00BC7C8A = { 253 | CreatedOnToolsVersion = 9.4.1; 254 | ProvisioningStyle = Automatic; 255 | }; 256 | }; 257 | }; 258 | buildConfigurationList = 4689A7AF20EC081A00BC7C8A /* Build configuration list for PBXProject "DemoContainerView" */; 259 | compatibilityVersion = "Xcode 8.0"; 260 | developmentRegion = en; 261 | hasScannedForEncodings = 0; 262 | knownRegions = ( 263 | en, 264 | Base, 265 | ); 266 | mainGroup = 4689A7AB20EC081A00BC7C8A; 267 | productRefGroup = 4689A7B520EC081A00BC7C8A /* Products */; 268 | projectDirPath = ""; 269 | projectRoot = ""; 270 | targets = ( 271 | 4689A7B320EC081A00BC7C8A /* DemoContainerView */, 272 | ); 273 | }; 274 | /* End PBXProject section */ 275 | 276 | /* Begin PBXResourcesBuildPhase section */ 277 | 4689A7B220EC081A00BC7C8A /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | 4689A7C420EC081C00BC7C8A /* LaunchScreen.storyboard in Resources */, 282 | 46343B8120F28E4B00EF63F7 /* ProximaNova-Regular.otf in Resources */, 283 | 4689A7C120EC081C00BC7C8A /* Assets.xcassets in Resources */, 284 | 4A164E9421B1418F0056DCF4 /* LICENSE in Resources */, 285 | 4A164E9221B1418B0056DCF4 /* README.md in Resources */, 286 | 46343B8020F28E4B00EF63F7 /* ProximaNova-Extrabld.otf in Resources */, 287 | 4689A7BF20EC081A00BC7C8A /* Main.storyboard in Resources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | /* End PBXResourcesBuildPhase section */ 292 | 293 | /* Begin PBXSourcesBuildPhase section */ 294 | 4689A7B020EC081A00BC7C8A /* Sources */ = { 295 | isa = PBXSourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 4689A7BC20EC081A00BC7C8A /* DemoViewController.m in Sources */, 299 | 4620C5FD219F8D480029326D /* DemoHeaderViews.m in Sources */, 300 | 46A1F41F21A5ED8F00541435 /* DemoCollectionCell.m in Sources */, 301 | 4617423021AC949200730CC5 /* DemoModalViewController.m in Sources */, 302 | 4689A7C720EC081C00BC7C8A /* main.m in Sources */, 303 | 4648BFCF210E3FC60007D083 /* DemoCollectionDelegate.m in Sources */, 304 | 4A9527E520F8EB4D000DFDFB /* DemoCollectionDataSource.m in Sources */, 305 | 4648BFCC210E3FA60007D083 /* DemoTableDelegate.m in Sources */, 306 | 46A1F41C21A5ED1500541435 /* DemoTableCell.m in Sources */, 307 | 4689A7DC20EC08DE00BC7C8A /* DemoTableDataSource.m in Sources */, 308 | 46C5192A2126267B00A6F607 /* ContainerScrollDelegate.m in Sources */, 309 | 4A0ACB2521AC517B00465221 /* DemoScrollViews.m in Sources */, 310 | 4A94AE7A21A3F6C90045A212 /* ContainerViewController.m in Sources */, 311 | 46C519292126267B00A6F607 /* ContainerView.m in Sources */, 312 | 4689A7B920EC081A00BC7C8A /* AppDelegate.m in Sources */, 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | /* End PBXSourcesBuildPhase section */ 317 | 318 | /* Begin PBXVariantGroup section */ 319 | 4689A7BD20EC081A00BC7C8A /* Main.storyboard */ = { 320 | isa = PBXVariantGroup; 321 | children = ( 322 | 4689A7BE20EC081A00BC7C8A /* Base */, 323 | ); 324 | name = Main.storyboard; 325 | sourceTree = ""; 326 | }; 327 | 4689A7C220EC081C00BC7C8A /* LaunchScreen.storyboard */ = { 328 | isa = PBXVariantGroup; 329 | children = ( 330 | 4689A7C320EC081C00BC7C8A /* Base */, 331 | ); 332 | name = LaunchScreen.storyboard; 333 | sourceTree = ""; 334 | }; 335 | /* End PBXVariantGroup section */ 336 | 337 | /* Begin XCBuildConfiguration section */ 338 | 4689A7C820EC081C00BC7C8A /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | CLANG_ANALYZER_NONNULL = YES; 343 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 344 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 345 | CLANG_CXX_LIBRARY = "libc++"; 346 | CLANG_ENABLE_MODULES = YES; 347 | CLANG_ENABLE_OBJC_ARC = YES; 348 | CLANG_ENABLE_OBJC_WEAK = YES; 349 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 350 | CLANG_WARN_BOOL_CONVERSION = YES; 351 | CLANG_WARN_COMMA = YES; 352 | CLANG_WARN_CONSTANT_CONVERSION = YES; 353 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 354 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 355 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 356 | CLANG_WARN_EMPTY_BODY = YES; 357 | CLANG_WARN_ENUM_CONVERSION = YES; 358 | CLANG_WARN_INFINITE_RECURSION = YES; 359 | CLANG_WARN_INT_CONVERSION = YES; 360 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 361 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 362 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 363 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 364 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 365 | CLANG_WARN_STRICT_PROTOTYPES = YES; 366 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 367 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 368 | CLANG_WARN_UNREACHABLE_CODE = YES; 369 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 370 | CODE_SIGN_IDENTITY = "iPhone Developer"; 371 | COPY_PHASE_STRIP = NO; 372 | DEBUG_INFORMATION_FORMAT = dwarf; 373 | ENABLE_STRICT_OBJC_MSGSEND = YES; 374 | ENABLE_TESTABILITY = YES; 375 | GCC_C_LANGUAGE_STANDARD = gnu11; 376 | GCC_DYNAMIC_NO_PIC = NO; 377 | GCC_NO_COMMON_BLOCKS = YES; 378 | GCC_OPTIMIZATION_LEVEL = 0; 379 | GCC_PREPROCESSOR_DEFINITIONS = ( 380 | "DEBUG=1", 381 | "$(inherited)", 382 | ); 383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 385 | GCC_WARN_UNDECLARED_SELECTOR = YES; 386 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 387 | GCC_WARN_UNUSED_FUNCTION = YES; 388 | GCC_WARN_UNUSED_VARIABLE = YES; 389 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 390 | MTL_ENABLE_DEBUG_INFO = YES; 391 | ONLY_ACTIVE_ARCH = YES; 392 | SDKROOT = iphoneos; 393 | }; 394 | name = Debug; 395 | }; 396 | 4689A7C920EC081C00BC7C8A /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_SEARCH_USER_PATHS = NO; 400 | CLANG_ANALYZER_NONNULL = YES; 401 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 402 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 403 | CLANG_CXX_LIBRARY = "libc++"; 404 | CLANG_ENABLE_MODULES = YES; 405 | CLANG_ENABLE_OBJC_ARC = YES; 406 | CLANG_ENABLE_OBJC_WEAK = YES; 407 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 408 | CLANG_WARN_BOOL_CONVERSION = YES; 409 | CLANG_WARN_COMMA = YES; 410 | CLANG_WARN_CONSTANT_CONVERSION = YES; 411 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 414 | CLANG_WARN_EMPTY_BODY = YES; 415 | CLANG_WARN_ENUM_CONVERSION = YES; 416 | CLANG_WARN_INFINITE_RECURSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 420 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 421 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 422 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 423 | CLANG_WARN_STRICT_PROTOTYPES = YES; 424 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 425 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 426 | CLANG_WARN_UNREACHABLE_CODE = YES; 427 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 428 | CODE_SIGN_IDENTITY = "iPhone Developer"; 429 | COPY_PHASE_STRIP = NO; 430 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 431 | ENABLE_NS_ASSERTIONS = NO; 432 | ENABLE_STRICT_OBJC_MSGSEND = YES; 433 | GCC_C_LANGUAGE_STANDARD = gnu11; 434 | GCC_NO_COMMON_BLOCKS = YES; 435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 437 | GCC_WARN_UNDECLARED_SELECTOR = YES; 438 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 439 | GCC_WARN_UNUSED_FUNCTION = YES; 440 | GCC_WARN_UNUSED_VARIABLE = YES; 441 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 442 | MTL_ENABLE_DEBUG_INFO = NO; 443 | SDKROOT = iphoneos; 444 | VALIDATE_PRODUCT = YES; 445 | }; 446 | name = Release; 447 | }; 448 | 4689A7CB20EC081C00BC7C8A /* Debug */ = { 449 | isa = XCBuildConfiguration; 450 | buildSettings = { 451 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 452 | CODE_SIGN_STYLE = Automatic; 453 | DEVELOPMENT_TEAM = Y7546NLJW9; 454 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 455 | GCC_PREFIX_HEADER = ""; 456 | INFOPLIST_FILE = "$(SRCROOT)/DemoContainerView/Info.plist"; 457 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 458 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 459 | PRODUCT_BUNDLE_IDENTIFIER = mrusta.containerView; 460 | PRODUCT_NAME = "$(TARGET_NAME)"; 461 | TARGETED_DEVICE_FAMILY = "1,2"; 462 | }; 463 | name = Debug; 464 | }; 465 | 4689A7CC20EC081C00BC7C8A /* Release */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 469 | CODE_SIGN_STYLE = Automatic; 470 | DEVELOPMENT_TEAM = Y7546NLJW9; 471 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 472 | GCC_PREFIX_HEADER = ""; 473 | INFOPLIST_FILE = "$(SRCROOT)/DemoContainerView/Info.plist"; 474 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 475 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 476 | PRODUCT_BUNDLE_IDENTIFIER = mrusta.containerView; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | TARGETED_DEVICE_FAMILY = "1,2"; 479 | }; 480 | name = Release; 481 | }; 482 | /* End XCBuildConfiguration section */ 483 | 484 | /* Begin XCConfigurationList section */ 485 | 4689A7AF20EC081A00BC7C8A /* Build configuration list for PBXProject "DemoContainerView" */ = { 486 | isa = XCConfigurationList; 487 | buildConfigurations = ( 488 | 4689A7C820EC081C00BC7C8A /* Debug */, 489 | 4689A7C920EC081C00BC7C8A /* Release */, 490 | ); 491 | defaultConfigurationIsVisible = 0; 492 | defaultConfigurationName = Release; 493 | }; 494 | 4689A7CA20EC081C00BC7C8A /* Build configuration list for PBXNativeTarget "DemoContainerView" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | 4689A7CB20EC081C00BC7C8A /* Debug */, 498 | 4689A7CC20EC081C00BC7C8A /* Release */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | /* End XCConfigurationList section */ 504 | }; 505 | rootObject = 4689A7AC20EC081A00BC7C8A /* Project object */; 506 | } 507 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView.xcodeproj/project.xcworkspace/xcuserdata/mrusta.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView.xcodeproj/xcuserdata/rustam.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DemoContainerView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | containerView.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 03.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | 7 | @interface AppDelegate : UIResponder 8 | 9 | @property (strong, nonatomic) UIWindow *window; 10 | 11 | @end 12 | 13 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 03.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "AppDelegate.h" 6 | 7 | @interface AppDelegate () 8 | 9 | @end 10 | 11 | @implementation AppDelegate 12 | 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 15 | // Override point for customization after application launch. 16 | 17 | return YES; 18 | } 19 | 20 | 21 | - (void)applicationWillResignActive:(UIApplication *)application { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 24 | } 25 | 26 | 27 | - (void)applicationDidEnterBackground:(UIApplication *)application { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | 38 | - (void)applicationDidBecomeActive:(UIApplication *)application { 39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 40 | } 41 | 42 | 43 | - (void)applicationWillTerminate:(UIApplication *)application { 44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 45 | } 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_0@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_0.imageset/IMG_0@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_0.imageset/IMG_0@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_1@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_1.imageset/IMG_1@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_1.imageset/IMG_1@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_10@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_10.imageset/IMG_10@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_10.imageset/IMG_10@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_11@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_11.imageset/IMG_11@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_11.imageset/IMG_11@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_12@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_12.imageset/IMG_12@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_12.imageset/IMG_12@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_13@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_13.imageset/IMG_13@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_13.imageset/IMG_13@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_14@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_14.imageset/IMG_14@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_14.imageset/IMG_14@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_15@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_15.imageset/IMG_15@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_15.imageset/IMG_15@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_16.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_16@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_16.imageset/IMG_16@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_16.imageset/IMG_16@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_17.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_17@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_17.imageset/IMG_17@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_17.imageset/IMG_17@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_18.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_18@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_18.imageset/IMG_18@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_18.imageset/IMG_18@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_19.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_19@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_19.imageset/IMG_19@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_19.imageset/IMG_19@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_2@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_2.imageset/IMG_2@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_2.imageset/IMG_2@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_20.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_20@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_20.imageset/IMG_20@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_20.imageset/IMG_20@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_21.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_21@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_21.imageset/IMG_21@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_21.imageset/IMG_21@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_22.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_22@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_22.imageset/IMG_22@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_22.imageset/IMG_22@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_23.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_23@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_23.imageset/IMG_23@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_23.imageset/IMG_23@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_24.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_24@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_24.imageset/IMG_24@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_24.imageset/IMG_24@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_25.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_25@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_25.imageset/IMG_25@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_25.imageset/IMG_25@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_26.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_26@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_26.imageset/IMG_26@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_26.imageset/IMG_26@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_27.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_27@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_27.imageset/IMG_27@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_27.imageset/IMG_27@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_28.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_28@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_28.imageset/IMG_28@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_28.imageset/IMG_28@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_29.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_29@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_29.imageset/IMG_29@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_29.imageset/IMG_29@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_3@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_3.imageset/IMG_3@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_3.imageset/IMG_3@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_30.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_30@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_30.imageset/IMG_30@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_30.imageset/IMG_30@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_31.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_31@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_31.imageset/IMG_31@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_31.imageset/IMG_31@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_32.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_32@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_32.imageset/IMG_32@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_32.imageset/IMG_32@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_33.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_33.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_33.imageset/IMG_33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_33.imageset/IMG_33.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_34.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_34.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_34.imageset/IMG_34.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_34.imageset/IMG_34.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_35.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_35@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_35.imageset/IMG_35@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_35.imageset/IMG_35@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_36.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_36@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_36.imageset/IMG_36@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_36.imageset/IMG_36@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_37.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_37.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_37.imageset/IMG_37.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_37.imageset/IMG_37.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_38.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_38.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_38.imageset/IMG_38.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_38.imageset/IMG_38.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_39.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_39.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_39.imageset/IMG_39.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_39.imageset/IMG_39.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_4@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_4.imageset/IMG_4@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_4.imageset/IMG_4@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_40.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_40.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_40.imageset/IMG_40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_40.imageset/IMG_40.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_41.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_41@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_41.imageset/IMG_41@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_41.imageset/IMG_41@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_42.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_42@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_42.imageset/IMG_42@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_42.imageset/IMG_42@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_43.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_43.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_43.imageset/IMG_43.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_43.imageset/IMG_43.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_44.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_44@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_44.imageset/IMG_44@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_44.imageset/IMG_44@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_45.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_45@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_45.imageset/IMG_45@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_45.imageset/IMG_45@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_46.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_46@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_46.imageset/IMG_46@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_46.imageset/IMG_46@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_5@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_5.imageset/IMG_5@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_5.imageset/IMG_5@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_6@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_6.imageset/IMG_6@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_6.imageset/IMG_6@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_7@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_7.imageset/IMG_7@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_7.imageset/IMG_7@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_8@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_8.imageset/IMG_8@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_8.imageset/IMG_8@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "IMG_9@3x.jpg", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/IMG_9.imageset/IMG_9@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/IMG_9.imageset/IMG_9@3x.jpg -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/header_shadow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "header_shadow.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Assets.xcassets/header_shadow.imageset/header_shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Assets.xcassets/header_shadow.imageset/header_shadow.png -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoHeaderViews/DemoHeaderViews.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoHeaders.h 3 | // DemoContainerView 4 | // 5 | // Created by Rustam Motygullin on 17/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "ContainerTypes.h" 12 | 13 | @interface HeaderLabel : UIView 14 | @property (nonatomic, strong) UILabel *label; 15 | @property (nonatomic, strong) UIView *separatorLine; 16 | @property (nonatomic, strong) UIView *grip; 17 | @end 18 | 19 | 20 | @interface HeaderSearch : UIView 21 | @property (nonatomic, strong) UISearchBar *searchBar; 22 | @property (nonatomic, strong) UIView *separatorLine; 23 | @end 24 | 25 | 26 | @interface HeaderGrib : UIView 27 | @property (nonatomic, strong) UIView *separatorLine; 28 | @property (nonatomic, strong) UIImageView *separatorShadow; 29 | @property (nonatomic, strong) UIView *grip; 30 | @end 31 | 32 | 33 | @interface DemoHeaderViews : NSObject 34 | 35 | + (HeaderLabel *)createHeaderLabel; 36 | + (HeaderSearch *)createHeaderSearch; 37 | + (HeaderGrib *)createHeaderGrip; 38 | 39 | + (void)changeColorsHeaderView:(UIView *)headerView forStyle:(ContainerStyle)style; 40 | 41 | @end 42 | 43 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoHeaderViews/DemoHeaderViews.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoHeaders.m 3 | // DemoContainerView 4 | // 5 | // Created by Rustam Motygullin on 17/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import "DemoHeaderViews.h" 10 | #import "ContainerDefines.h" 11 | 12 | @implementation HeaderLabel 13 | @end 14 | 15 | @implementation HeaderSearch 16 | @end 17 | 18 | @implementation HeaderGrib 19 | @end 20 | 21 | 22 | @implementation DemoHeaderViews 23 | 24 | 25 | + (void)changeColorsHeaderView:(UIView *)headerView forStyle:(ContainerStyle)style { 26 | 27 | if(!headerView) return; 28 | 29 | CGFloat alpha = 0.5; 30 | UIColor *separatorColor = GRAYLEVEL(180); 31 | UIColor *graberColor = [separatorColor copy]; 32 | if((style == ContainerStyleDark) || 33 | (style == ContainerStyleDefault)) { 34 | if (style == ContainerStyleDark) alpha = 0.2; 35 | else if (style == ContainerStyleDefault) alpha = 1.0; 36 | separatorColor = GRAYLEVEL(222); 37 | graberColor = RGB(235, 239, 245); 38 | } 39 | 40 | if ([headerView isKindOfClass:[HeaderLabel class]]) { 41 | HeaderLabel *headerLabel = (HeaderLabel *)headerView; 42 | headerLabel.label.textColor = (style == ContainerStyleDark) ? WHITE_COLOR : BLACK_COLOR; 43 | headerLabel.separatorLine.backgroundColor = separatorColor; 44 | headerLabel.separatorLine.alpha = alpha; 45 | headerLabel.grip.backgroundColor = graberColor; 46 | headerLabel.grip.alpha = alpha; 47 | } 48 | else if([headerView isKindOfClass:[HeaderSearch class]]) { 49 | HeaderSearch *headerSearch = (HeaderSearch *)headerView; 50 | headerSearch.searchBar.keyboardAppearance = (style == ContainerStyleDark) ? UIKeyboardAppearanceDark : UIKeyboardAppearanceDefault; 51 | headerSearch.separatorLine.backgroundColor = separatorColor; 52 | headerSearch.separatorLine.alpha = alpha; 53 | } 54 | else if([headerView isKindOfClass:[HeaderGrib class]]) { 55 | HeaderGrib *headerGrip = (HeaderGrib *)headerView; 56 | headerGrip.separatorLine.backgroundColor = separatorColor; 57 | headerGrip.separatorLine.alpha = alpha; 58 | headerGrip.grip.backgroundColor = graberColor; 59 | headerGrip.grip.alpha = alpha; 60 | } 61 | 62 | } 63 | 64 | + (CGFloat)headerSize { 65 | CGFloat paddingWidht = SCREEN_PORTRAIT ?0. :20.; 66 | CGFloat widht = (SCREEN_PORTRAIT ?SCREEN_WIDTH :SCREEN_HEIGHT - paddingWidht); 67 | return widht; 68 | } 69 | 70 | + (HeaderLabel *)createHeaderLabel { 71 | 72 | HeaderLabel *view = [[HeaderLabel alloc] initWithFrame:CGRectMake(0, 0, [self headerSize], CUSTOM_HEADER_HEIGHT)]; 73 | view.clipsToBounds = YES; 74 | 75 | UILabel * 76 | label = [[UILabel alloc]initWithFrame:CGRectMake( 18, 16, 161, 30)]; 77 | label.font = [UIFont fontWithName:@"ProximaNova-Extrabld" size:24]; 78 | 79 | label.text = @"Heading"; 80 | view.label = label; 81 | [view addSubview:label]; 82 | 83 | view.grip = [self createGrip]; 84 | [view addSubview:view.grip]; 85 | 86 | view.separatorLine = [self createSeparatorLine]; 87 | [view addSubview:view.separatorLine]; 88 | 89 | 90 | return view; 91 | } 92 | 93 | + (HeaderSearch *)createHeaderSearch { 94 | 95 | HeaderSearch *view = [[HeaderSearch alloc] initWithFrame:CGRectMake(0, 0, [self headerSize], CUSTOM_HEADER_HEIGHT)]; 96 | view.clipsToBounds = YES; 97 | 98 | UISearchBar * 99 | searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 4, [self headerSize], CUSTOM_HEADER_HEIGHT -4)]; 100 | searchBar.barStyle = UIBarStyleDefault; 101 | searchBar.searchBarStyle = UISearchBarStyleMinimal; 102 | searchBar.placeholder = @"Search"; 103 | searchBar.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth ); 104 | view.searchBar = searchBar; 105 | [view addSubview:searchBar]; 106 | 107 | view.separatorLine = [self createSeparatorLine]; 108 | [view addSubview:view.separatorLine]; 109 | return view; 110 | } 111 | 112 | + (HeaderGrib *)createHeaderGrip { 113 | HeaderGrib *view = [[HeaderGrib alloc] initWithFrame:CGRectMake(0, 0, [self headerSize], 20)]; 114 | 115 | view.grip = [self createGrip]; 116 | [view addSubview:view.grip]; 117 | 118 | view.separatorLine = [self createSeparatorLine]; 119 | view.separatorLine.frame = CGRectMake( 120 | view.separatorLine.frame.origin.x, 19.5 , 121 | view.separatorLine.frame.size.width, view.separatorLine.frame.size.height 122 | ); 123 | 124 | view.separatorShadow = [[UIImageView alloc]initWithFrame:CGRectMake(0, 19.5, [self headerSize], 20)]; 125 | view.separatorShadow.image = IMG(@"header_shadow.png"); 126 | view.separatorShadow.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth); 127 | // view.separatorShadow.alpha = 0.4; 128 | [view addSubview:view.separatorShadow]; 129 | 130 | [view addSubview:view.separatorLine]; 131 | return view; 132 | } 133 | 134 | + (UIView *)createSeparatorLine { 135 | CGFloat height = 0.5; 136 | UIView * 137 | line = [[UIView alloc]initWithFrame: CGRectMake( 0, CUSTOM_HEADER_HEIGHT -height, [self headerSize], height )]; 138 | line.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth ); 139 | return line; 140 | } 141 | 142 | + (UIView *)createGrip { 143 | UIView * 144 | grip = [[UIView alloc] initWithFrame: CGRectMake( (([self headerSize] / 2) -18) , 8 , 36, 4 )]; 145 | grip.autoresizingMask = (UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin ); 146 | grip.layer.cornerRadius = grip.frame.size.height / 2; 147 | return grip; 148 | } 149 | 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoModalViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoModalViewController.h 3 | // DemoContainerView 4 | // 5 | // Created by Rustam Motygullin on 26/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ContainerViewController.h" 11 | 12 | @interface DemoModalViewController : ContainerViewController 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoModalViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoModalViewController.m 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 26/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import "DemoModalViewController.h" 10 | #import "DemoScrollViews.h" 11 | 12 | @interface DemoModalViewController () 13 | 14 | @end 15 | 16 | @implementation DemoModalViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | UITextView *textView = [DemoScrollViews createTextViewWithProtocols:self]; 22 | [self.containerView addSubview:textView]; 23 | 24 | } 25 | - (IBAction)closeController:(UIButton *)sender { 26 | [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoCells/DemoCollectionCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCollectionCell.h 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 21/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoCollectionCell : UICollectionViewCell 12 | 13 | @property (strong, nonatomic) UIImageView *imageView; 14 | @property (strong, nonatomic) UIView *view; 15 | @property (strong, nonatomic) UILabel *label; 16 | 17 | @property (strong, nonatomic) UITapGestureRecognizer *tapGesture; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoCells/DemoCollectionCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCollectionCell.m 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 21/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import "DemoCollectionCell.h" 10 | 11 | @implementation DemoCollectionCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoCells/DemoTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoTableCell.h 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 21/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoTableCell : UITableViewCell 12 | 13 | @property (strong, nonatomic) UILabel *labelTitle; 14 | @property (strong, nonatomic) UILabel *labelSubTitle; 15 | @property (strong, nonatomic) UIView *separatorLine; 16 | @property (strong, nonatomic) UIImageView *imageAvatar; 17 | 18 | @property (strong, nonatomic) UITapGestureRecognizer *tapGesture; 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoCells/DemoTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoTableCell.m 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 21/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import "DemoTableCell.h" 10 | 11 | @implementation DemoTableCell 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsCollectionView/DemoCollectionDataSource.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | #import "ContainerTypes.h" 7 | 8 | 9 | 10 | @interface DemoCollectionDataSource : NSObject 11 | 12 | @property (strong, nonatomic) NSMutableArray *photos; 13 | @property ContainerStyle containerStyle; 14 | 15 | @end 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsCollectionView/DemoCollectionDataSource.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "DemoCollectionDataSource.h" 6 | #import "DemoCollectionCell.h" 7 | 8 | #import "ContainerDefines.h" 9 | 10 | @implementation DemoCollectionDataSource 11 | 12 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 13 | return self.photos.count ; 14 | } 15 | 16 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 17 | 18 | DemoCollectionCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier: @"collectionCell" forIndexPath: indexPath]; 19 | cell.backgroundColor = CLR_COLOR; 20 | cell.clipsToBounds = YES; 21 | 22 | CGFloat indent = (((SCREEN_WIDTH - ((SCREEN_WIDTH * .437333) * 2)) / 3) / 2); 23 | CGFloat imageSize = (SCREEN_WIDTH * .437333); 24 | 25 | CGSize cellSize = (CGSize) 26 | { 27 | ((imageSize + (indent * 2)) -1) , 28 | (imageSize + indent + 36) 29 | }; 30 | 31 | if(!cell.imageView ) 32 | { 33 | cell.imageView = [UIImageView new]; 34 | cell.imageView.clipsToBounds = 1; 35 | cell.imageView.backgroundColor = CLR_COLOR; 36 | cell.imageView.contentMode = UIViewContentModeScaleAspectFill; 37 | cell.imageView.layer.cornerRadius = 6; 38 | [cell addSubview: cell.imageView]; 39 | } 40 | 41 | if(!cell.label) 42 | { 43 | cell.label = [[UILabel alloc]initWithFrame:CGRectMake(8, cellSize.height -26, cellSize.width -16, 18)]; 44 | cell.label.font = [UIFont fontWithName:@"ProximaNova-Extrabld" size:14]; 45 | cell.label.textColor = BLACK_COLOR; 46 | [cell addSubview:cell.label]; 47 | } 48 | 49 | cell.imageView.frame = CGRectMake( indent, indent, imageSize, imageSize); 50 | cell.imageView.image = self.photos[indexPath.row][@"small"]; 51 | 52 | cell.label.text = (indexPath.row) ? (indexPath.row == 1) ? @"mapView" : SFMT(@"photo %d",(int)indexPath.row) : @"settings" ; 53 | cell.label.textColor = (self.containerStyle == ContainerStyleDark) ? WHITE_COLOR : BLACK_COLOR; 54 | 55 | return cell; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsCollectionView/DemoCollectionDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 29.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "ContainerScrollDelegate.h" 6 | 7 | @interface DemoCollectionDelegate : ContainerScrollDelegate 8 | @property (strong, nonatomic) void(^blockSelectIndex)(NSInteger); 9 | @end 10 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsCollectionView/DemoCollectionDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 29.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "DemoCollectionDelegate.h" 6 | 7 | #import "ContainerDefines.h" 8 | 9 | @implementation DemoCollectionDelegate 10 | 11 | #pragma mark - CollectionView Delegate 12 | 13 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 14 | if(self.blockSelectIndex) self.blockSelectIndex(indexPath.row); 15 | } 16 | 17 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 18 | 19 | CGFloat indent = (((SCREEN_WIDTH - ((SCREEN_WIDTH * .437333) * 2)) / 3) / 2); 20 | CGFloat imageSize = (SCREEN_WIDTH * .437333); 21 | 22 | CGSize size = (CGSize) { 23 | ((imageSize + (indent * 2)) -1), 24 | (imageSize + indent + 36) 25 | }; 26 | 27 | return size; 28 | } 29 | 30 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{ 31 | 32 | CGFloat indent = (((SCREEN_WIDTH - ((SCREEN_WIDTH * .437333) * 2)) / 3) / 2); 33 | return UIEdgeInsetsMake(indent,indent,0,indent); 34 | } 35 | 36 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { 37 | return .0; 38 | } 39 | 40 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { 41 | return .0; 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsTableView/DemoTableDataSource.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | #import "ContainerTypes.h" 7 | 8 | @interface DemoTableDataSource : NSObject 9 | 10 | @property (strong, nonatomic) NSMutableArray *photos; 11 | @property ContainerStyle containerStyle; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsTableView/DemoTableDataSource.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 11.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "DemoTableDataSource.h" 6 | #import "DemoTableCell.h" 7 | 8 | #import "ContainerDefines.h" 9 | 10 | @implementation DemoTableDataSource 11 | 12 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex { 13 | return self.photos.count ; 14 | } 15 | 16 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 17 | 18 | DemoTableCell * cell = [tableView dequeueReusableCellWithIdentifier:@"TableCell"]; 19 | if(!cell) { 20 | cell = [[DemoTableCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: @"TableCell" ]; 21 | cell.backgroundColor = CLR_COLOR; 22 | } 23 | 24 | if(!cell.separatorLine) { 25 | cell.separatorLine = [[UIView alloc]initWithFrame:CGRectMake( 16 , 87.5, SCREEN_WIDTH -32 , 0.5)]; 26 | cell.separatorLine.backgroundColor = RGB(222, 222, 222); 27 | [cell addSubview: cell.separatorLine]; 28 | } 29 | 30 | if(!cell.labelTitle) { 31 | cell.labelTitle = [[UILabel alloc]initWithFrame:CGRectMake( 18 , 20, SCREEN_WIDTH -67 , 30)]; 32 | cell.labelTitle.font = [UIFont fontWithName:@"ProximaNova-Extrabld" size:22]; 33 | cell.labelTitle.textColor = BLACK_COLOR; 34 | [cell addSubview:cell.labelTitle]; 35 | } 36 | 37 | if(!cell.labelSubTitle) { 38 | cell.labelSubTitle = [[UILabel alloc]initWithFrame:CGRectMake( 18 , 50, SCREEN_WIDTH -67, 16)]; 39 | cell.labelSubTitle.font = [UIFont fontWithName:@"ProximaNova-Regular" size:15]; 40 | cell.labelSubTitle.textColor = RGB(124,132,148); 41 | [cell addSubview:cell.labelSubTitle]; 42 | } 43 | 44 | cell.labelTitle .text = (indexPath.row) ? (indexPath.row == 1) ? @"mapView" : SFMT(@"photo %d", (int)indexPath.row) : @"settings" ; 45 | cell.labelSubTitle.text = @"Subtitle"; 46 | cell.labelTitle.textColor = (self.containerStyle == ContainerStyleDark) ? WHITE_COLOR : BLACK_COLOR; 47 | 48 | switch (self.containerStyle) { 49 | case ContainerStyleDefault: { 50 | cell.separatorLine.backgroundColor = GRAYLEVEL(222); 51 | cell.separatorLine.alpha = 1; 52 | } break; 53 | case ContainerStyleLight:{ 54 | cell.separatorLine.backgroundColor = GRAYLEVEL(180); 55 | cell.separatorLine.alpha = 0.5; 56 | } break; 57 | case ContainerStyleDark:{ 58 | cell.separatorLine.backgroundColor = GRAYLEVEL(222); 59 | cell.separatorLine.alpha = 0.2; 60 | } break; 61 | case ContainerStyleExtraLight:{ 62 | cell.separatorLine.backgroundColor = GRAYLEVEL(180); 63 | cell.separatorLine.alpha = 0.5; 64 | } break; 65 | default: 66 | break; 67 | } 68 | 69 | return cell; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsTableView/DemoTableDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 29.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "ContainerScrollDelegate.h" 6 | 7 | @interface DemoTableDelegate : ContainerScrollDelegate 8 | @property (strong, nonatomic) void(^blockSelectIndex)(NSInteger); 9 | @end 10 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoProtocolsTableView/DemoTableDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 29.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import "DemoTableDelegate.h" 6 | 7 | @implementation DemoTableDelegate 8 | 9 | #pragma mark - TableView Delegate 10 | 11 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 12 | { 13 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 14 | if(self.blockSelectIndex) self.blockSelectIndex(indexPath.row); 15 | } 16 | 17 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 18 | { 19 | return 88; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoScrollViews.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoScrollViews.h 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 26/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "ContainerTypes.h" 12 | 13 | @interface DemoScrollViews : NSObject 14 | 15 | + (UITableView *)createTableViewWithProtocols:(id)protocols; 16 | + (UICollectionView *)createCollectionViewWithProtocols:(id)protocols; 17 | + (UITextView *)createTextViewWithProtocols:(id)protocols; 18 | 19 | @end 20 | 21 | 22 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoScrollViews/DemoScrollViews.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoScrollViews.m 3 | // DemoContainerView 4 | // 5 | // Created by Рустам Мотыгуллин on 26/11/2018. 6 | // Copyright © 2018 mrusta. All rights reserved. 7 | // 8 | 9 | #import "DemoScrollViews.h" 10 | #import "ContainerDefines.h" 11 | #import "DemoCollectionCell.h" 12 | 13 | @implementation DemoScrollViews 14 | 15 | + (UITableView *)createTableViewWithProtocols:(id)protocols { 16 | UITableView * 17 | table = [[UITableView alloc] initWithFrame:FRAME_SCROLLVIEW style:UITableViewStylePlain]; 18 | table.separatorStyle = UITableViewCellSeparatorStyleSingleLine; 19 | table.showsVerticalScrollIndicator = NO; 20 | table.backgroundColor = CLR_COLOR; 21 | table.delegate = protocols; 22 | table.dataSource = protocols; 23 | return table; 24 | } 25 | 26 | 27 | + (UICollectionView *)createCollectionViewWithProtocols:(id)protocols { 28 | UICollectionView * 29 | collection = [[UICollectionView alloc]initWithFrame:FRAME_SCROLLVIEW collectionViewLayout:[[UICollectionViewFlowLayout alloc]init]]; 30 | [collection registerClass:[DemoCollectionCell class] forCellWithReuseIdentifier:@"collectionCell"]; 31 | collection.backgroundColor = CLR_COLOR; 32 | collection.delegate = protocols; 33 | collection.dataSource = protocols; 34 | return collection; 35 | } 36 | 37 | + (UITextView *)createTextViewWithProtocols:(id)protocols { 38 | 39 | UITextView * textView = [[UITextView alloc]initWithFrame:FRAME_SCROLLVIEW]; 40 | textView.delegate = protocols; 41 | textView.returnKeyType = UIReturnKeyDone; 42 | textView.backgroundColor = CLR_COLOR; 43 | //textView.textColor = (self.containerStyle == ContainerStyleDark) ?WHITE_COLOR :BLACK_COLOR; 44 | textView.font = FONT_S(15); 45 | textView.text = @"This example demonstrates a block quote. Because some introductory phrases will lead\ 46 | naturally into the block quote,\ 47 | you might choose to begin the block quote with a lowercase letter. In this and the later\ 48 | examples we use “Lorem ipsum” text to ensure that each block quotation contains 40 words or\ 49 | more. Lorem ipsum dolor sit amet, consectetur adipiscing elit. (Organa, 2013, p. 234)\ 50 | Example 2\ 51 | This example also demonstrates a block quote. Some introductory sentences end abruptly in a\ 52 | colon or a period:\ 53 | In those cases, you are more likely to capitalize the beginning word of the block quotation.\ 54 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nisi mi, pharetra sit amet mi vitae,\ 55 | commodo accumsan dui. Donec non scelerisque quam. Pellentesque ut est sed neque.\ 56 | (Calrissian, 2013, para. 3)\ 57 | Example 3\ 58 | This is another example of a block quotation. Sometimes, the author(s) being cited will be\ 59 | included in the introduction. In that case, according to Skywalker and Solo,\ 60 | because the author names are in the introduction of this quote, the parentheses that follow it\ 61 | will include only the year and the page number. Lorem ipsum dolor sit amet, consectetur\ 62 | adipiscing elit. Sed nisi mi, pharetra sit amet mi vitae, commodo accumsan dui. Donec non\ 63 | scelerisque quam. Pellentesque ut est sed neque. (2013, p. 103)\ 64 | Copyright © 2013 by the American Psychological Association. This content may be reproduced for classroom or teaching purposes\ 65 | provided that credit is given to the American Psychological Association. For any other use, please contact the APA Permissions Office.\ 66 | Example 4\ 67 | In this example, we have added our own emphasis. This needs to be indicated parenthetically,\ 68 | so the reader knows that the italics were not in the original text. Amidala (2009) dabbled in hyperbole,\ 69 | saying,\ 70 | Random Explosions 2: Revenge of the Dialogue is the worst movie in the history of time\ 71 | [emphasis added]. . . . it’s [sic] promise of dialogue is a misnomer of explosive proportions. Lorem ipsum\ 72 | dolor sit amet, consectetur adipiscing elit. Sed nisi mi, pharetra sit amet mi vitae. (p. 13)\ 73 | This paragraph appears flush left because it is a continuation of the paragraph we began above the block\ 74 | quote. Note that we also added “[sic]” within the block quotation to indicate that a misspelling was in\ 75 | the original text, and we’ve included ellipses (with four periods) because we have omitted a sentence\ 76 | from the quotation (see pp. 172–173 of the Publication Manual of the American Psychological\ 77 | Association).\ 78 | Example 5\ 79 | This example is similar to the previous one, except that we have continued the quotation to\ 80 | include text from a second paragraph. Amidala (2009) dabbled in hyperbole, saying,\ 81 | Random Explosions 2: Revenge of the Dialogue is the worst movie in the history of time\ 82 | [emphasis added]. . . . it’s [sic] promise of dialogue is a misnomer of explosive proportions.\ 83 | On the other hand, Delightful Banter on Windswept Mountainside is a film to be\ 84 | cherished for all time. Filmmakers hoping to top this film should abandon hope. (p. 13)\ 85 | This paragraph begins with an indent because we do not intend it to continue the paragraph\ 86 | that we started above the block quote. Note that we also added “[sic]” within the block quotation to\ 87 | indicate that a misspelling was in the original text, and we’ve included ellipses (with four periods)\ 88 | because we have omitted a sentence from this quotation (see pp. 172–173 of the Manual)."; 89 | 90 | return textView; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoViewController.h: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 03.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | 7 | #import 8 | #import "ContainerViewController.h" 9 | 10 | @interface DemoViewController : ContainerViewController 11 | 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Demo/DemoViewController.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 03.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | 6 | #import "DemoViewController.h" 7 | #import "ContainerDefines.h" 8 | 9 | #import "DemoHeaderViews.h" 10 | 11 | #import "DemoScrollViews.h" 12 | #import "DemoTableCell.h" 13 | #import "DemoCollectionCell.h" 14 | 15 | 16 | 17 | 18 | @interface DemoViewController () 19 | 20 | 21 | @property (strong, nonatomic) NSMutableArray *photoItems; 22 | 23 | @property (strong, nonatomic) UITableView *tableView; 24 | @property (strong, nonatomic) UICollectionView *collectionView; 25 | @property (strong, nonatomic) UITextView *textView; 26 | 27 | 28 | @property (strong, nonatomic) UIImageView *imageView; 29 | @property (strong, nonatomic) IBOutlet UIView *settingsView; 30 | @property (strong, nonatomic) IBOutlet MKMapView *mapView; 31 | @property (strong, nonatomic) IBOutlet UIVisualEffectView *mapViewStatusBarBlur; 32 | 33 | @property (strong, nonatomic) IBOutlet UISegmentedControl *segmentedContainerMove; 34 | @property (strong, nonatomic) IBOutlet UISwitch *switchEnableMiddle; 35 | 36 | @property (strong, nonatomic) IBOutlet UILabel *containerLabelValueTop; 37 | @property (strong, nonatomic) IBOutlet UILabel *containerLabelValueBottom; 38 | @property (strong, nonatomic) IBOutlet UILabel *containerLabelValueCornerRadius; 39 | 40 | @end 41 | 42 | 43 | 44 | 45 | @implementation DemoViewController 46 | 47 | 48 | #pragma mark - Life Cycle 49 | 50 | - (void)viewDidLoad { 51 | [super viewDidLoad]; 52 | 53 | 54 | if(!_imageView) { 55 | _imageView = [[UIImageView alloc]initWithFrame:FRAME]; 56 | _imageView.contentMode = SCREEN_PORTRAIT ?UIViewContentModeScaleAspectFill :UIViewContentModeScaleAspectFit; 57 | _imageView.clipsToBounds = YES; 58 | _imageView.backgroundColor = GRAYLEVEL(210); 59 | _imageView.autoresizingMask = 60 | (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | 61 | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin); 62 | _imageView.alpha = 0; 63 | } 64 | [self.bottomView addSubview:_imageView]; 65 | 66 | 67 | [self.mapView setRegion:[self.mapView regionThatFits:COORDINATE_SAN_FRANCISCO]]; 68 | self.mapView.alpha = 0; 69 | 70 | self.mapViewStatusBarBlur.alpha = 1; 71 | 72 | self.mapViewStatusBarBlur.frame = CGRectMake( 73 | self.mapViewStatusBarBlur.frame.origin.x, self.mapViewStatusBarBlur.frame.origin.y , 74 | self.mapViewStatusBarBlur.frame.size.width, SCREEN_STATUS_HEIGHT 75 | ); 76 | 77 | _tableView = [DemoScrollViews createTableViewWithProtocols:self]; 78 | [self changeTableViewSeparatorStyle]; 79 | [self.containerView addSubview:_tableView]; 80 | 81 | self.containerCornerRadius = 15; 82 | self.containerBottomButtonToMoveTop = YES; 83 | // [self containerMove:ContainerMoveTypeTop animated:NO]; 84 | 85 | self.delegate = self; 86 | 87 | 88 | 89 | [self initScrollViewsPhotoItems]; 90 | 91 | } 92 | 93 | #pragma mark - Init Photos Items For TableView & CollecionView 94 | 95 | - (void)initScrollViewsPhotoItems { 96 | 97 | for (int count =0; count < 46; count++) { 98 | UIImage *img = IMG( SFMT(@"IMG_%d",count) ); 99 | UIImage *imgSmall = [self imageWithImage:img size:200]; 100 | 101 | [self.photoItems addObject:@{ @"big" : img, 102 | @"small" : imgSmall }]; 103 | } 104 | if(self.tableView) [self.tableView reloadData]; 105 | if(self.collectionView) [self.collectionView reloadData]; 106 | } 107 | 108 | 109 | - (NSMutableArray *)photoItems { 110 | if(!_photoItems) _photoItems = [NSMutableArray new]; 111 | return _photoItems; 112 | } 113 | 114 | 115 | - (UIImage *)imageWithImage:(UIImage *)image size:(NSInteger)size { 116 | 117 | CGSize cgSize = CGSizeMake( size, (image.size.height / (image.size.width / size) )); 118 | CGRect cgRect = CGRectMake( 0, 0, size, (image.size.height / (image.size.width / size) )); 119 | UIGraphicsBeginImageContextWithOptions( cgSize, NO, 0.0); 120 | [image drawInRect: cgRect ]; 121 | UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext(); 122 | UIGraphicsEndImageContext(); 123 | return newImage; 124 | } 125 | 126 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 127 | [self.view endEditing:YES]; 128 | } 129 | 130 | 131 | #pragma mark - UIContentContainer Protocol 132 | 133 | - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { 134 | [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 135 | 136 | if(_imageView) { 137 | _imageView.contentMode = (size.width < size.height) ?UIViewContentModeScaleAspectFill :UIViewContentModeScaleAspectFit; 138 | } 139 | if(_tableView) { 140 | [_tableView reloadData]; 141 | } 142 | if(_collectionView) { 143 | [_collectionView reloadData]; 144 | } 145 | } 146 | 147 | #pragma mark - SearchBar Delegate 148 | 149 | - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { 150 | if(self.containerPosition != ContainerMoveTypeTop) [self containerMove:ContainerMoveTypeTop]; 151 | GCD_ASYNC_GLOBAL_BEGIN(0) { 152 | GCD_ASYNC_MAIN_BEGIN { 153 | [searchBar becomeFirstResponder]; 154 | }); 155 | }); 156 | } 157 | 158 | #pragma mark - TableView Delegate 159 | 160 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 161 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 162 | [self selectCellIndex:(SelectType)indexPath.row animated:YES]; 163 | } 164 | 165 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 166 | return 88; 167 | } 168 | 169 | #pragma mark - TableView DataSource 170 | 171 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex { 172 | return self.photoItems.count; 173 | } 174 | 175 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 176 | 177 | DemoTableCell * cell = [tableView dequeueReusableCellWithIdentifier:@"TableCell"]; 178 | if(!cell) { 179 | cell = [[DemoTableCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: @"TableCell" ]; 180 | cell.backgroundColor = CLR_COLOR; 181 | } 182 | 183 | cell.separatorInset = UIEdgeInsetsMake(0, 16, 0, 16); 184 | 185 | if(!cell.labelTitle) { 186 | cell.labelTitle = [[UILabel alloc]initWithFrame:CGRectMake( 18 , 20, SCREEN_WIDTH -67 , 30 )]; 187 | cell.labelTitle.font = [UIFont fontWithName:@"ProximaNova-Extrabld" size:22]; 188 | cell.labelTitle.textColor = BLACK_COLOR; 189 | [cell addSubview:cell.labelTitle]; 190 | } 191 | 192 | if(!cell.labelSubTitle) { 193 | cell.labelSubTitle = [[UILabel alloc]initWithFrame:CGRectMake( 18 , 50, SCREEN_WIDTH -67, 16 )]; 194 | cell.labelSubTitle.font = [UIFont fontWithName:@"ProximaNova-Regular" size:15]; 195 | cell.labelSubTitle.textColor = RGB(124,132,148); 196 | [cell addSubview:cell.labelSubTitle]; 197 | } 198 | 199 | cell.labelTitle .text = (indexPath.row) ? (indexPath.row == 1) ? @"mapView" : SFMT(@"photo %d", (int)indexPath.row) : @"settings" ; 200 | cell.labelSubTitle.text = @"Subtitle"; 201 | cell.labelTitle.textColor = (self.containerStyle == ContainerStyleDark) ? WHITE_COLOR : BLACK_COLOR; 202 | 203 | cell.tag = indexPath.row; 204 | cell.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTableCellTap:)]; 205 | [cell addGestureRecognizer:cell.tapGesture]; 206 | 207 | return cell; 208 | } 209 | 210 | - (void)handleTableCellTap:(UIGestureRecognizer *)gestureRecognizer { 211 | NSInteger i = gestureRecognizer.view.tag; 212 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0]; 213 | 214 | [_tableView selectRowAtIndexPath:indexPath 215 | animated:YES 216 | scrollPosition:UITableViewScrollPositionNone]; 217 | [self tableView:_tableView didSelectRowAtIndexPath:indexPath]; 218 | } 219 | 220 | 221 | 222 | #pragma mark - CollectionView Delegate 223 | 224 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 225 | [self selectCellIndex:(SelectType)indexPath.row animated:YES]; 226 | } 227 | 228 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 229 | 230 | CGFloat widht = SCREEN_PORTRAIT ?SCREEN_WIDTH :(SCREEN_HEIGHT - 20); 231 | 232 | CGFloat indent = (((widht - ((widht * .437333) * 2)) / 3) / 2); 233 | CGFloat imageSize = (widht * .437333); 234 | 235 | CGSize size = (CGSize) { 236 | ((imageSize + (indent * 2)) -1), 237 | (imageSize + indent + 36) 238 | }; 239 | 240 | return size; 241 | } 242 | 243 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{ 244 | 245 | CGFloat widht = SCREEN_PORTRAIT ?SCREEN_WIDTH :(SCREEN_HEIGHT - 20); 246 | 247 | CGFloat indent = (((widht - ((widht * .437333) * 2)) / 3) / 2); 248 | return UIEdgeInsetsMake(indent,indent,0,indent); 249 | } 250 | 251 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { 252 | return .0; 253 | } 254 | 255 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { 256 | return .0; 257 | } 258 | 259 | 260 | #pragma mark - CollectionView DataSource 261 | 262 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 263 | return self.photoItems.count; 264 | } 265 | 266 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 267 | 268 | DemoCollectionCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier: @"collectionCell" forIndexPath: indexPath]; 269 | cell.backgroundColor = CLR_COLOR; 270 | cell.clipsToBounds = YES; 271 | 272 | CGFloat widht = SCREEN_PORTRAIT ?SCREEN_WIDTH :(SCREEN_HEIGHT - 20); 273 | 274 | CGFloat indent = (((widht - ((widht * .437333) * 2)) / 3) / 2); 275 | CGFloat imageSize = (widht * .437333); 276 | 277 | CGSize cellSize = (CGSize) 278 | { 279 | ((imageSize + (indent * 2)) -1) , 280 | (imageSize + indent + 36) 281 | }; 282 | 283 | if(!cell.imageView ) { 284 | cell.imageView = [UIImageView new]; 285 | cell.imageView.clipsToBounds = 1; 286 | cell.imageView.backgroundColor = CLR_COLOR; 287 | cell.imageView.contentMode = UIViewContentModeScaleAspectFill; 288 | cell.imageView.layer.cornerRadius = 6; 289 | [cell addSubview: cell.imageView]; 290 | } 291 | 292 | if(!cell.label) { 293 | cell.label = [[UILabel alloc]initWithFrame:CGRectMake( 8, cellSize.height -26, cellSize.width -16, 18)]; 294 | cell.label.font = [UIFont fontWithName:@"ProximaNova-Extrabld" size:14]; 295 | cell.label.textColor = BLACK_COLOR; 296 | [cell addSubview:cell.label]; 297 | } 298 | 299 | cell.imageView.frame = CGRectMake( indent, indent, imageSize, imageSize); 300 | cell.imageView.image = self.photoItems[indexPath.row][@"small"]; 301 | 302 | cell.label.frame = CGRectMake( 8, cellSize.height -26, cellSize.width -16, 18); 303 | cell.label.text = (indexPath.row) ? (indexPath.row == 1) ? @"mapView" : SFMT(@"photo %d",(int)indexPath.row) : @"settings" ; 304 | cell.label.textColor = (self.containerStyle == ContainerStyleDark) ? WHITE_COLOR : BLACK_COLOR; 305 | 306 | cell.tag = indexPath.row; 307 | cell.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleColletionCellTap:)]; 308 | [cell addGestureRecognizer:cell.tapGesture]; 309 | 310 | return cell; 311 | } 312 | 313 | - (void)handleColletionCellTap:(UIGestureRecognizer *)gestureRecognizer { 314 | NSInteger i = gestureRecognizer.view.tag; 315 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0]; 316 | 317 | [_collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone]; 318 | [self collectionView:_collectionView didSelectItemAtIndexPath:indexPath]; 319 | } 320 | 321 | #pragma mark - TableView & Collection Select Cell 322 | 323 | - (void)selectCellIndex:(SelectType)index animated:(BOOL)animated { 324 | 325 | __weak typeof(self) weakSelf = self; 326 | ANIMATIONCOMP( (animated) ? 0.25 : 0. , ^(void) { 327 | 328 | weakSelf.imageView.alpha = 0; 329 | 330 | }, ^(BOOL fin) { 331 | 332 | if((index != SelectTypeSettings) && 333 | (index != SelectTypeMap)) { 334 | weakSelf.imageView.image = self.photoItems[index][@"big"]; 335 | } 336 | 337 | ANIMATION( (animated) ? 0.25 : 0. , ^(void){ 338 | 339 | weakSelf.mapViewStatusBarBlur.hidden = YES; 340 | weakSelf.mapView.alpha = 0; 341 | weakSelf.settingsView.alpha = 0; 342 | 343 | switch (index) { 344 | case SelectTypeSettings: 345 | weakSelf.settingsView.alpha = 1; 346 | break; 347 | case SelectTypeMap: 348 | weakSelf.mapView.alpha = 1; 349 | weakSelf.mapViewStatusBarBlur.hidden = APP.statusBarHidden; 350 | break; 351 | default: 352 | weakSelf.imageView.alpha = 1; 353 | break; 354 | } 355 | }); 356 | }); 357 | } 358 | 359 | #pragma mark - ContainerView Delegate 360 | 361 | - (void)changeContainerMove:(ContainerMoveType)containerMove containerY:(CGFloat)containerY animated:(BOOL)animated { 362 | [super changeContainerMove:containerMove containerY:containerY animated:animated]; 363 | if(animated) { 364 | self.segmentedContainerMove.selectedSegmentIndex = containerMove; 365 | } 366 | } 367 | 368 | #pragma mark - ContainerView Changes Parameters 369 | 370 | - (IBAction)changeStatusbar:(UISwitch *)sender { 371 | BOOL hidden = (!sender.on); 372 | self.mapViewStatusBarBlur.hidden = hidden; 373 | APP.statusBarHidden = hidden; 374 | } 375 | 376 | - (IBAction)changeContainerEnabledMiddle:(UISwitch *)sender { 377 | self.containerAllowMiddlePosition = sender.on; 378 | } 379 | 380 | - (IBAction)changeContainerZoom:(UISwitch *)sender { 381 | self.containerZoom = sender.on; 382 | } 383 | 384 | - (IBAction)changeShadow:(UISwitch *)sender { 385 | self.containerShadowView = sender.on; 386 | } 387 | 388 | - (IBAction)changeContainerShadow:(UISwitch *)sender { 389 | self.containerShadow = sender.on; 390 | } 391 | 392 | - (IBAction)changeContainerShowBottomButtonToMoveTop:(UISwitch *)sender { 393 | self.containerBottomButtonToMoveTop = sender.on; 394 | } 395 | 396 | 397 | - (IBAction)changeContainerAlpha:(UISlider *)sender { 398 | self.containerView.alpha = sender.value; 399 | } 400 | 401 | - (IBAction)changeContainerMove:(UISegmentedControl *)sender { 402 | if((ContainerMoveType)sender.selectedSegmentIndex == ContainerMoveTypeMiddle) { 403 | self.containerAllowMiddlePosition = YES; 404 | [self.switchEnableMiddle setOn:YES animated: YES]; 405 | } 406 | [self containerMove:(ContainerMoveType)sender.selectedSegmentIndex]; 407 | } 408 | 409 | 410 | - (IBAction)changeContainerTitleType:(UISegmentedControl *)sender { 411 | 412 | switch (sender.selectedSegmentIndex) { 413 | case 0: self.headerView = nil; break; 414 | case 1: { 415 | HeaderGrib *grib = [DemoHeaderViews createHeaderGrip]; 416 | [DemoHeaderViews changeColorsHeaderView:grib forStyle:self.containerStyle]; 417 | self.headerView = grib; 418 | } break; 419 | case 2: { 420 | HeaderLabel *label = [DemoHeaderViews createHeaderLabel]; 421 | [DemoHeaderViews changeColorsHeaderView:label forStyle:self.containerStyle]; 422 | self.headerView = label; 423 | } break; 424 | case 3: { 425 | HeaderSearch *search = [DemoHeaderViews createHeaderSearch]; 426 | search.searchBar.delegate = self; 427 | [DemoHeaderViews changeColorsHeaderView:search forStyle:self.containerStyle]; 428 | self.headerView = search; 429 | } break; 430 | default: break; 431 | } 432 | } 433 | 434 | - (IBAction)changeContainerStyle:(UISegmentedControl *)sender { 435 | 436 | ContainerStyle style = sender.selectedSegmentIndex; 437 | self.containerStyle = style; 438 | 439 | UIView *view = self.headerView; 440 | if(view) [DemoHeaderViews changeColorsHeaderView:view forStyle:style]; 441 | 442 | if(style == ContainerStyleDark) { 443 | if(self.textView) { 444 | self.textView.textColor = WHITE_COLOR; 445 | self.textView.keyboardAppearance = UIKeyboardAppearanceDark; 446 | } 447 | 448 | self.mapView.mapType = MKMapTypeHybrid; 449 | self.mapViewStatusBarBlur.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; 450 | STATUSBAR_STYLE(UIStatusBarStyleLightContent); 451 | // self.mapViewStatusBarBlur.hidden 452 | self.view .backgroundColor = RGB(55, 55, 55); 453 | self.settingsView.backgroundColor = RGB(66, 66, 66); 454 | } else { 455 | if(self.textView) { 456 | self.textView.textColor = BLACK_COLOR; 457 | self.textView.keyboardAppearance = UIKeyboardAppearanceDefault; 458 | } 459 | self.mapView.mapType = MKMapTypeStandard; 460 | self.mapViewStatusBarBlur.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; 461 | STATUSBAR_STYLE(UIStatusBarStyleDefault); 462 | self.view .backgroundColor = RGB(235, 235, 241); 463 | self.settingsView.backgroundColor = RGB(225, 225, 231); 464 | } 465 | 466 | if(self.tableView) { 467 | [self changeTableViewSeparatorStyle]; 468 | [self.tableView reloadData]; 469 | } 470 | if(self.collectionView) { 471 | [self.collectionView reloadData]; 472 | } 473 | 474 | } 475 | 476 | - (void)changeTableViewSeparatorStyle { 477 | UIColor * color; 478 | 479 | switch (self.containerStyle) { 480 | case ContainerStyleDefault: 481 | color = RGBA(222,222,222,1); 482 | break; 483 | case ContainerStyleDark: 484 | color = RGBA(222,222,222,0.2); 485 | break; 486 | case ContainerStyleExtraLight: 487 | case ContainerStyleLight: 488 | color = RGBA(180,180,180,0.5); 489 | break; 490 | 491 | } 492 | [self.tableView setSeparatorColor:color]; 493 | } 494 | 495 | - (IBAction)changeContainerSizeTop:(UISlider *)sender { 496 | CGFloat top = sender.value; 497 | 498 | [self containerMoveCustomPosition:top moveType:ContainerMoveTypeTop animated:YES]; 499 | 500 | self.containerTop = top - IPHONE_X_PADDING_TOP; 501 | self.containerLabelValueTop.text = SFMT(@"%.0f y", top); 502 | } 503 | 504 | - (IBAction)changeContainerSizeBottom:(UISlider *)sender { 505 | CGFloat bottom = sender.value; // (SCREEN_HEIGHT -((sender.maximumValue +50) -sender.value)); 506 | 507 | [self containerMoveCustomPosition: (SCREEN_HEIGHT - bottom) moveType:ContainerMoveTypeBottom animated:NO]; 508 | 509 | self.containerBottom = bottom - IPHONE_X_PADDING_BOTTOM; 510 | self.containerLabelValueBottom.text = SFMT(@"%.0f y", bottom); 511 | } 512 | 513 | 514 | - (IBAction)changeContainerCornerRadius:(UISlider *)sender { 515 | self.containerCornerRadius = sender.value; 516 | self.containerLabelValueCornerRadius.text = SFMT(@"%d", (int)sender.value); 517 | } 518 | 519 | - (IBAction)changeContainerScrollViewType:(UISegmentedControl *)sender { 520 | 521 | if(_tableView) { 522 | [_tableView removeFromSuperview]; 523 | _tableView = nil; 524 | } 525 | if(_collectionView) { 526 | [_collectionView removeFromSuperview]; 527 | _collectionView = nil; 528 | } 529 | if(_textView) { 530 | [_textView removeFromSuperview]; 531 | _textView = nil; 532 | } 533 | 534 | switch (sender.selectedSegmentIndex) { 535 | case 0: { 536 | _tableView = [DemoScrollViews createTableViewWithProtocols:self]; 537 | [self changeTableViewSeparatorStyle]; 538 | [self.containerView addSubview:_tableView]; 539 | } break; 540 | case 1: { 541 | _collectionView = [DemoScrollViews createCollectionViewWithProtocols:self]; 542 | [self.containerView addSubview:_collectionView]; 543 | } break; 544 | case 2: { 545 | _textView = [DemoScrollViews createTextViewWithProtocols:self]; 546 | _textView.textColor = (self.containerStyle == ContainerStyleDark) ?WHITE_COLOR :BLACK_COLOR; 547 | _textView.delegate = self; 548 | [self.containerView addSubview:_textView]; 549 | } break; 550 | default: break; 551 | } 552 | 553 | } 554 | 555 | - (void)textViewDidBeginEditing:(UITextView *)textView { 556 | [self containerMove:ContainerMoveTypeTop animated:YES]; 557 | } 558 | 559 | // TODO: add New Container 560 | //- (IBAction)addNewContainer { 561 | // ContainerView *container = [[ContainerView alloc] initWithFrame: CGRectMake( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT +50 )]; 562 | // [container containerMove:ContainerMoveTypeHide animated:NO]; 563 | // [self.view addSubview:container]; 564 | // [container containerMove:ContainerMoveTypeBottom]; 565 | //} 566 | 567 | 568 | 569 | @end 570 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | NSExceptionDomains 28 | 29 | example.com 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | NSIncludesSubdomains 34 | 35 | 36 | 37 | 38 | NSLocationAlwaysAndWhenInUseUsageDescription 39 | Privacy - Location Always and When In Use Usage Description 40 | NSLocationAlwaysUsageDescription 41 | Privacy - Location Always Usage Description 42 | NSLocationWhenInUseUsageDescription 43 | Privacy - Location When In Use Usage Description 44 | UIAppFonts 45 | 46 | ProximaNova-Regular.otf 47 | ProximaNova-Extrabld.otf 48 | 49 | UILaunchStoryboardName 50 | LaunchScreen 51 | UIMainStoryboardFile 52 | Main 53 | UIRequiredDeviceCapabilities 54 | 55 | armv7 56 | 57 | UISupportedInterfaceOrientations 58 | 59 | UIInterfaceOrientationPortrait 60 | UIInterfaceOrientationLandscapeRight 61 | UIInterfaceOrientationLandscapeLeft 62 | 63 | UISupportedInterfaceOrientations~ipad 64 | 65 | UIInterfaceOrientationPortrait 66 | UIInterfaceOrientationPortraitUpsideDown 67 | UIInterfaceOrientationLandscapeLeft 68 | UIInterfaceOrientationLandscapeRight 69 | 70 | UIViewControllerBasedStatusBarAppearance 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Resources/ProximaNova-Extrabld.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Resources/ProximaNova-Extrabld.otf -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/Resources/ProximaNova-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrustaa/ContainerView/47ba32aa2790b2fd98720e9f5948645924ad4aca/DemoContainerView/DemoContainerView/Resources/ProximaNova-Regular.otf -------------------------------------------------------------------------------- /DemoContainerView/DemoContainerView/main.m: -------------------------------------------------------------------------------- 1 | 2 | // Created by Rustam Motygullin on 03.07.2018. 3 | // Copyright © 2018 mrusta. All rights reserved. 4 | 5 | #import 6 | #import "AppDelegate.h" 7 | 8 | int main(int argc, char * argv[]) { 9 | @autoreleasepool { 10 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rustam Motygullin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ContainerView 2 | 3 | ContainerView is designed to add a cool swim from the bottom to the animation with the effect of scale, controlled by the help of a gesture, scrollView also takes control. 4 | 5 | The idea is taken from the application [Apple Maps](https://www.apple.com/ios/maps/) 6 | 7 | ______________________________ 8 | Also, ☝️ See the new version `Swift` [ContainerController](https://github.com/mrustaa/ContainerController/) 9 | 10 | ## Preview 11 | ![image](https://github.com/mrustaa/gif_presentation/blob/master/Assets/1.gif) 12 | ![image](https://github.com/mrustaa/gif_presentation/blob/master/Assets/2.gif) 13 | ![image(Landscape)](https://github.com/mrustaa/gif_presentation/blob/master/Assets/3.gif) 14 | 15 | 16 | 17 | - [Installation](#installation) 18 | - [CocoaPods](#cocoapods) 19 | - [Getting Started](#getting-started) 20 | - [Setting](#setting) 21 | - [Change position Top Middle Bottom](#change-position-top-middle-bottom) 22 | - [Adding Custom View](#adding-custom) 23 | - [`View` under ContainerView](#view-under-containerview) 24 | - [`ScrollView` in ContainerView](#scrollview-in-containerview) 25 | - [`HeaderView` in ContainerView](#headerview-in-containerview) 26 | - [Protocol](#protocol) 27 | - [Reports the changes current position of the container, after its use](#reports-the-changes-current-position-of-the-container-after-its-use) 28 | - [License](#license) 29 | 30 | 31 | 32 | ## Installation 33 | 34 | ### CocoaPods 35 | 36 | ContainerView is available through [CocoaPods](https://cocoapods.org). To install 37 | it, simply add the following line to your Podfile: 38 | 39 | ```ruby 40 | pod 'ContainerView' 41 | ``` 42 | 43 | ## Getting Started 44 | 45 | ```objc 46 | #import 47 | #import "ContainerViewController.h" 48 | 49 | @interface ViewController : ContainerViewController 50 | @end 51 | ``` 52 | 53 | ## Setting 54 | 55 | ```objc 56 | - (void)viewDidLoad { 57 | [super viewDidLoad]; 58 | 59 | // This parameter for changing the rounding corner radius of the Container 60 | self.containerCornerRadius = 15; 61 | 62 | // This parameter to add a blur to the background of the Container 63 | self.containerStyle = ContainerStyleLight; 64 | 65 | // This parameter adds 3 position (move to the middle). Default there are 2 positions 66 | self.containerAllowMiddlePosition = YES; 67 | 68 | // This parameter allows you to zoom in on the screen under Container 69 | self.containerZoom = YES; 70 | 71 | // This parameter sets the shadow under Container 72 | self.containerShadowView = YES; 73 | 74 | // This parameter sets the shadow in Container 75 | self.containerShadow = YES; 76 | 77 | // This parameter indicates whether to add a button when the container is at the bottom to move the container to the top 78 | self.containerBottomButtonToMoveTop = YES; 79 | } 80 | ``` 81 | 82 | ### Change position Top Middle Bottom 83 | 84 | ```objc 85 | - (void)viewDidLoad { 86 | [super viewDidLoad]; 87 | 88 | // These parameters set the new position value. 89 | self.containerTop = 50; 90 | self.containerMiddle = 200; 91 | self.containerBottom = 400; 92 | } 93 | ``` 94 | 95 | ### Move position with an animation 96 | 97 | ```objc 98 | - (void)moveTop { 99 | [self containerMove:ContainerMoveTypeTop]; 100 | } 101 | 102 | - (void)moveMiddle { 103 | [self containerMove:ContainerMoveTypeMiddle]; 104 | } 105 | 106 | - (void)moveBottom { 107 | [self containerMove:ContainerMoveTypeBottom]; 108 | } 109 | ``` 110 | 111 | ## Adding Custom 112 | 113 | ### `View` under ContainerView 114 | 115 | #### ☝️ Adding all views under the ContainerView necessarily via the `self.bottomView` 116 | 117 | ```objc 118 | - (void)viewDidLoad { 119 | [super viewDidLoad]; 120 | 121 | UILabel *label = [[UILabel alloc]initWithFrame: CGRectMake(18, 26, 60, 30 )]; 122 | label.font = [UIFont boldSystemFontOfSize:24]; 123 | label.textColor = [UIColor redColor]; 124 | label.text = @"Label"; 125 | 126 | [self.bottomView addSubview:label]; 127 | } 128 | ``` 129 | 130 | ### `ScrollView` in ContainerView 131 | 132 | #### ☝️ For all `ScrollView`, add the `self` delegate. Otherwise, moving the container through scrolling will not work. 133 | 134 | ```objc 135 | @interface ViewController () 136 | @end 137 | 138 | @implementation ViewController 139 | 140 | - (void)viewDidLoad { 141 | [super viewDidLoad]; 142 | 143 | UITextView *textView = [[UITextView alloc]initWithFrame:self.view.bounds]; 144 | textView.delegate = self; 145 | textView.returnKeyType = UIReturnKeyDone; 146 | textView.backgroundColor = [UIColor clearColor]; 147 | textView.font = [UIFont systemFontOfSize:46]; 148 | textView.text = @"This \n example \n more \n text \n\n\n\n\n\n\n\n ...."; 149 | 150 | [self.containerView addSubview:textView]; 151 | } 152 | 153 | @end 154 | ``` 155 | 156 | ### `HeaderView` in ContainerView 157 | 158 | ```objc 159 | - (void)addHeader { 160 | 161 | CGFloat height = 60; 162 | 163 | UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, height)]; 164 | 165 | UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 4, self.view.frame.size.width, height -4)]; 166 | searchBar.barStyle = UIBarStyleDefault; 167 | searchBar.searchBarStyle = UISearchBarStyleMinimal; 168 | searchBar.placeholder = @"Search"; 169 | [headerView addSubview:searchBar]; 170 | 171 | self.containerView.headerView = headerView; 172 | } 173 | ``` 174 | 175 | ## Protocol 176 | 177 | ### Reports the changes current position of the container, after its use 178 | 179 | ```objc 180 | @interface ViewController () 181 | @end 182 | 183 | @implementation ViewController 184 | 185 | - (void)changeContainerMove:(ContainerMoveType)containerMove containerY:(CGFloat)containerY animated:(BOOL)animated { 186 | [super changeContainerMove:containerMove containerY:containerY animated:animated]; 187 | ... 188 | } 189 | 190 | @end 191 | ``` 192 | 193 | ## Author 194 | 195 | 📩| [mrustaa](https://github.com/mrustaa/) NOVEMBER 2018 196 | 197 | ## License 198 | 199 | ContainerView is available under the MIT license. See the LICENSE file for more info. 200 | --------------------------------------------------------------------------------