17 Mar 2017

Bottom Bar(Dragging a view from bottom of controller to Top) it is with collection View...



Bottom Bar(Dragging a view from bottom of controller to Top) it is with collection View...


storyBoard:

#import <UIKit/UIKit.h>
#import "NRTranslucentSideBar.h"

@interface ViewController : UIViewController

@property (nonatomic, strong) NRTranslucentSideBar *bottomBar;

@end


#import "ViewController.h"

@interface ViewController () <NRTranslucentSideBarDelegate,UICollectionViewDelegate, UICollectionViewDataSource>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //Example of Bottom Sidebar
    self.bottomBar = [[NRTranslucentSideBar alloc] init];
    self.bottomBar.delegate = self;
    self.bottomBar.translucentStyle = UIBarStyleBlack;
    self.bottomBar.tag = 1;
    
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    
    [self.view addGestureRecognizer:panGestureRecognizer];
    
    // Top Sidebar with CollectionView
    UICollectionView *collectionView;
   
    UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.itemSize = CGSizeMake(100, 100);
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    collectionView = [[UICollectionView alloc] initWithFrame: CGRectMake(20, 20, self.view.frame.size.width, self.view.frame.size.height) /*self.view.frame*/ collectionViewLayout:flowLayout];
    collectionView.delegate = self;
    collectionView.dataSource = self;
    [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];

   
    
    // Set ContentView in SideBar
    [self.bottomBar setContentViewInSideBar:collectionView];
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer
{
    
    // if you have only one sidebar, do like following
    
     self.bottomBar.isCurrentPanGestureTarget = YES;
     [self.bottomBar handlePanGestureToShow:recognizer inView:self.view];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - UICollectionViewDataSource

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    
    NSLog(@"Given insets top,left,bottom, right");
    return UIEdgeInsetsMake(10, 10, 5, 5);
    
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    
    return 50;
}

- (UICollectionViewCell  *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
    cell.contentView.backgroundColor = [UIColor blueColor];
    UIImageView *imageView = [[ UIImageView alloc]initWithFrame:CGRectMake(5, 5, 90, 90)];
    imageView.image = [UIImage imageNamed:@"image.jpg"];
    [cell.contentView addSubview:imageView];
  
    return cell;
}

#pragma mark - UICollectionViewDelegate

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"calling didselctitem at path %ld",(long)indexPath.item);
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"diddeselectitem");
}


@end




#import <UIKit/UIKit.h>

@class NRTranslucentSideBar;

@protocol NRTranslucentSideBarDelegate <NSObject>

@optional

- (void)sideBar:(NRTranslucentSideBar *)sideBar didAppear:(BOOL)animated;
- (void)sideBar:(NRTranslucentSideBar *)sideBar willAppear:(BOOL)animated;
- (void)sideBar:(NRTranslucentSideBar *)sideBar didDisappear:(BOOL)animated;
- (void)sideBar:(NRTranslucentSideBar *)sideBar willDisappear:(BOOL)animated;

@end

@interface NRTranslucentSideBar : UIViewController <UIGestureRecognizerDelegate>


@property (nonatomic, assign) CGFloat sideBarHeight;
@property (nonatomic, assign) CGFloat animationDuration;
@property (nonatomic) BOOL translucent;
@property (nonatomic) UIBarStyle translucentStyle;
@property (nonatomic) CGFloat translucentAlpha;
@property (nonatomic, strong) UIColor *translucentTintColor;
@property (readonly) BOOL hasShown;
@property BOOL isCurrentPanGestureTarget;
@property NSInteger tag;

@property (nonatomic, weak) id <NRTranslucentSideBarDelegate> delegate;

- (instancetype)init;

- (void)show;
- (void)showAnimated:(BOOL)animated;
- (void)showInViewController:(UIViewController *)controller;
- (void)showInViewController:(UIViewController *)controller animated:(BOOL)animated;

- (void)dismiss;
- (void)dismissAnimated:(BOOL)animated;

- (void)handlePanGestureToShow:(UIPanGestureRecognizer *)recognizer inView:(UIView *)view;
- (void)handlePanGestureToShow:(UIPanGestureRecognizer *)recognizer inViewController:(UIViewController *)controller;

- (void)setContentViewInSideBar:(UIView *)contentView;

@end

#import "NRTranslucentSideBar.h"

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

@interface NRTranslucentSideBar ()

@property (nonatomic, strong) UIToolbar *translucentView;
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer;
@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer;
@property CGPoint panStartPoint;

@end

@implementation NRTranslucentSideBar

- (instancetype)init {
    self = [super init];
    if (self) {
        [self initNRTranslucentSideBar];
    }
    return self;
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

#pragma mark - Custom Initializer
- (void)initNRTranslucentSideBar {
    _hasShown = NO;
    self.isCurrentPanGestureTarget = NO;
    
    self.sideBarHeight = 600;
    self.animationDuration = 0.5f;
    
    [self initTranslucentView];
    
    self.view.backgroundColor = [UIColor clearColor];
    self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
    self.tapGestureRecognizer.delegate = self;
    [self.view addGestureRecognizer:self.tapGestureRecognizer];
    self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    self.panGestureRecognizer.minimumNumberOfTouches = 1;
    self.panGestureRecognizer.maximumNumberOfTouches = 1;
    [self.view addGestureRecognizer:self.panGestureRecognizer];
}

- (void)initTranslucentView {
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        CGRect translucentFrame =
        CGRectMake(self.view.bounds.size.height, -self.sideBarHeight, self.view.bounds.size.width, self.sideBarHeight);
        self.translucentView = [[UIToolbar alloc] initWithFrame:translucentFrame];
        self.translucentView.frame = translucentFrame;
        self.translucentView.contentModeUIViewContentModeTop;
        self.translucentView.clipsToBounds = YES;
        self.translucentView.barStyle = UIBarStyleDefault;
        [self.view.layer insertSublayer:self.translucentView.layer atIndex:0];
    }
}

#pragma mark - View Life Cycle
- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)loadView {
    [super loadView];
}

#pragma mark - Layout
- (BOOL)shouldAutorotate {
    return YES;
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    
    if ([self isViewLoaded] && self.view.window != nil) {
        [self layoutSubviews];
    }
}

- (void)layoutSubviews {
    CGFloat y =  self.parentViewController.view.bounds.size.height - self.sideBarHeight;
    
    if (self.contentView != nil) {
        self.contentView.frame = CGRectMake(0, y, self.parentViewController.view.bounds.size.width, self.sideBarHeight);
    }
}

#pragma mark - Accessor
- (void)setTranslucentStyle:(UIBarStyle)translucentStyle {
    self.translucentView.barStyle = translucentStyle;
}

- (UIBarStyle)translucentStyle {
    return self.translucentView.barStyle;
}

- (void)setTranslucent:(BOOL)translucent {
    self.translucentView.translucent = translucent;
}

- (BOOL)translucent {
    return self.translucentView.translucent;
}

- (void)setTranslucentAlpha:(CGFloat)translucentAlpha {
    self.translucentView.alpha = translucentAlpha;
}

- (CGFloat)translucentAlpha {
    return self.translucentView.alpha;
}

- (void)setTranslucentTintColor:(UIColor *)translucentTintColor {
    self.translucentView.barTintColor = translucentTintColor;
}

- (UIColor *)translucentTintColor {
    return self.translucentView.barTintColor;
}

#pragma mark - Show
- (void)showInViewController:(UIViewController *)controller animated:(BOOL)animated {
    if ([self.delegate respondsToSelector:@selector(sideBar:willAppear:)]) {
        [self.delegate sideBar:self willAppear:animated];
    }
    
    [self addToParentViewController:controller callingAppearanceMethods:YES];
    self.view.frame = controller.view.bounds;
    
    CGFloat parentHeight = self.view.bounds.size.height;
    CGRect sideBarFrame = self.view.bounds;
    sideBarFrame.origin.y =  parentHeight;
    sideBarFrame.size.height = self.sideBarHeight;
    
    if (self.contentView != nil) {
        self.contentView.frame = sideBarFrame;
    }
    sideBarFrame.origin.y = parentHeight - self.sideBarHeight;
    
    void (^animations)() = ^{
        if (self.contentView != nil) {
            self.contentView.frame = sideBarFrame;
        }
        self.translucentView.frame = sideBarFrame;
    };
    void (^completion)(BOOL) = ^(BOOL finished)
    {
        _hasShown = YES;
        self.isCurrentPanGestureTarget = YES;
        if (finished && [self.delegate respondsToSelector:@selector(sideBar:didAppear:)]) {
            [self.delegate sideBar:self didAppear:animated];
        }
    };
    
    if (animated) {
        [UIView animateWithDuration:self.animationDuration delay:0 options:kNilOptions animations:animations completion:completion];
    }
    else {
        animations();
        completion(YES);
    }
}

-(void)showInViewController:(UIViewController *)controller {
    [self showInViewController:controller animated:YES];
}

- (void)showAnimated:(BOOL)animated {
    UIViewController *controller = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (controller.presentedViewController != nil) {
        controller = controller.presentedViewController;
    }
    [self showInViewController:controller animated:animated];
}

- (void)show {
    [self showAnimated:YES];
}

#pragma mark - Show by Pangesture
- (void)startShow:(CGFloat)startY {
    UIViewController *controller = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (controller.presentedViewController != nil) {
        controller = controller.presentedViewController;
    }
    [self startShowInViewController:controller startY:startY];
}

-(void)startShowInViewController:(UIViewController *)controller startY:(CGFloat)startY{
    [self addToParentViewController:controller callingAppearanceMethods:YES];
    self.view.frame = controller.view.bounds;
    
    CGFloat parentHeight = self.view.bounds.size.height;
    
    CGRect sideBarFrame = self.view.bounds;
    sideBarFrame.origin.y = parentHeight;
    sideBarFrame.size.height = self.sideBarHeight;
    if (self.contentView != nil) {
        self.contentView.frame = sideBarFrame;
    }
    self.translucentView.frame = sideBarFrame;
}

- (void)move:(CGFloat)deltaFromStartY {
    CGRect sideBarFrame = self.translucentView.frame;
    CGFloat parentHeight = self.view.bounds.size.height;
    
        CGFloat y = deltaFromStartY;
        if (deltaFromStartY >= self.sideBarHeight) {
            y = self.sideBarHeight;
        }
        sideBarFrame.origin.y = parentHeight - y;
    
    if (self.contentView != nil) {
        self.contentView.frame = sideBarFrame;
    }
    self.translucentView.frame = sideBarFrame;
}

- (void)showAnimatedFrom:(BOOL)animated deltaY:(CGFloat)deltaYFromStartYToEndY {
    if ([self.delegate respondsToSelector:@selector(sideBar:willAppear:)]) {
        [self.delegate sideBar:self willAppear:animated];
    }
    
    CGRect sideBarFrame = self.translucentView.frame;
    CGFloat parentHeight = self.view.bounds.size.height;
    
    sideBarFrame.origin.y = parentHeight - sideBarFrame.size.height;
    
    void (^animations)() = ^{
        if (self.contentView != nil) {
            self.contentView.frame = sideBarFrame;
        }
        
        self.translucentView.frame = sideBarFrame;
    };
    void (^completion)(BOOL) = ^(BOOL finished)
    {
        _hasShown = YES;
        if (finished && [self.delegate respondsToSelector:@selector(sideBar:didAppear:)]) {
            [self.delegate sideBar:self didAppear:animated];
        }
    };
    
    if (animated) {
        [UIView animateWithDuration:self.animationDuration delay:0 options:kNilOptions animations:animations completion:completion];
    }
    else {
        animations();
        completion(YES);
    }
}

#pragma mark - Dismiss
- (void)dismiss {
    [self dismissAnimated:YES];
}

- (void)dismissAnimated:(BOOL)animated {
    if ([self.delegate respondsToSelector:@selector(sideBar:willDisappear:)]) {
        [self.delegate sideBar:self willDisappear:animated];
    }
    
    void (^completion)(BOOL) = ^(BOOL finished)
    {
        [self removeFromParentViewControllerCallingAppearanceMethods:YES];
        _hasShown = NO;
        self.isCurrentPanGestureTarget = NO;
        if ([self.delegate respondsToSelector:@selector(sideBar:didDisappear:)]) {
            [self.delegate sideBar:self didDisappear:animated];
        }
    };
    
    if (animated) {
        CGRect sideBarFrame = self.translucentView.frame;
        CGFloat parentHeight = self.view.bounds.size.height;
        sideBarFrame.origin.y = parentHeight;
        [UIView animateWithDuration:self.animationDuration
                              delay:0
                            options:UIViewAnimationOptionBeginFromCurrentState
                         animations: ^{
                             if (self.contentView != nil) {
                                 self.contentView.frame = sideBarFrame;
                             }
                             self.translucentView.frame = sideBarFrame;
                         }
                         completion:completion];
    }
    else {
        completion(YES);
    }
}

#pragma mark - Dismiss by Pangesture
- (void)dismissAnimated:(BOOL)animated deltaY:(CGFloat)deltaYFromStartYToEndY {
    if ([self.delegate respondsToSelector:@selector(sideBar:willDisappear:)]) {
        [self.delegate sideBar:self willDisappear:animated];
    }
    
    void (^completion)(BOOL) = ^(BOOL finished)
    {
        [self removeFromParentViewControllerCallingAppearanceMethods:YES];
        _hasShown = NO;
        self.isCurrentPanGestureTarget = NO;
        if ([self.delegate respondsToSelector:@selector(sideBar:didDisappear:)]) {
            [self.delegate sideBar:self didDisappear:animated];
        }
    };
    
    if (animated) {
        CGRect sideBarFrame = self.translucentView.frame;
        CGFloat parentHeight = self.view.bounds.size.height;
        sideBarFrame.origin.y = parentHeight;
        
        [UIView animateWithDuration:self.animationDuration
                              delay:0
                            options:UIViewAnimationOptionBeginFromCurrentState
                         animations: ^{
                             if (self.contentView != nil) {
                                 self.contentView.frame = sideBarFrame;
                             }
                             self.translucentView.frame = sideBarFrame;
                         }
         
                         completion:completion];
    }
    else {
        completion(YES);
    }
}

#pragma mark - Gesture Handler
- (void)handleTapGesture:(UITapGestureRecognizer *)recognizer {
    CGPoint location = [recognizer locationInView:self.view];
    if (!CGRectContainsPoint(self.translucentView.frame, location)) {
        [self dismissAnimated:YES];
    }
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {
    if (!self.isCurrentPanGestureTarget) {
        return;
    }
    
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.panStartPoint = [recognizer locationInView:self.view];
    }
    
    if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint currentPoint = [recognizer locationInView:self.view];
        [self move:self.sideBarHeight + self.panStartPoint.y - currentPoint.y];

    }
    
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGPoint endPoint = [recognizer locationInView:self.view];
        
            if (self.panStartPoint.y - endPoint.y >= self.sideBarHeight / 3) {
                [self showAnimatedFrom:YES deltaY:self.panStartPoint.y - endPoint.y];
            }
            else {
                [self dismissAnimated:YES deltaY:self.panStartPoint.x - endPoint.x];
            }
      }
}

- (void)handlePanGestureToShow:(UIPanGestureRecognizer *)recognizer inView:(UIView *)view {
    if (!self.isCurrentPanGestureTarget) {
        return;
    }
    
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.panStartPoint = [recognizer locationInView:view];
        [self startShow:self.panStartPoint.y];
    }
    
    if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint currentPoint = [recognizer locationInView:view];
      
        [self move:self.panStartPoint.y - currentPoint.y];
    }
    
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGPoint endPoint = [recognizer locationInView:view];
        
            if (self.panStartPoint.y - endPoint.y >= self.sideBarHeight / 3) {
                [self showAnimatedFrom:YES deltaY:self.panStartPoint.y - endPoint.y];
            }
            else {
                [self dismissAnimated:YES deltaY:self.panStartPoint.y - endPoint.y];
            }
      }
}

-(void)handlePanGestureToShow:(UIPanGestureRecognizer *)recognizer inViewController:(UIViewController *)controller {
    if (!self.isCurrentPanGestureTarget) {
        return;
    }
    
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.panStartPoint = [recognizer locationInView:controller.view];
        [self startShowInViewController:controller startY:self.panStartPoint.y];
    }
    
    if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint currentPoint = [recognizer locationInView:controller.view];
     
            [self move:self.panStartPoint.y - currentPoint.y];
    }
    
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGPoint endPoint = [recognizer locationInView:controller.view];
        
            if (self.panStartPoint.y - endPoint.y >= self.sideBarHeight / 3) {
                [self showAnimatedFrom:YES deltaY:self.panStartPoint.y - endPoint.y];
            }
            else {
                [self dismissAnimated:YES deltaY:self.panStartPoint.y - endPoint.y];
            }
     }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (touch.view != gestureRecognizer.view) {
        return NO;
    }
    return YES;
}

#pragma mark - ContentView
- (void)setContentViewInSideBar:(UIView *)contentView {
    if (self.contentView != nil) {
        [self.contentView removeFromSuperview];
    }
    
    self.contentView = contentView;
    self.contentView.backgroundColor = [UIColor clearColor];
    [self.view addSubview:self.contentView];
}

#pragma mark - Helper
- (void)addToParentViewController:(UIViewController *)parentViewController callingAppearanceMethods:(BOOL)callAppearanceMethods {
    if (self.parentViewController != nil) {
        [self removeFromParentViewControllerCallingAppearanceMethods:callAppearanceMethods];
    }
    
    if (callAppearanceMethods) [self beginAppearanceTransition:YES animated:NO];
    [parentViewController addChildViewController:self];
    [parentViewController.view addSubview:self.view];
    [self didMoveToParentViewController:self];
    if (callAppearanceMethods) [self endAppearanceTransition];
}

- (void)removeFromParentViewControllerCallingAppearanceMethods:(BOOL)callAppearanceMethods {
    if (callAppearanceMethods) [self beginAppearanceTransition:NO animated:NO];
    [self willMoveToParentViewController:nil];
    [self.view removeFromSuperview];
    [self removeFromParentViewController];
    if (callAppearanceMethods) [self endAppearanceTransition];
}

@end

Result:

No comments:

Post a Comment

Recent Posts

Codable demo

Link: https://www.dropbox.com/s/kw7c1kgv1628bh7/codableDemo.zip?dl=0