I'm creating a questionnaire app for iOS in Swift.
I only need one view for all questions. How do I make one generic view and make it look like I'm switching to the new view with swipe when only replacing some of the data on that view?
Alright, so I think I know what you're attempting to do. You could possibly do it like this. This is assuming you have a custom UIViewController subclass with all your textfields and labels on it; I've named this QuestionaireViewController.
let nextVC = QuestionaireViewController()
self.navigationController?.pushViewController(nextVC, animated: true)
Additionally, you'll want to set up unwind segues each time you create a new VC, so that if needed the Navigation Controller can segue back.
You can add an animation to your subviews (UILabels, etc.) on screen. You can add a separate animation to each swipe gesture and have the animation move in the direction of the swipe. I like this because you have some flexibility in what you animate and how you do so.
You'll need to setup swipe gesture recognizers and methods for each to handle the swipe and animate the layers.
If you want a "traditional feeling" swipe left / swipe right type of setup you'll need to setup a push animation with a subtype for each direction.
Related
I want to implement a bottom sheet as per the image.
The bottom will have a pan gesture to pull up and down
What I am confused about is :
Should I add a view to the existing view controller and add pan gesture to that view to pull up and down.
Should create a new window and add bottom sheet as a subview and push that window.
If, I choose the second option how would I update window on pan?
You should not create a new UIWindow. Generally an iOS app has just 1 window. The two best options I see are:
You can add a subview and gesture recognisers to implement pulling. That means that all the logic will probably be within the parent UIViewController. If there is not much logic, and the sheet does not have to be reusable, this is a good option.
If there is more logic inside the sheet, or the sheet has the be reusable, then it would be better to create a separate UIViewController for this. You can then present this using a custom animation and a presentation controller. Look into UIViewControllerAnimatedTransitioning and UIPresentationController for this.
I have used the second option before. A UIPresentationController take care of positioning the sheet view on the bottom of screen. It also dims the background, and attaches gesture recognisers to handle pulling and dismissing.
You can use this tutorial to get started with a UIPresentationController. You can also take the code from there and adapt it to your needs: https://www.raywenderlich.com/915-uipresentationcontroller-tutorial-getting-started
I have the following scenario and need help in resolving a tricky situation in the scenario
There is an Xcode project and am using EzSwipeController for swipe (pagination effect) between three View Controllers at the moment.
In my first ViewController (this viewController is fetched from my custom dynamic framework as part of my requirement) -
Code to fetch ViewController:
userProfile.createProfileUI(userSession!) { result in
switch result {
case let .Success(profileViewController):
myDetailsVC = profileViewController //myDetailsVc is passed to EZSwipControllerDataSource array
default:
break
}
}
The other two ViewControllers are within my project storyboard
The Problem -
In the first ViewController, there is a tableView with canEditRowAtIndexPath enabled for few cells (phone numbers).
So when I try to swipe the row, the EZSwipeController responds first and
hence, I am not able to edit the row.
Here is what is happening - http://recordit.co/SOJgdeYchP
Here is what should happen - http://recordit.co/EBPSbjH31q
How do I handle this problem? Is there a way where I can override the default swipe controller action when I try to edit the row?
Please help!
Attach the swipe gesture recognizer to a parent in the hierarchy.
If you're using a UITableViewController, replace it with a UIViewController with a UITableView inside it. Then just drag the gesture recognizer onto the view controller in Storyboard, and it'll attach to the UIViewController's Content View instead of the UITableView.
Though at the end of the day, this is inherently a flawed approach, since swiping to flip pages in an app is only ever viable if you don't have any elements on the pages that also have swipe gestures in them. If you do, even if you code a workaround to make the gesture recognizer for the element in the view controller (in this case, a table view cell) fire instead of the page flipping swipe gesture, that creates an inconsistent user experience.
My suggestion: don't use a table view for such a form altogether. On top of the aforementioned mechanical UX issue, from a user perception perspective, there's nothing indicating visually that this is a table view and not just a scroll view, so there's nothing indicating to the user that swipe actions (Delete) are available. Use a scroll view instead, and take a different approach to deleting (Delete buttons that are always visible, Delete buttons that are only visible after the user hits Edit somewhere, etc.).
I am building an app called Single Photo. It is part of the "Learn to Code" iBook from Apple. I have built the original app, but now would like to expand on it.
I have added a second View Controller to Main.storyboard, as well as a UIImageView. However, I am not sure how to connect the two View Controllers together. I know that I have to add a segue, but I want to use a swipe gesture (like a photo gallery). It was recommended that I use UIPanGestureRecognizer as an alternative to UISwipeGestureRecognizer.
My confusion is that I am not sure how to implement either UIGestureRecognizer. Do I have to implement it as the segue between the two View Controllers? That would make sense.
tl;dr: How do I implement UIGestureRecognizer as a segue between two View Controllers?
EDIT: When I make some changes, I get the errors seen in the screenshot.
{1}: https://i.stack.imgur.com/JpViy.png {1}
I'd be using the Swipe gesture for that; for me it seems the most natural one for changing views with touch?
Whilst I don't know Swift yet sadly, this is how i would do it;
Add a gesture recogniser object onto your view using Interface Builder. You'll find it in the list of objects to add (Label, TextField, etc).
Add an IBAction method in your ViewController.m and declare it in your .h also like:
- (IBAction)handleSwipe:(UISwipeGestureRecognizer *)recognizer
Connect the gesture recogniser in Interface Builder to the IBAction as a 'Sent Action'
Make a new Segue by Control-clicking on the first view controller and dragging the blue line to the second view. Give this segue a unique identifier and set the style of segue.
Handle the gesture in the IBAction based on direction of swipe and call the segue from here;
[self performSegueWithIdentifer:#"theSegue" sender:self];
See if that gets you there
It is possible to use a UIPanGestureRecognizer or UISwipeGestureRecognizer to trigger a segue between view controllers, but it's by no means automatic.
I suggest using a UIPageViewController. That is a type of parent view controller that manages a set of child view controllers and lets you page between them, like a photo gallery or iBooks.
There is a demo application built into Xcode called PhotoScroller that will give you the idea. Search on PhotoScroller in the Xcode help system to find it. As I recall it's written in Objective-C, but it will at least give you the idea of how a page view controller works.
tl;dr: How do I implement UIGestureRecognizer as a segue between two View Controllers?
tl;dr: You would write an interactive custom view controller transition animation.
Create a segue in storyboard from the initial view controller to your new one. Then click on it and set the identifier to something. Place the first three lines of code in your initial controller's viewDidLoad changing 'MyVC' to your controller's class name. Then put the method in and put the name of the segue you created.
let gesture = UISwipeGestureRecognizer(target: self, action: #selector(MyVC.performChange))
gesture.direction = .right
self.view.addGestureRecognizer(gesture)
func performChange() {
self.performSegue(withIdentifier: "MySegue", sender: nil)
}
I think that this is a great question that could be answered best if divided into two different sections.
First thing is to understand how to use UIGestureRecognizer so that you can do different things when a user either taps, long presses, rotates, pinches, etc, a certain view. And then, if you want to make a transition between ViewControllers look different than the usual and add a cool effect to it, you will need to learn more about UIViewControllerAnimatedTransitioning, here is a great tutorial for that: APPCODA's Introduction to Custom View Controller Transitions and Animations.
Let's do an example and try to answer your question:
Let's say you have two ViewControllers, call them MainVC and SecondaryVC and you want to transition from one to the other after the user performs a certain gesture. As you previously mentioned, you can create a segue between them and set an identifier for it (so that you can perform the segue in code later on), you do this by clicking on the segue from your storyboard and going to the Attributes Inspector. For this example let's set the identifier to ToSecondaryVC and do something when the user swipes to the right anywhere in the view.
First thing, you need to initialize a UISwipeGesture object, so let's set the gesture recognizer by adding in the following to ViewDidLoad() of the MainVC class:
let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(MainVC.handleSwipeGesture(_:)))
// Adding detection for a right swipe
swipeGesture.direction = .Right
view.addGestureRecognizer(swipeGesture)
After this you want to create a function in which you will perform the segue (or do anything else really) after the swipeGesture has happened. Like so,
func handleSwipeGesture(gesture: UISwipeGestureRecognizer) {
performSegueWithIdentifier("ToSecondaryVC", sender: self)
}
I think that should do it for understanding how to use UIGestureRecognizer, and you can work on the other supported gestures by doing something very similar to what we did in this example. Hopefully that helps you a little bit! Best of luck!
I implemented my own custom animation using the UIViewControllerAnimatedTransitioning protocol. However, this replaces the entire default push animation (including the navigation bar animation, and the new view sliding on top of the old one). I want to keep that stuff, and animate a simple UIView on top, which visualises how an item from the first view is being taken to the next.
Is there a way to accomplish this?
There is an "annimateAlongSide" function .... think it belongs to the TransitionCoordinator. Check that out.
So I'm working on a Google Maps-app, and I want a certain behavior. When tapping a marker I want the "Detail View", displayed below to popup. If swiping that detail view up I want it to cover the whole screen and make "MORE DETAIL" appear. If swiping down, it will close it.
I just can't figure out how to implement this behavior. Container View? Just a regular UIView wit gesture recognizer? Modal segue?
I'm not asking for code, just some words to get me on the right track.
Edit: For anyone else looking for this kind of behavior, every answer below is perfectly fine. I went with the container view, since the detail view is doing some network requests and UITableView work.
Can be done with Pan gesture and I would say by having Parent ViewController (Container) and Child ViewController instead UIView. Let me know if you would need more help :)
go with UIView and UIGestureRecognizer, it would be faster and simpler. Modal segue does not cover the whole page as you want, and container view is too much work to put on just a simple thing