Detecting If User Has in Call Status Bar

Detecting if user has in call status bar

UIApplicationDelegate has these two methods.

// ObjC
- (void)application:(UIApplication *)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame; // in screen coordinates
- (void)application:(UIApplication *)application didChangeStatusBarFrame:(CGRect)oldStatusBarFrame;

// Swift
func application(_ application: UIApplication, willChangeStatusBarFrame newStatusBarFrame: CGRect)
func application(_ application: UIApplication, didChangeStatusBarFrame oldStatusBarFrame: CGRect)

And there are Notifications too.

//ObjC
UIApplicationWillChangeStatusBarFrameNotification
UIApplicationDidChangeStatusBarFrameNotification

// Swift
Notification.Name.UIApplicationWillChangeStatusBarFrame
Notification.Name.UIApplicationDidChangeStatusBarFrame

but they're not posted on the launch of the app, so I wouldn't recommend it.

The simulator has an useful tool to test that.

Hardware->Toggle In-Call Status Bar (⌘Y)

I would suggest you to implement those methods on your AppDelegate file. They will be called when the status bar change it's height. One of them it's called before and the other after the change.

Assuming you want that your ViewController to be notified when the change occurs, one option, is to send notifications. Like this

First, add this property/variable on AppDelegate

// ObjC
@property (assign, nonatomic) CGRect currentStatusBarFrame;

// Swift
var currentStatusBarFrame: CGRect = .zero

then, implement willChangeStatusBarFrame

// ObjC
- (void) application:(UIApplication *)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame
{
self.currentStatusBarFrame = newStatusBarFrame;
[[NSNotificationCenter defaultCenter] postNotificationName:@"Status Bar Frame Change"
object:self
userInfo:@{@"current status bar frame": [NSValue valueWithCGRect:newStatusBarFrame]}];

}

// Swift
func application(_ application: UIApplication, willChangeStatusBarFrame newStatusBarFrame: CGRect) {
currentStatusBarFrame = newStatusBarFrame
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: "Status Bar Frame Change"),
object: self,
userInfo: ["current status bar frame": newStatusBarFrame])
}

And we're done with the base of our Status Bar Frame Checker. The next part you implement on any ViewController that needs to know the status bar frame.

Any time you want to get the status bar frame, you do like so

// ObjC
[(AppDelegate*)[[UIApplication sharedApplication] delegate] currentStatusBarFrame]

// Swift
(UIApplication.shared.delegate as! AppDelegate).currentStatusBarFrame

And to be notified when it changes, add this to ViewDidLoad method.

In ObjC

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarFrameChanged:)
name:@"Status Bar Frame Change"
object:[[UIApplication sharedApplication] delegate]];

And implement this method

- (void) statusBarFrameChanged:(NSNotification*)notification
{
CGRect newFrame = [[notification.userInfo objectForKey:@"current status bar frame"] CGRectValue];
NSLog(@"new height %f", CGRectGetHeight(newFrame));
}

In Swift

    NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "Status Bar Frame Change"),
object: nil,
queue: nil) { (note) in
guard let currentStatusBarFrame = note.userInfo?["current status bar frame"] as? CGRect else {return}
print("New Height", currentStatusBarFrame.height)
}

How to detect touches in status bar

So this is my current solution, which works amazingly well. But please come with other ideas, as I don't really like it...

  • Add a scrollview somewhere in your view. Maybe hide it or place it below some other view etc.
  • Set its contentSize to be larger than the bounds
  • Set a non-zero contentOffset
  • In your controller implement a delegate of the scrollview like shown below.

By always returning NO, the scroll view never scrolls up and one gets a notification whenever the user hits the status bar. The problem is, however, that this does not work with a "real" content scroll view around. (see question)

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
// Do your action here
return NO;
}

How do I detect touches on UIStatusBar/iPhone

Based on Tom's answer, I wrote the code. It works well.

- (void)viewDidLoad {
[super viewDidLoad];
// required
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
scrollView.delegate = self;
scrollView.contentSize = CGSizeMake(0.0f,1.0f);
[scrollView setContentOffset:CGPointMake(0.0f,1.0f) animated:NO];
// optional
scrollView.scrollsToTop = YES; // default is YES.
[self.view addSubview:scrollView];
}

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
NSLog(@"Detect status bar is touched.");
/* Your own code. */
return NO;
}

How can you check if status bar is visible in Android

I had to start my activity in android:launchMode="singleInstance" and in OnAttachedToWindow() i had to call this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
Now the status bar won't be shown even if other Activities in the same application do show the status bar.

How to detect programmatically that call is on hold in iOS?

We can use CallKit Framework to get the Call Hold event.

We need to conform to CXCallObserver Delegate

 [_callObserver setDelegate:self queue:nil];

where _callObserver is the instance of my CXCallObserver class

- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call {
if (call.isOnHold == true) {
NSLog(@"Call is on hold");
}
}

Check if status bar is already visible on iPhone before loading app

Click on your project in the file navigator see section deployment info -> see status bar style -> check hide status bar. Or add Status Bar Initially Hide true in your app's plist does the same thing.
deployment screen



Related Topics



Leave a reply



Submit