Why UISearchBar and its scope buttons are shown in one line? - ipad

I have seen Apple's example "TableSearch" that when touched its scope buttons come below the search bar.
http://developer.apple.com/iphone/library/samplecode/TableSearch/Introduction/Intro.html
But when I make my own it looks good at first but when I touch it looks like ugly, scope buttons and search bar are shown in the same line like this:
http://cl.ly/BN9
What do I have to do make it like "TableSearch" example in the iPad?
I am doing everything in IB and tried to modify the search bar programatically from the controller:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.rowHeight = 88.0f;
self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);
self.searchDisplayController.searchResultsTableView.rowHeight = self.tableView.rowHeight;
//BELOW DID NOT WORK:
CGRect b = self.searchDisplayController.searchBar.bounds;
self.searchDisplayController.searchBar.bounds = CGRectMake(b.origin.x, b.origin.y, b.size.width, self.tableView.rowHeight);
b = self.searchDisplayController.searchBar.frame;
self.searchDisplayController.searchBar.frame = CGRectMake(b.origin.x, b.origin.y, b.size.width, self.tableView.rowHeight);
//BELOW WORKS PERFECT BUT IS A PRIVATE METHOD, HENCE I AM NOT SUPPOSED TO USE IT
//[self.searchDisplayController.searchBar setCombinesLandscapeBars:NO];
}
Thanks in advance.

I've encountered this bug as well, and I've both filed a report with Apple and requested technical assistance. I'll let you know how it goes. In the meantime I'll give you a brief bit of background on this bug.
On the iPhone, to preserve precious vertical screen real estate in Landscape mode, the UISearchDisplayController sets the UISearchBar to combine its search bar and search field in a single horizontal layout. This works pretty well because of the increased horizontal size of the screen (480 points in Landscape). Unfortunately, it works not so well on the iPad, where in Landscape mode the UI change really isn't necessary in the first place because you have plenty of vertical real estate. You also still only have 320 pixels of horizontal display space in the master view of the UISplitViewController, not the increased 480 of the iPhone. The result is an iSore.
Presumably the problem is that UISearchDisplayController is behaving badly in its willRotateToInterfaceOrientation:duration‎: method. Specifically, it's not bothering to check whether it's on an iPhone or not before it sets the combinesLandscapeBars property on its UISearchBar. The private API kludge in your code works because it fixes that oversight in the UISearchDisplayController. But of course Apple will rain down the fury of the ancients on you for using undocumented APIs, so you can't. Really we're at the mercy of Apple on this one.
If you're willing to give up the eye-candy and convenience of UISearchDisplayController, you can use a UISearchBar sans UISearchDisplayController and manage aspects of presentation yourself. Obviously this requires a lot more code and would be pointless if Apple's API engineers did their jobs, but it will at least resolve the display bug.
If you're Apple you can use your own undocumented APIs, which is why Mail.app doesn't have this problem.
UPDATE
The bug report I've filed with Apple is #8344719.

Using the following code, you will not get warning:
if ([self.searchDisplayController.searchBar respondsToSelector:#selector(setCombinesLandscapeBars:)])
{
objc_msgSend(self.searchDisplayController.searchBar, #selector(setCombinesLandscapeBars:), NO );
}

When you set the bounds and frame for the searchBar, like for the frame here:
blabla.searchBar.frame = CGRectMake(b.origin.x,
b.origin.y,
b.size.width,
self.tableView.rowHeight);
it seems like there is a problem with height. Scope buttons require some space under the search bar, so you should increase the height of both bounds and the frame.
If you show and hide scope buttons on some event you need to adjust the frame size each time.

I'm getting this issue on an iPad, but I can get it to work if I insert this in my implementation file:
#synthesize tableView;
I'm guessing there is something bad with the XIB being loaded, but I don't know why this would fix it.

Related

UIView not redrawing, but elements become misplaced

I'm having an issue with my app's layout which is a bit tricky to explain. When the app first starts, this is what I'm showing:
After the user taps "Create Profile", I animate those buttons and show a registration form instead:
Needless to say, the buttons are now not in their "natural" position. Note, however, that the text fields are - that's where I have placed them in the storyboard, but when the view first loads I hide them. The animations are working great, but then I needed to scroll my view up when the user gives focus to a text field and the keyboard hides the field. The details of how to trigger the bug are a bit hard to explain, so I managed to boil it down to what seems to be a redraw event, except that it isn't... Let me try and explain that.
First of all, here's what happens when the keyboard is about to show:
- (void)keyboardWillShow:(NSNotification*)notification
{
CGRect frame = self.view.frame;
frame.size.height -= 1;
self.view.frame = frame;
}
Notice that this is a test only, probably the minimal I found that would still trigger the bug. All it does is resize the view. I would expect the view to be exactly as it was, with one less pixel, right? Wrong. Here's what I get:
That is, all elements returned to their "natural" positions, completely ignoring their previous positions. My first guess was that it would seem that the window is redrawing, so I tried this:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
NSLog(#"View was drawn");
}
But this only triggers when the window is first drawn, not when this strange behaviour happens. To understand what I mean by "natural position", here's what I have in storyboard:
You can also see that I'm not using constraints and the underlying structure of my view:
The full code for the entire setup is quite extensive, so pretty much not practical at all to show. However, how I animate the subviews resumes to changing their frame as I did in keyboardWillShow, and setting their positions to whatever I need.
Any ideas?
So you're using storyboards and you have "Use AutoLayout" set to false for your entire storyboard?
In that case your app is using "struts and springs" style placement rules. You're going to have to debug those.
It's a bit hard to describe everything in a view controller in a post. It's easier to go over it in IB. Perhaps you can write a utility function that logs all the autoresizingMask values for the views in your view controller, and go over those, and perhaps post them here describing the autoresizingMask values for each view in your original post.

iOS 7 status bar overlaps with view - did they have to make it like this?

I know this has been asked before, but none of these solutions work, and that's the reason of my posting. Please do not close before considering my case.
My plist already has UIViewControllerBasedStatusBarAppearance = false.
I have already tried applying deltas, but to no result.
Changing the top level view frame in ViewWillAppear (like self.view.frame) did not succeed.
I thought of increasing the view height (storyboard attribute inspector), in combination with deltas, but my top level view X, Y are disabled in storyboard attribute inspector.
My main view doesn't have any children views because I load them into main view either dynamically or load them from XIBs which are again shared by more than view controllers. These XIBs provide layout for both Portrait and Landscape. I don't know what approach is ideal for this kind of configuration, but I would like it better if solution lies along these lines.
This approach worked partially, but gave me inconsistent results.
What makes the solution tricky is the fact that I have to support all 4 orientations - this is something I handle in code via didRotate and willRotate delegates for my other views, but failing to do it for statusbar.
Please help...
Could this link be of any help?
You might have to use the new setEdgesForExtendedLayout: method to get this working consistently?
Also, have a look at these official docs if you haven't already done so.
I ended up writing my own function to shift my all subviews (remember, not top level views whose frame is fixated by IB).
It didn't spoil my work but imagine if this was the case for a very big project with so many screens, the limitations would have made it a nightmare.

UISearchDisplayController's full-screen background intercepts touch events in iOS 7

I have a UITableview that doesn't take up the whole screen (screenshot). Everything worked fine in iOS 6. But in iOS 7, when the user searches, the search result table takes up the whole view (screenshot).
To fix this, I tried setting the frame manually as described in this answer. The appearance is now correct (screenshot), but now the "<" button in the top left doesn't receive tap events when the search results table is displayed.
It seems the searchResultsTableView is adding a full-screen background view that is intercepting touch events. To prove this, I added this code to didShowSearchResultsTableView:
controller.searchResultsTableView.superview.backgroundColor = [UIColor blueColor];`
This screenshot confirms my hypothesis.
How can I fix this to allow the "<" button to receive tap events?
I want to avoid modifying controller.searchResultsTableView.superview so that my change doesn't break in future versions of iOS.
And what change in iOS 7 caused this behavior to start happening?
I am still searching for a better solution, but currently my solution is in the viewControllers viewDidLayoutSubviews tell your view to move to front. The code would look something like this.
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.view bringSubviewToFront:self.navigationBar];
}

Phonegap 2.6 with KeyboardShrinksView and HideKeyboardFormAccessoryBar

i have a problem with one of the new phonegap features in 2.6 (ios), finally they included an option to shrink the webview to handle fixed elements. Unfortunately in combination with the HideKeyboardFormAccessoryBar option set to true, a strange white bar appears instead of the AccessoryView (take a look at the screenshot).
This is not happening when i set KeyboardShrinksView to false
has anyone experienced a similar problem with the new version? is this a bug or a feature? ;)
cheers
horst.
This is a bug. It's caused by the WebView not being resized properly after the keyboard is displayed. By default, PhoneGap resizes the height of the WebView by subtracting the view frame by the height of the keyboard. But, it doesn't take into account the fact that the form accessory bar is hidden in that calculation.
Here's a temporary solution to this while PhoneGap fixes this bug:
In CDVViewController.m (under Classes/Cleaver), go to line 140. It should be within the (void) keyboardWilLShowOrHide function. In the showEvent if statement, it calculates the new size of the WebView based on the height of the keyboard.
Change the contents of the if statement to:
if (showEvent) {
newFrame.size.height -= keyboardFrame.size.height;
if ([#"true" isEqualToString: self.settings[#"HideKeyboardFormAccessoryBar"]]) {
newFrame.size.height += 45;
}
}
I added an extra if statement that also checks for the HideKeyboardFormAccessoryBar configuration. If it's set, it'll increase the size of the WebView by an additional 45 pixels (the height of the form accessory bar).
While the keyboard is transitioning up, it seems the webview is already resized and the background is white, thus causing the white background to be shown. My HTML body background is black so it looks odd when the white background flashes. Does anyone know how to update the background of the UIView?
Video reproducing the issue in slow motion.
http://www.youtube.com/watch?v=iOjdxJuYp8c
Thanks!
Tom
Edit: I was able to change the background color by adding this code to MainViewConetroller.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.view.backgroundColor = [UIColor colorWithRed:51/255.0 green:51/255.0 blue:51/255.0 alpha:1];
}
It's definitely a bug. The phonegap dev team is going to fix this issue in the 2.7 release in a few weeks.
I have just checked my code and I have 2.6 and this fix is already there. But it is not working and I still see the grey bar with the same conditions. How that could be?
EDIT: It looks like that one of my teammates did this fix and solved the issue. The thing is that you still can see the grey space and it is removed very quickly.

iOS: Add an image to the Navigation bar

I'm currently working on an iOS app that is pretty much supposed look and work like an already existing android app.
As a part of that, I'd like to make the top navigation look the same, but since iOs devices do not provide a hardware or software integrated back button, I'd also like to keep the back button navigation that's common to iOs apps.
I've tried numerous attempts to achieve it, but I'll stick with the latest I'm working on since it looks the most promising. I've started to work on a custom UINavigationBar class that overrides the initWithCoder: and layoutSubviews: methods. The result is as follows:
As you can see, the back button now overlaps the application icon. What I'm looking for is a way to make the button and the text to scale into the space right of the application icon. I've tried to handle this in layoutSubviews: but the superclass logic appears to be rather complex, I was not able to reproduce it's functionality (in particular it seems to be working with some private variables I don't have access to).
I also tried manipulating self.frame before calling [super layoutSubviews] but apart from endless loops I was not able to achieve anything in that direction.
I'd be happy if anyone could point me into the right direction.
If I understand your problem correctly, I think you could do this by adding a custom titleView to the UINavigationItem, and have an image view (on the left side for the icon) and a label (for the title) as subviews. This would replace the default title.

Resources