I need to detect shake gesture in iOS. I have done the usual stuff and it works perfectly fine. The thing is I have multiple view controllers in UITabBarController and I wish each of them to detect the shake gesture.
When shaking in any of the view controller , I get switched to a particular tab. The problem is if I shake in one view controller and try to shake in other controller the gesture is not detected unless some action is performed in that controller.
I know I need to set becomeFirstResponder but I need to know how can this property be set to the current tab of the UITabBarController so that the shake gesture is recognised by all tabs.
Write the code for detection (usually via a notification observer for shake) in a base view controller and and all the controller will subclass from this. Now you can write the code to move the particular tab in this base controller.
Problem solved.
Related
I am working on trying to implement a presentation controller that essentially mimics the behavior of the UISheetPresentationController. I am doing this because I want to add a third detent and also I want this to work for iOS 14, so I cannot use the existing UISheetPresentationController.
I have it where I can present a view controller and it will stop at one location (say 50% of the screen height). And then I have a pan gesture that, when active, starts the interactive dismissal of the view controller. If the view controller is pulled down so far when the gesture ends, the view is dismissed, otherwise the dismissal is cancelled and the view returns to the 50% height.
That is all working fine. But then how do I add multiple stops, or detents? The pan gesture starts an interactive dismissal, but that dismissal does not support multiple different places where the view controller could end up.
Does anyone know how Apple implements their "detents" in the UISheetPresentationController? Or does anyone have any suggestions on how this might be implemented?
You can also add this to your .sheet{}
.presentationDetents([.medium, .large, .fraction(0.1)])
or
.presentationDetents([.medium, .large, .height(300)])
I want to implement a hold-to-preview button that brings up a view containing an AVPlayerLayer, which plays as long as the touch doesn't end. The video player is contained in a different view controller, and I am hoping to be able to use presentViewController:animated: when presenting it, and not just add it as a subview and child view controller.
My question is about how to deal with the touch event. I see two possible ways:
I try to transfer the active touch down event to the presented view controller (not sure if even possible), or
I try to keep the original view controller's gesture recognizer active, and then let the video view controller know when it's time to dismiss itself. I'm hoping this could be achieved either by just setting the presented view controller's userInteractionEnabled to false, or perhaps using a UIViewControllerTransitioningDelegate to present it, and then just skip calling completeTransition: or something similar (I believe touches don't register on the new view until you complete the animation, but please correct me if I'm wrong).
My question is about how to deal with the touch event.
Touches are always associated with the view that they start in. You can't transfer the touch to a different view. I've never tried it, but the options I think you should explore first are:
Use view controller containment. Make your preview view controller a child view controller of the one where the touch originates. That way the parent and its view hierarchy never go away, although they could be covered up.
Attach the gesture recognizer to the window. A window is a view, and should be able to have gesture recognizers. You could make the gesture recognizer's target the app delegate or some other object that will always be around, and have the delegate post a notification when the recognizer is triggered. Again, I haven't tried this, but it seems like it should work.
At some point in my app, a user can move a UIView after a long press on that view. This works fine.
When the view passes over a specific region, the app has to switch to another UIViewController. The moving view is attached to this new controller. So far so good.
The problem is that now the moving view is not moving anymore (i.e. it doesn't follow the finger of the user) :-(
Seems this issue is related to the UILongPressGestureRecognizer that was fired in a ViewController that is not active anymore.
Any idea how I could handle that ?
ofcourse there might be a requirment to use a UIPanGesturerechognizer,
why dont you enable or add it to the parent view on long press?
You should implement touchesBegan, touchesEnded etc to handle moving of your view. This way, when you're switching the controller, you can still move that view.
Anyway, this idea seems to be weird at least and I'd reconsider app architecture on your place.
I want to handle transitions between two instances of the same view controller class, using pan gestures.
I've read almost every transitions can be handled by segues, but is it the same when using pan gestures?
Segues don't seem to be a good fit for this kind of transitions.
For the moment, I have a master view controller which instantiates to sub view controllers. The gesture related code resides in the master view controller.
It works well, but I believe there has to be a solution where all the controller management stuff is done in the storyboard.
What is the best place in my code to handle this kind of transitions?
It sounds to me like what you want is a UIPageViewController set up to scroll instead of page curl (That's a settable property) A page view controller would do all the work for you.
There is a sample app in the Xcode docs called PhotoScroller that shows how to set this up. It does lots of other stuff too, (pinch to zoom and image tiling) but you can ignore that.
If you can't get a UIPageViewController to give you the transition you want then you might need to build your own custom parent view controller class. Embedding a single child using a container VC and an embed segue is trivial. I haven't tried to embed multiple children in the same container yet. using embed segues yet. I've done transitions between child VCs using the "manual" parent/child VC calls that were added in iOS 5
I've found a really great article on the way to implement custom transitions with iOS 7, whether they're interactive or not: http://www.captechconsulting.com/blog/tyler-tillage/ios-7-tutorial-series-custom-navigation-transitions-more
It comes with a very detailed demo.
Animations should be classes implementing the UIViewControllerAnimatedTransitioning or UIViewControllerInteractiveTransitioning protocols.
The code using the gesture recognizer can reside in those classes.
The animation can then be returned in the following methods of your navigation controller delegate:
navigationController:animationControllerForOperation:fromViewController:toViewController:
navigationController:interactionControllerForAnimationController:
This way I can plug the animation to whatever controller I want to.
I hope it could help someone.
After creating an Xcode project from the iPad "master/detail" storyboard template, I cannot seem to find the UIGestureRecognizer instance that's responsible for the Mail-style swipe to show the master view in portrait mode.
I need to do this in order to make it ignore touches on certain UI elements, but it doesn't seem to be handled by any of the 4 gesture recognizers returned by the gestureRecognizers method of the master view. When I set a delegate on them, its functions only get called when interacting with the master view itself, and not with a swipe on, e.g. the detail area. The detail view returns an empty array from gestureRecognizers.
A project-wide search for "gesture" reveals nothing, and I see no gesture recognizers in the storyboard. Where is this handler created and managed in the default Xcode "master/detail" template, and how can I access it in order to set a delegate?
I expect it is on the split view controller itself rather than the master or detail view controllers. You can turn it on or off using the presentsWithGesture property (5.1 and later only).