17 Mar 2017

Top Bar (Like side menu but it's an top to down menu e.g.. in our ph to on wifi, bluetooth we drag a view from top to down)...


Top Bar (Like side menu but it's an top to down menu e.g.. in our ph to on wifi, bluetooth we drag a view from top to down)...


StoryBoard:


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

@interface ViewController : UIViewController

@property (nonatomic, strong) NRTranslucentSideBar *sideBar;

@end


#import "ViewController.h"

@interface ViewController () <NRTranslucentSideBarDelegate,UITableViewDelegate, UITableViewDataSource>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    
    self.sideBar = [[NRTranslucentSideBar alloc] init];
    self.sideBar.delegate = self;
    self.sideBar.translucentStyle = UISearchBarStyleDefault;
    self.sideBar.tag = 0;
    
    // Top Sidebar with TableView
    UITableView *tableView = [[UITableView alloc] init];
    tableView.dataSource = self;
    tableView.delegate = self;
    tableView.separatorColor = [UIColor blueColor];
    
    // Set ContentView in SideBar
    [self.sideBar setContentViewInSideBar:tableView];
    
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    
    [self.view addGestureRecognizer:panGestureRecognizer];
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer
{
     self.sideBar.isCurrentPanGestureTarget = YES;
     [self.sideBar handlePanGestureToShow:recognizer inView:self.view];
}

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

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}

- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    
    NSString *sectionName;
    if (section == 0)
        sectionName = @"Section 0";
    
    if (section == 1)
        sectionName = @"Section 1";

    return sectionName;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSInteger numOfRows = 0;
    numOfRows = section == 0 ? 15 : 10; //if else single line condition
    return numOfRows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:MyIdentifier] ;
    }
    @try {
        cell.textLabel.text = @"Top Side Bar with tableView";
        cell.textLabel.textColor = [UIColor greenColor];
    }
    @catch (NSException *exception) {
    }
    @finally {
    }
    return cell;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    NSLog(@"Table view didselectRowAtIndexPath method called");
}

@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 = 580;
    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(0,-self.sideBarHeight, self.view.bounds.size.width, self.sideBarHeight);
        self.translucentView = [[UIToolbar alloc] initWithFrame:translucentFrame];
        self.translucentView.frame = translucentFrame;
        self.translucentView.contentMode = UIViewContentModeScaleAspectFill;
        self.translucentView.clipsToBounds = YES;
        self.translucentView.barStyle = UIBarStyleDefault;
        

        [self.view addSubview:self.translucentView];
//        [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 {
   
    if (self.contentView != nil) {
        self.contentView.frame = CGRectMake(0, 0, 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;
    
    CGRect sideBarFrame = self.view.bounds;
    sideBarFrame.origin.y = -self.sideBarHeight;
    sideBarFrame.size.height = self.sideBarHeight;
    
    if (self.contentView != nil) {
        self.contentView.frame = sideBarFrame;
    }
    sideBarFrame.origin.y0;
    
    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;
    
    CGRect sideBarFrame = self.view.bounds;
    sideBarFrame.origin.y = -self.sideBarHeight;
    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 y = deltaFromStartY - _sideBarHeight;
        if (y >= 0) {
            y = 0;
        }
        sideBarFrame.origin.y = 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;
    
    sideBarFrame.origin.y = 0;
    
    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;
        sideBarFrame.origin.y =  -self.sideBarHeight;
        [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;
        sideBarFrame.origin.y = -self.sideBarHeight;
        
        [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 + currentPoint.y - self.panStartPoint.y];

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

- (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:currentPoint.y - self.panStartPoint.y];
    }
    
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGPoint endPoint = [recognizer locationInView:view];
        
            if (endPoint.y - self.panStartPoint.y >= self.sideBarHeight / 3) {
                [self showAnimatedFrom:YES deltaY:endPoint.y - self.panStartPoint.y];
            }
            else {
                [self dismissAnimated:YES deltaY:endPoint.y - self.panStartPoint.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:currentPoint.y - self.panStartPoint.y];
    }
    
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGPoint endPoint = [recognizer locationInView:controller.view];
        
            if (endPoint.y - self.panStartPoint.y >= self.sideBarHeight / 3) {
                [self showAnimatedFrom:YES deltaY:endPoint.y - self.panStartPoint.y];
            }
            else {
                [self dismissAnimated:YES deltaY:endPoint.y - self.panStartPoint.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