How do I detect touches on UIStatusBar/iPhone - ios

I'm trying to detect any touch on the iPhone's UIStatusBar but its not working. I've tried subclassing UIApplication and UIWindow to access it but still nothing.

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;
}

You need to have a UIScrollView in your responder chain, and it needs to have a delegate set. You can then override scrollViewShouldScrollToTop: in the delegate, which will be called when the user taps on the status bar. Be sure to return NO if you don't want the default behavior of scrolling the scroll view back to the top.

You can't. The status bar is held by the application. You can only turn it on and off.
More importantly, any fiddling with the status bar is likely to get your app rejected by Apple because it could interfere with the operation of the hardware e.g. disguising or hiding a low battery.
If you need full screen touches for your views you should just hide the status bar.

Related

How do I add a subview to UIStatusBar in Theos?

I know it sounds like this question has a simple answer, but hear me out. Although UIStatusBar is a subclass of UIView, you can't use the addSubview method to add a subview to it because it doesn't use it. The same goes for UIStatusBarWindow. Neither the view or window have a viewcontroller, so I can't hook into that in any way.
Here is the relevant section of code. The line where I call the addSubviews method on self is the issue, because addSubviews isn't a method of UIStatusBar.
#import <CoreGraphics/CoreGraphics.h>
#interface UIStatusBar : UIView
#end
%hook UIStatusBar
- (void)layoutSubviews {
//Round corners under status bar
CGFloat radius = 15;
CGRect wholeScreen = [[UIScreen mainScreen] bounds];
UIView *roundedCorners = [[UIView alloc] initWithFrame: CGRectMake(-radius, 20-radius, wholeScreen.size.width+2*radius, wholeScreen.size.height-20+2*radius)];
roundedCorners.layer.borderWidth = radius;
roundedCorners.layer.cornerRadius = 2*radius;
roundedCorners.layer.borderColor = UIColor.blackColor.CGColor;
roundedCorners.userInteractionEnabled = NO;
[self addSubView:roundedCorners];
}
%end
Is there another way I can add the subview? The reason I'm trying to do it this way is so that, whenever the status bar is hidden, my roundedCorners view is also hidden. I could hide it whenever the status bar is hidden, but due to different apps using many different methods of hiding the status bar that doesn't work out as well as I hoped.
I think a solution here is to use the notifications delivered whenever the status bar's height changes.
Using either/both:
UIApplicationWillChangeStatusBarFrameNotification
UIApplicationDidChangeStatusBarFrameNotification
or you can also use the AppDelegate methods that get called when the status bar changes frame:
-application:willChangeStatusBarFrame:
-application:didChangeStatusBarFrame:
You can in these methods adjust your rounded corners according to the status bar's new frame. Hopefully this solves you problem!

Adding MKMapView Causes Status Bar Issue in iOS 7

I'm solving the status bar issue in iOS 7 using
if(st.version == 7)
{
CGRect screen = [[UIScreen mainScreen] bounds];
CGRect frame = self.navigationController.view.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
self.navigationController.view.frame = frame;
}
Since I'm using navigation controller and pushing from one to another using [self.navigationController pushViewController:newone animated:YES];. It works fine in all view controllers. But, if the viewcontroller has mkmapview in xib, status bar issue of ios 7 occurs.
If I delete the mapview form xib and push to that view controller means, it will be like,
If I add the mapview even by code below,
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 100, 320, 100)];
[self.view addSubview:self.mapView];
It looks like,
How to solve this?
if(st.version == 7){
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 120, 320, 100)];
}else{
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 100, 320, 100)];
}
If you add mapView in viewWillAppear replace it in viewDidAppear.
Maybe you have this issue because you're doing manipulations with view's frames before your view is completely set up
I would highly suggest against doing it like that.
If you're using interface builder, then add constraints based on how you want your application to look and the frame will auto adjust itself.
If you're not using interface builder, then still use constraints, but get a good tutorial about making constraints programatically (as I don't know how to do it myself).
Edit: The reason I HIGHLY suggest not doing it with hardcoded numbers is that it'll be a pain to do iOS 6/7 Landscape/Portrait 3.5/4 inch screens. That's 8 cases.
i think you have some adjust your navigation Y position set -20px. that way it goes overlay. use this code your ViewController
CGRect screen = [[UIScreen mainScreen] bounds];
CGRect frame = self.navigationController.view.frame;
frame.origin.y =0;
frame.size.height = screen.size.height;
self.navigationController.view.frame = frame;
or may it you have use wantFullScreenLayout some where in your project
setWantsFullScreenLayout = YES:
statusbar section is located to the (0,0) point to catch.
Statusbar and as large as the size of the current view to increase the value of mainScreen change the size of the bounds.
Statusbar change the style of the translucent style.
this below link you get some clear idea about your issue
How do I get the navigation bar in a UINavigationController to update its position when the status bar is hidden?
Override the -edgesForExtendedLayout method in your view controller
-(UIRectEdge)edgesForExtendedLayout {
return UIRectEdgeNone;
}
If you want to hide status bar from a particular view add this method in that particular view.m file
- (BOOL)prefersStatusBarHidden
{
return YES;
}
What about setting self.automaticallyAdjustsScrollViewInsets = NO; in viewDidLoad of your view controller or in IB?
Try to set MapView(ScrollView) automaticallyAdjustsScrollViewInsets = NO;
Try to set edgesForExtendedLayout to UIRectEdgeNone;
Try to use UIViewController.topLayoutGuide, see the Q&A from apple about this issue:Preventing the Status Bar from Covering Your Views.
Try to use the bar position delegation, see UIBarPositioningDelegate Protocol Reference
According to your description and screenshots, you are trying to move the whole UINavigationController.view.frame 20 pt, and the MapView(ScrollView) did something to prevent it happened (or re-set), put some breakpoint and log to track the frame of UINavigationController.view.frame changed.
Could you please provide a sample project? I'm so curious about what really happened.
try this
- (void)viewWillAppear:(BOOL)animated
{
self.navigationController.navigationBar.translucent = NO;
}
- (void)viewDidAppear:(BOOL)animated
{
self.navigationController.navigationBar.translucent = YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[application setStatusBarHidden:YES];
return YES;}
Please add this line to your code.This will hide the status bar from your app.
If you have a xib. Did you try to enabled Top Bar in simulated Metrics ?

iOS 7 UISearchBar right spacing

Don't know why, my search bar in iOS 7 is leaving a right space. It's ok in iOS 6.
I know it has something to do with the section index, because if I remove it the space disappears, but I don't know how to fix it. Any thoughts?
Embed your UISearchBar in a UIView and then add that as the tableHeaderView. Structuring it that way in a storyboard worked for me. I'm guessing iOS resizes the UISearchBar in the tableHeaderView, but leaves a basic UIView alone (and doesn't bother to look inside it).
You might also want to make the section index transparent, which I did with:
[[UITableView appearance] setSectionIndexBackgroundColor:[UIColor clearColor]];
[[UITableView appearance] setSectionIndexTrackingBackgroundColor:[UIColor clearColor]];
Until a better answer appears, I just manually changed the frame of the search bar like this:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGRect barFrame = self.searchBar.frame;
barFrame.size.width = self.view.bounds.size.width;
self.searchBar.frame = barFrame;
}
I had this same issue with the iPhone 6/ 6Plus when using a SearchDisplayController. (Using Swift)
I tried setting the frame of the search bar but with no luck but i noticed that if i tapped on the textField of the UISearchBar and then cancelled it then it would take on the proper size of the view. I therefore managed to fix the issue by calling the code below in ViewDidLoad of the viewController using the search.
self.searchController.setActive(true, animated: false)
self.searchController.setActive(false, animated: false)
self.contactsTableView.sectionIndexBackgroundColor = [UIColor clearColor];
The reason for that white edge is because your index layer has a white background and is on top of the search bar. This should be sufficient.
Add the search bar inside a UIView put as tableView's header view. Set the tableview's sectionIndexBackgroundColor to clear color because it covers the header.
Tested with iOS 7, 7.1;
Because the table view always leaves 15px on the right for section Indexes View, so you should resize the Seach bar after reloading the table view
First:
self.tblData.sectionIndexBackgroundColor = [UIColor clearColor]; //(iOS >= 7 only)
Cheating time:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
[self performSelector:#selector(resizeSearchBar) withObject:nil afterDelay:0.01];
}
- (void) resizeSearchBar
{
CGRect frame = self.searchBar.frame;
if (frame.size.width < self.tblData.frame.size.width) {
frame.size.width = self.tblData.frame.size.width;
}
self.searchBar.frame = frame;
}
- (void) reloadTableData // call it anytime you want to reload table view
{
[self.tblData reloadData];
[self performSelector:#selector(resizeSearchBar) withObject:nil afterDelay:0.01];
}
Suggest
Dont cheat like me, just do the simpler way:
self.searchBar.searchBarStyle = UISearchBarStyleMinimal; // iOS >= 7 only
I also attached a UISearcBar in my application, and nothing is wrong there even my application supports rotation also.
Could you try removing and re creating UISearchBar in storyboard/xib
I added the search bar as a subview of the top-level view instead of the table view. Used autolayout to pin the searchbar to the top guide, and a vertical space constraint of 0 between the search bar and the table view.
The accepted solution with the method viewDidLayoutSubviews makes the screen flicker.
Instead what I did was create a subclass of UISearchBar that simply does this:
FullWidthSearchBar.h:
#interface FullWidthSearchBar : UISearchBar
#end
FullWidthSearchBar.m:
#import "FullWidthSearchBar.h"
#implementation FullWidthSearchBar
- (void)setFrame:(CGRect)frame {
frame.size.width = self.superview.bounds.size.width;
[super setFrame:frame];
}
#end
And then I assigned that class to the search bar on my xib:
The problem is the right white block, so if we change the block color the same as the search bar background, it looks normal.
just
if (IOS7) {
self.tableview.backgroundColor = [UIColor colorWithPatternImage:self.searchBar.backgroundImage];
}

Programmatically scroll a UIWebView on iOS

How can I programmatically scroll a UIWebView in Objective-C (iOS)?
The only solution I can think of is to put it inside a UIScrollView and programmatically scroll that, however this presents the problem that the web view is often the wrong size and therefore the bottom of the page is cut off when scrolling. I have no idea how to programatically change the size of a web view to fit its content either... so far I have:
UIView *webDocView = webView.subviews.lastObject;
webView.frame = CGRectMake(webView.frame.origin.x, webView.frame.origin.y, webView.frame.size.width, webDocView.frame.size.height);
But for some reason this will not work.
Should I persue the solution of using a ScrollView... or is there a better way to do this?
UIWebView doesn't have any properties that specify its position on the document it is rendering. You likely need to do this through Javascript, if you want the animated feel of it take a look at this. http://www.learningjquery.com/2007/09/animated-scrolling-with-jquery-12
Apple says: "You should not embed UIWebView objects in UIScrollView object. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled." This probably has a lot to do with instances of both UIWebView and UIScrollView being scrollable and the interaction of two scrolling requests is too much.
Here is a simple solution that I've tested and it works:
Add the following in viewDidLoad to add a scrollView on top of our webView:
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.delegate = self;
[self.webView addSubview:self.scrollView];
When the page loads, we adjust the frame and contentSize of the scrollView
-(void) webViewDidFinishLoad:(UIWebView *)webView {
self.scrollView.frame = webView.bounds;
self.scrollView.contentSize = webView.scrollView.contentSize;
}
Now you can change offset of the web view.scrollView by setting self.webView.scrollView.contentOffset to whatever CGPoint that you want programatically.
Remember that, by doing this, touch events are no longer passed to the webiview. If you want the web view to still respond to the user dragging, then also do this:
#pragma mark UIScrollView Delegate
-(void) scrollViewDidScroll:(UIScrollView *)scrollView {
self.webView.scrollView.contentOffset = scrollView.contentOffset;
}

How to show UIWebView's scroll indicators

I have a UIWebView with some content and I need to make its scroll indicator visible for a short time (like [UIScrollView flashScrollIndicators]).
Any idea how to do this?
Starting iOS 5.0 onwards, one can now customize the scrolling behavior of UIWebView by accessing the 'scrollview' property to achieve the desired functionality:
[webView.scrollView flashScrollIndicators];
There's no real way of doing this via a published API, however I think that in this case it's OK to guess the UIScrollView subview, so long as you make sure your application doesn't crash if you can't find the UIScrollView:
UIView* scrollView = [webView.subviews objectAtIndex:0];
if ([scrollView isKindOfClass:[UIScrollView class]) {
[((UIScrollView*)scrollView) flashScrollIndicators];
} else {
// If Apple changes the view hierarchy you won't get
// a flash, but that doesn't matter too much
}
EDIT: The above will not work because the first subview of a UIWebView is a UIScroller, not a UIScrollView (my memory might be playing tricks on me). Perhaps try the following?
UIView* uiScroller = [webView.subviews objectAtIndex:0];
if ([uiScroller respondsToSelector:#selector(displayScrollerIndicators)]) {
[((UIScrollView*)uiScroller) performSelector:#selector(displayScrollerIndicators)];
} else {
// If Apple changes the view hierarchy you won't get
// a flash, but that doesn't matter too much
}

Resources