I'm trying to replicate the functionality in the Facebook for iOS app where the UISearchBar in the navigation bar is 'shared' between view controllers. For example, tapping on the search bar on the home News Feed view appears to push a new view controller and 'transfer' the search bar to the new view controller. The search bar size is resized and animated alongside view controller transitions (including when using the 'interactive pop' transition, as depicted in the screenshot below). This behaviour is exhibited in various ways throughout the app. Is there a standard way to achieve this behaviour in UIKit, or are Facebook somehow applying custom transitions/animations to the navigation bar and search bar?
Having had a quick play with it, first I'd say that the main screen is split into several parts. Its hard to know what those objects are, but at a guess, I'd say theyve got a UIViewController that just contains the search bar and other 'navigation' elements. Below that theres another UIViewController that contains the newsfeed, and that is a flexible space in that various other things (custom) can happen in there. Both of these are likely set as 'ChildViewControllers' within a parent ViewController. This allows you to for eg, get several UIViewControllers onto the same UIViewController space in interface builder.
Their search bar itself is highly customized and might not even be based on a UISearchBar. Theyve probably just created a fully custom UIView with a UITextView to type into and lots of other custom animation going on. Still, you can achieve much of what they are doing by using a UISearchBar.
So going this way, the search bar remains the same search bar, while content changes below. If you for eg do a search, then the search results appear below, but that same UISearchBar stays visible above.
An alternative approach that I might do if not using ChildViewControllers (I've gone off that method), would be to simply use UIView based objects within a single UIViewController. So a UISearchBar at the top, probably within a parent UIView. And another UIView below to contain the feed and everything else. Again, just search using the single UISearchBar and change the contents of the UIView below as required.
Related
I'm having a strange issue with my UISearchDisplayController. When the search display activates the frame of the background fading view and the tableview are incorrectly overlapping the UISearchBar. It appears the results tableview is not taking the offset for the UIStatusBar into account.
The ViewController is using auto layout. Since the application does not use any opaque bars, the view controller does not extend any of its edges.
Extend edges under top bars = NO,
under bottom bars = NO, and
under opaque bars = NO.
Here is the initial layout:
This is what happens when the search display activates:
And finally, here is the resulting output of the search:
I solved my own problem. A hard lesson learned. After a few hours of thinking "It really shouldn't be this hard." I realized that my instance of UISearchDisplayController was not properly linked to the API provided property of its parent view controller. If you're using UIStoryBoards / Interface Builder be sure to click on your ViewController and view its provided outlets in the inspector. If you see this:
Then something is wrong and you're going to run into issues just as I had. What you'll want to do is to click in that empty circle and drag to your instance of the Search Display Controller. If things are linked up right you should see this:
I foolishly didn't pay attention to this and created my own IBOutlet to reference the Search Display controller. That caused IB to null out the API provided outlet as a UIViewController can only support one Search Display Controller. If you need me to clarify anything let me know.
I would like to implement IOS Weather APP like transition, ListView, tap on list item it expands to detail view, or pinch to list also expands to detail view.
Slide left and right transitions. Please let me know how can I implement that.
Thanks in Advance.
Here is some post on a blog I found that explains Apple new Transitioning API on iOS 7, go through it, read it.
In short lines, here are the steps
1 - Set a transition delegate on a controller
There are 3 types of transitions you might want to customise :
UINavigationController push & pop transitions
UItabBarController tab changed transitions
any modal presentation with presentViewController:animated
Each of these 3 cases offers its own 'transition delegate' protocol :
UINavigationControllerDelegate
UITabBarControllerDelegate
UIViewControllerTransitioningDelegate
When, from somewhere in your code, you use the methods for presentation :
pushViewController:animated: or popViewControllerAnimated:
setViewControllers:animated:
presentViewController:animated
Then, these delegates asks for what I call an 'animator' if an animation is required.
What I'm calling an 'animator' is an object conforming to protocol <UIViewControllerAnimatedTransitioning> (or <UIViewControllerInteractiveTransitioning> in case of interactive transition, like gesture driven interactions). This decouples the animation from your UIViewControllers (which might already have plenty of code inside)
2 - Write the 'animator'
This is the object responsible for animating transition. This can be a viewController, or a completely new NSObject.
In case of a UINavigationController, you could define different animators for push and pop operation.
3 - add the properties you need for your animation into your animator, and code the animation
The 'animator' might implement different protocols, depending on which transition you're trying to customise.
In case of non interactive animations, these are the methods :
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext : define the duration of animation
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext this is where the beef goes. See the example code in link above,
- (void)animationEnded:(BOOL)transitionCompleted for any clean-up after your animation was played.
In your case, you might want to add some 'origin' and 'target' UIView properties in your animator class (as weak properties of course !)
Then, when you detect 'which' view was tapped by user. (in your UITableVIewDelegate or UICollectionViewDelegate didSelect methods), you tell your animator so that it can animate with THAT specific frame, then call the 'push', 'pop' or 'presentViewController' , depending on your navigation logic.
You can definitely pull this off with the transitioning api.
Check out this project, I think it will help:
https://github.com/chefnobody/Colors
I was able to do it using this example from Ash Furrow # Teehan + Lax: http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions/ with some modifications:
To augment this example to get the pinch/pull table view cell separation animation you would need to identify the table view cell that was selected (or "selected" relative to the pinch gesture"), then in -animateTransition: you animate the actual table view cells above and below the selected cell out of view, revealing your details view controller. Remember, also to animate back to the table view from the details you need to (during the "pop") know which cell would be selected (scrolling it back into view if it's not already in view) then animate the cells surrounding it from off screen, back into view.
As for the swipe interaction between the different cities you would implement a different InteractionController that handles the transitions there. Again, you can probably follow Furrow's example and figure out how to pull it off.
I am a newbie in all this as will be apparent really soon.
I am using the iOS: Application: Tabbed application template. I have placed a UIImageView in the first view and two standard rounded buttons. One button is attached to an action in the FirstView Controller which places a picture into the UIImageView. The second button is attached to an action in the AppDelegate which calls a method in the FirstViewController which in turn places a second picture into the UIImageView.
The AppDelegate method does not replace the picture. It doesn't crash… it just does not seem to do anything.
How can I manipulate the view in the First and Second View Controller from the AppDelegate?
#dasdom
Well that's one issue explained. I've been reading the theory of MVC and trying to put it into practice now. Short version is I am trying to write a Battleship app for practice. Was planning on using the first screen to setup the game pieces, prefs, etc.. and use the second screen for actual game play.
I've created another class to use as my "brain center" but I ran into the same issue of not being able to manipulate anything on the screen for the first or second views. (That's why I tried the appDelegate).
That's my life story right now… can you throw some pointers my way on how to proceed and how to solve my one of many problems?
First you shouldn't do that. The AppDelegate should only be responsible for bringing the first view onto the screen.
Second you should have a look into the Model-View-Controller design pattern. Search for it in your preferred search machine.
But I you really still want to do that you should have a look into delegation and/or notifications. For example you could send the First View Controller a notification from the AppDelegate to change the image.
I have a series of UIViewControllers throughout my application. Most of them have the navigation bar but some of them hide it.
The problem is that sometimes as you transition between a view with or without navbars to another view with or without navbars there is a black box that replaces the navbar during the transition. This problem was discussed here: Hiding a UINavigationController's UIToolbar during viewWillDisappear:
This solution is fine and it does get rid of the black box, but I really don't want what was described as a "Cheshire Cat" disappearance. I've tried myriad solutions using prepareForSegue, ViewWillAppear, viewWillDisappear, etc. The best I can do is change the scenario in which the black bar shows up.
By this I mean, there are four combinations of view transitions between the two navigation bar states (hidden vs. not-hidden):
Hidden - Hidden
Hidden - Not Hidden
Not Hidden - Hidden
Not Hidden - Not Hidden
No matter what solution I've tried, at least one of those combinations results in my black box rearing its ugly head. The problem I have is that I've been unable to find anywhere that I can get a reference to the source view controller and the destination view controller when popping a view off of the navigation controller's view stack.
If I could get both references in the same event, I could simply determine what the combination is and handle the behavior appropriately like I would in prepare for segue.
Now, I know that "it's not possible" is a reasonable (and even a probable) answer, but I won't accept that as a solution alone. If it is indeed not possible, I'd like thoughts on a reasonable alternative. For example, I could handle all view controller popping manually (including the default back button) and thus could get the "upcoming controller" from the navigation controller's stack.
I would just prefer a solution using built in APIs or at least a solution where my controllers didn't have to be aware of their own navigation bar states.
Thanks a lot,
Patrick
I think UINavigationControllerDelegate is what you're after. It declares two methods:
-navigationController:willShowViewController:animated:
-navigationController:didShowViewController:animated:
All you need to do is set yourself as the delegate of the parent navigation controller and implement these methods to be notified of incoming view controllers.
Having said that, I've never needed to resort to this for hiding and showing navigation bars. Strictly speaking, view controllers where the navigation bar will always be visible never touch the navigation bar's visibility. When I'm moving into a view controller where it needs to hide, that view controller is responsible for hiding and setting it back to its prior state before disappearing. Following these standards has proven reliable for me.
I have one background I want constant to all views; it shouldn't animate out and back to itself. I have another background I want common to another handful of views that layers on top of that one. I could do this cleanly enough by:
a) just having one viewcontroller and managing all the transitions of layered objects within that
b) using separate viewcontollers and managing them programatically
But I don't grok how I can do this with a storyboard proper-like. Do I need to make a custom segue? Is there a certain type of segue it should be, if it's custom (or otherwise)? Is there a best viewcontroller that I do it all inside? (note: there's no "levels" of navigation, tab bar, navbar, etc... though if that's the way to go, with the elements hidden, and that's the "best" way to do it, I suppose that that might be me c)? )
Hope I've explained this well enough. :) I do grok layer transparency, etc, as far as views go....
Thanks!
ETA: After more research, I thought I understood c as the correct answer, (with a nod to set "default" UIViewController background image? ) ~
navigation controller with main background
navigation controller with secondary background elements
subpage 1
subpage 2
subpage 3
other controller
But I'm still hitting a wall. Not grokking the storyboard (IB) way to even add a background to a navigation controller. The number of custom classes I've made and tossed out, now....
See if this is what you need. It is not in storyboard, but should do well enough.
navViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.jpg"]];
This is what I have done (but only with 1 level of nav controller). You can put this code in AppDelegate.m, or maybe subclass UINavigationViewController and change the view's backgroundColor there (and attach it within StoryBoard)
I guess the problem is StoryBoard still has some limitations. And UINavigationViewController is not an interface element, it is a View Controller. It is simply shown as a simulated element in StoryBoard.)