ios SWRevealViewController reveal push segue animation - ios

I'm using SWRevealViewController(the updated version) to make a slide-out sidebar menu app,
connecting different rear view controllers (based on different sidebar cell tapped) by
SWRevealViewControllerSeguePushController class segue.
every time I tap a cell which is different from the current one
the sidebar becomes fully reveal then the new rear view controller gets pushed-in from
the right side.
It looks like the old rear vc first moves to the right (totally invisible) and
then the new one moves
to the left to show full screen.
That does not look smooth, I want it looks like I'm always using the same view controller when
different cell tapped and the rear vc would always be visible at least a part of it.
any way to modify the original animation setting?
thanks in advance!

finally found the setting method in
- (void)_dispatchPushFrontViewController:(UIViewController *)newFrontViewController animated:(BOOL)animated
{
FrontViewPosition preReplacementPosition = FrontViewPositionLeft;
if ( _frontViewPosition > FrontViewPositionLeft ) preReplacementPosition = FrontViewPositionRightMost;
//change FrontViewPositionRightMost to FrontViewPositionRight

Alternatively, you can simply edit the _rearViewRevealOverdraw property in SWRevealViewController.m to be 0.0f to prevent the rear controller from revealing any more of the rear view during the presentation animation.

Related

What is the standard method for implementing navigation menus in swift?

I'm trying to create navigation through the use of a menu in my app, but I'm not sure how it should be done. I currently have a system set out like this:
ContainerViewController
|
+---CenterNavigationController
|
+---ViewControllerA [i.e. the root view controller which will be changed]
|
+---MenuViewController [pushed to navigation stack on btn press]
and when a item in the menu is pressed to load another view controller, MenuViewController calls a delegate method in the ContainerViewController which replaces the NavigationController with a new one with a different root
let newVC = ViewControllerB()
CenterNavigationController = UINavigationController(rootViewController: newVC)
However this looks janky, both in the code and in the aesthetics of the app.
I'm not sure how to do this properly. I'm wanting the menu to be overlayed onto the current view, and have the ability to click 'back' in the menu to go back to what was showing on screen before the menuVC was loaded. How can I do this?
You do all correct. If navigation animation isn't good, then improve it. You can show menu animated from the left side and reload CenterNavigationController without animation. As for transparence, then just change the color of the main view of the menu view controller to semitransparent. The first subview that contains all menu items should be non-transparent and have lower width and sticked to the left side. That's it.
I think you should not push menu view controller into the navigation stack. Just load it right into the UINavigationView controller.
You can check loadViewController (line 251) method here https://gitlab.com/seriyvolk83/SwiftEx/blob/master/Source/UIExtensions.swift
It loads view controller into another view controller in a given bounds. To remove it later (close menu) you can use remove() (see line 321)
Hamburger menu is antipattern on iOS, I suggest using UITabBarController. If someone is holding a gun to your head and forcing you to put a hamburger menu in your app then use something like this: https://github.com/jonkykong/SideMenu

How do I make a now playing bar like in media player apps in iOS with XCode?

I am making a media player app. I have UITableViewControllers that are embedded in Navigation Controller. I would like to somehow make a view that would overlay potentially multiple (2?) of these tableviewcontrollers (one that shows the user's playlists, and the next would show the tracks in the playlist), but only at the bottom, like a now playing bar in (e.g.) Spotify's iOS app (as in the left bottom side of this
or as in this
I have tried to drag a Container View into my Navigation controller (in which my TableViewCell is embedded), but it won't let me drop it there.
It looks like I can drag the Container View into my TableView, but then how would it remain there when i navigate between tableviews?
Trying to follow #Rintaro's suggestion, but I'm a little new to XCode. How did you do this? So I made a single view application, i added a container view to the first VC, it's imm drawing it somewhere else in the storyboard, but i can't figure out how to tell that view that it's a navigation controller. also, as soon as i add a second container to the first VC and tried to size it, the first container disappears! It is still listed in the hierarchy on the left, and still has an arrow pointing out of it, but the view controller that was added and was being pointed to is also invisible?!
UPDATE: This works very well, but it has a problem with orientation changes. how can i make this work in both orientations? (I hypothesize that it currently positions the "nowplaying view" off screen when the orientation changes).
Basically, view hierarchy like that is constructed like this:
Using two "Container View" in initial view controller, one for Navigation Controller, one for "Now Playing Bar" view controller.
ADDED:
"Main Container View Controller" would be your own UIViewController subclass. It will have responsibility to show/hide "Now Playing Bar".
Workaround for Interface Builder strange behaviors.
You can set Auto Layout constraints like following. Maybe you might want to select the view from the left menu.
Note that, you should uncheck Constrain to margins check box.
Container View for Navigation Controller:
Container View for Now Playing Bar Controller:
And then, Update Frames from the menu:
If you are manually placing any buttons with absolute coordinates, make sure that you update the coordinates of them when the rotation is changed.
Obviously you need to create a custom UIView class, where you will show this menu. And when you will create it, add it to your view just like here:
float y = ROOTVC.view.frame.size.height - 49;
[self setFrame:CGRectMake(0, y, 320, 49)];
[ROOTVC.view addSubview:self];
[ROOTVC.view bringSubviewToFront:self];
I would simply add a nowPlayingView to the appDelegate.window and adjust either:
The window.rootController.view frame to avoid overlapping the nowPlayingView.
If window.rootController.view is a UIScrollView, adjust its contentInset.bottom to avoid overlapping the nowPlayingView. You can also use transparency/translucency with this solution.
Add a dummy toolbar to the controller that will get covered by the nowPlayingView.
If your window.rootController is a UINavigationController, then you have to probably do the above fore each controller you push. The nowPlayingView will stay unchanged on top.

When animating a viewController on top, the one in the back disappears.

I have a viewController which displays a map with annotations. When I click on a bar button, another viewController is supposed to animate on top of that. This works, BUT, when the animation completes, the viewController in the back disappears. It reappears again when the animated viewController closes again.
Here is a video of what happens - hopefully that will make things more clear:
Let me know if I should include the code as well.
When you present a view controller it is expected to take the full screen. As such, the view controllers 'below' it have their views removed from the stack to save resources which are expected to not be required.
You can change your presented view controller to do something like:
Either, don't be presented, just add a subview and animate it in.
Or, pass an image of the original view to the presented view, this becomes the background and that presented view animates a subview in over the image background.

Swap/ Transitioning between views iOS programming

I am a newbie to IOS programming and currently i have a tab bar application with two tabs. I have two questions.
The first tab shows a map, imagine it with some pushpins. There is a button on the navigation bar and when this is clicked i want the map view to to move out and a list view to come in. You can see the UI from the image. The button is called list.
Now when i click list I want this view to go away and the list view to come in. So here are my questions ?
1) How do i do this ? I tried the navigation model but i don't want that because I do not want a back button. I tried to make two different views and just dragged the button to that view but the app crashes. I just want the list button on the nab bar and when clicked the view changes to the list view and the button text changes to map. So now if I click the button again it should go back to the map view and the button changes to list.
2) How do i achieve the animations for this ? Ive seen some app where the page flips around and I've seen some options like reducing the opacity etc but I want to achieve the flip animation.
Thank You for any help I get. I really appreciate it.
Interface Builder can do most of this. Hold down the control key and drag from your map View Controller's UIBarButtonItem titled "List" to your list View Controller, then choose the Action Segue "modal". An arrow appears representing the segue; click on it and use the Attributes Inspector to change the Transition to "Flip Horizontal". Here's a video
Or, you could do this programmatically with presentViewController:animated:completion.
Now to get back to the map from the list, I believe that must be done programatically. Create a method that calls dismissViewControllerAnimated:completion: and make your list View Controller's UIBarButtonItem titled "Map" trigger it.
After reading your comments, I am wondering... if the structure of your app is logically a tabbed app structure (as indeed you refer to it as a 'tab bar application'), shouldn't you consider using the UITabViewController instead of a NavigationController? That is what it is designed to do, after all.
If you do use a TabViewController you should reconsider your desire for flip animation, as that doesn't really make UI-sense for tabs. If you can dispense with the flip animation, TabViewController could be a good way to go and you should at least experiment with that before dismissing the idea. It is also designed to grow... you can incorporate any number of tabs in a tab bar. Check out the apple docs (with pictures!)
You will notice that tabs are at the foot of the screen, whereas your 'tab' navController buttons are in a navbar at the top of the screen. This also helps as your app grows, as it is straightforward - from a UI design point of view and programmatically - to incorporate navControllers as navigation tools within individual tabs. For example, if your map/list flip routine does indeed make sense for this part of you app, you can keep this as a single tab (in it's own navigationController) and add other tabs for other parts of the app...
update
From your comment, you are saying that you are interested in the navController-inside-tabBarController setup. In this case here are some ways to get flip transitions AND no back button..
(1) modal presentation
The easiest way to get what you want is to set up one of your viewControllers (say the map view) to present the other one (the list view) modally.
If in the storyboard:
embed your mapViewController in a navController with a navbar button for navigation to the listView as in your picture
add your listViewController to the storyboard and embed it in it's own navContoller (not the mapViewController's navController). Drag a barButtonItem to this navController and wire it up to an IBAction in listViewController
CTRL-drag from mapViewController's 'list' button to the listViewController to create a segue. Select the segue and in the attributes inspector set the segue type to 'modal', with transition 'flips horizontal' and 'animated' checked. Give it a name in case you want to refer to it in code.
in the listViewController's IBAction add this:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
That should achieve your result. You can use the completion block to send information back from the list view to the map view, and/or set the map view as the listView's delegate.
If you are not using the storyboard check this apple guide
Presenting View Controllers from Other View Controllers
especially "Presenting a View Controller and Choosing a Transition Style".
There is one catch with this approach - when the presented view flips onto the screen, the entire previous view, including the tab bar, is flipped out of the way. The idea is that this is a modal view which the user is required to dismiss before doing anything else in the app.
(2) push/pop in a single navController If this does not suit your intent, you can navigate using a single NavigationController with push and popping of views, and you can hide the back button ... but you really would need to keep the back button functionality as you do want to go back to the mapView, not on to a new map view.
To hide the back button try:
self.navigationItem.hidesBackButton = YES
in the uppermost viewControllers' viewDidLoad
Then you can add a barButtonItem in the xib/storyboard, with this kind of IBAction:
[self popViewControllerAnimated:NO]
or
[self popToRootViewControllerAnimated:NO]
You would have to construct the flip animation in code as it is not supported as a built-in with UINavigationController (best left as an exercise for the reader!)
(3) swapping views in a single viewController As ghettopia has suggested, you could use a single viewController inside a navController (or with a manually place navBar) and swap two views around using the UIView class methods
transitionFromView:toView:duration:options:animations:completion
transitionWithView:duration:options:animations:completion.
This could be a good simplifying solution as your list and map are essentially two views of the same data model.

iPad SplitViewController leftViewController is UITableViewController and back button repaints the screen from top to bottom

I have a SplitViewController (iPad) and its leftViewController is a class inherited from UITableViewController; on the other hand, the rightViewController is a map. In landscape mode, when the leftViewController is shown (UITableViewController), then the user can tap on one item and it is pushed onto the left part of the SplitViewController another list of items (UITableViewController). As a result, it appears the title and the back button with the title of the previous list (this is the back button offered by the UITableViewController, so I have not programmed a new button to implement that behavior). During all that process the map does not change (and this is the desired behavior).
The problem is related to the back button and in landscape mode; that is, when it is pressed then the previous list is shown (and this is the desired behavior), however it seems like all the screen (the menu bar at the top and also the sliptviewcontroller -with left and rigth viewcontrollers) is refreshed (repainted) from top to bottom during less than one second.
I am quite sure that is not a problem related to animation because I have commented, in the code, all the sentences related to animation, and, I also have set to false all the function arguments like "animate:".
It is a esthetic problem, but I would like to correct it.
Thanks in advance,
Solution: Implement in the left view controller the following method.
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return YES;
}

Resources