Search code examples
iosuinavigationbarcustom-viewuistatusbar

Add customview in navigation bar like whatsapp


I want to create custom navigation bar like WhatsApp uses to display call indicator in the application as given below.

enter image description here

I have successfully added view like above but it's not responsive because I am not able to detect touch on status bar. I can touch only part below "Touch to return to call".

Code is as given below.

@property (nonatomic) UIView *navigationBarTopView;

UIWindow *window = [UIApplication sharedApplication].keyWindow;
if (_navigationBarTopView == nil) {
    _navigationBarTopView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, window.frame.size.width, 60.0)];
        [_navigationBarTopView setBackgroundColor:[UIColor colorWithRed:76.0/255.0 green:217.0/255.0 blue:100.0/255.0 alpha:1]];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, _navigationBarTopView.frame.size.height - 15, window.frame.size.width, 10)];
    [label setText:@"Touch to return to call"];
    [label setTextColor:[UIColor whiteColor]];
    [label setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]];
    [label setTextAlignment:NSTextAlignmentCenter];
    [_navigationBarTopView addSubview:label];

    //The setup code (in viewDidLoad in your view controller)
    UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    [_navigationBarTopView addGestureRecognizer:singleFingerTap];

    UITapGestureRecognizer *singleFingerTap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    [label addGestureRecognizer:singleFingerTap1];
}

[window addSubview:_navigationBarTopView];

I have also tried to add touch on status bar as give below but it doesn't work.

How do I detect touches on UIStatusBar/iPhone

Also navigation bar is not coming downside. I have tried to set keyWindow frame. But that is also not working.


Solution

  • UIStatusBar has higher priority than your application's window, so you won't get any touch event through status bar.

    To get touch event through status bar you need a window with higher window level than UIStatusBar.

    Try below code:

    #import "AppDelegate.h"
    
    @interface AppDelegate ()
    
    @property (nonatomic) UIWindow *buttonWindow;
    @property (nonatomic) UIWindow *textWindow;
    @property (nonatomic) CGFloat callViewHeight;
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
            if (@available(iOS 11.0, *)) {
            if (([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0)) {
                self.callViewHeight = 55.0f;
            } else {
                self.callViewHeight = 35.0f;
            }
        } else {
            self.callViewHeight = 35.0f;
        }
        return YES;
    }
    
    -(void)showVideoCallButton{
        self.textWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.callViewHeight)];
        self.textWindow.windowLevel = self.window.windowLevel + 1;
        self.textWindow.hidden = FALSE;
    
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.callViewHeight)];
        view.backgroundColor = [UIColor colorWithRed:76.0/255.0 green:217.0/255.0 blue:100.0/255.0 alpha:1];
        view.clipsToBounds = TRUE;
        UILabel *lblName = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.callViewHeight)];
        lblName.textAlignment = NSTextAlignmentCenter;
        [lblName setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]];
        lblName.text = @"";
    
        UILabel *lblTouch = [[UILabel alloc] initWithFrame:CGRectMake(0, self.callViewHeight - 20.0f, [UIScreen mainScreen].bounds.size.width, 20.0f)];
        lblTouch.textAlignment = NSTextAlignmentCenter;
        [lblTouch setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]];
        lblTouch.text = @"Touch to return to call";
        lblTouch.textColor = UIColor.whiteColor;
    
        [view addSubview:lblTouch];
        [view addSubview:lblName];
    
        [self.textWindow addSubview:view];
    
        self.buttonWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.callViewHeight)];
        self.buttonWindow.windowLevel = UIWindowLevelStatusBar + 1;
        self.buttonWindow.hidden = FALSE;
    
        UIButton *button = [[UIButton alloc] initWithFrame:lblName.bounds];
        [button setTitle:@"" forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonTouched) forControlEvents:UIControlEventTouchUpInside];
        [self.buttonWindow addSubview:button];
    
        self.textWindow.transform = CGAffineTransformMakeTranslation(0, -self.callViewHeight);
        self.buttonWindow.transform = CGAffineTransformMakeTranslation(0, -self.callViewHeight);
    
        [UIView animateWithDuration:0.25
                         animations:^{
                             self.textWindow.transform = CGAffineTransformIdentity;
                             self.buttonWindow.transform = CGAffineTransformIdentity;
                             if (@available(iOS 11.0, *)) {
                                 if (([[[UIApplication sharedApplication] delegate] window].safeAreaInsets.top > 20.0)) {
                                     self.window.frame = CGRectMake(0, self.callViewHeight - 40.0f, self.window.bounds.size.width, self.window.bounds.size.height - self.callViewHeight + 40.0f);
                                 } else {
                                     self.window.frame = CGRectMake(0, self.callViewHeight - 20.0f, self.window.bounds.size.width, self.window.bounds.size.height - self.callViewHeight + 20.0f);
                                 }
                             } else {
                                 self.window.frame = CGRectMake(0, self.callViewHeight - 20.0f, self.window.bounds.size.width, self.window.bounds.size.height - self.callViewHeight + 20.0f);
                             }
                         }];
    }
    
    -(void)hideVideoCallButton{
    
        [UIView animateWithDuration:0.25
                         animations:^{
                             self.textWindow.transform = CGAffineTransformMakeTranslation(0, -self.callViewHeight);
                             self.buttonWindow.transform = CGAffineTransformMakeTranslation(0, -self.callViewHeight);
                             self.window.frame = [UIScreen mainScreen].bounds;
                         } completion:^(BOOL finished) {
    
                             dispatch_async(dispatch_get_main_queue(), ^{
                                 self.buttonWindow.hidden = TRUE;
                                 self.buttonWindow = nil;
    
                                 self.textWindow.hidden = TRUE;
                                 self.textWindow = nil;
                             });
    
                         }];
    }
    
    -(void)buttonTouched{
        NSLog(@"Button Touched");
    }
    
    @end