Cocoa-Touch - Chain animations together - objective-c

This probably sounds harder than it is. I'm actually trying to chain some animations together to make it look smooth. What I'm doing is some basic animation of a UIPickerView that slides from the bottom of the screen and when it is dismissed it slides back to the bottom of the screen. I handle this functionality in two methods - (void)showPicker and - (void)hidePicker
Directly after the picker has been hidden I want to show the keyboard, but I don't want to show the keyboard before the picker has been hidden.
Also I want to this the other way around, directly after the keyboard has been hidden I want to show the UIPickerView. I know I can observe notifications of UIKeyboardDidShowNotification and UIKeyboardDidHideNotification
So what would be the best way to deal with this so that these animations are chained together in a smooth way?

For the path picker->keyboard try
[UIView animateWithDuration:0.3
animations:^{
[self hidePicker];
}
completion:^(BOOL finished){
[yourInputView becomeFirstResponder];
}];
The other way around listen to UIKeyboardDidHideNotification and invoke showPicker in the callback.

Do you show your picker as a way to input some info in a field or something?
If so, you better use the inputView property of UITextField so that it behaves quite like a normal TextField but uses your UIPickerView instead of the standard keyboard.
That's the standard way to do this (showing a picker in place of the keyboard) and you won't have to bother about chaining animations.

Related

How can I flip between two UIView?

I'm using two UITextView objects. Each UITextView represents the side of a single card in a flash card application. Just like when using regular flash cards, I want the user to have the ability to flip a card. I am asking how to flip between two UIView objects because UITextView are UIView subclasses so the same idea should work.
The animation I am looking for looks like this.
The only problem with the above example is that it utilizes two UIViewController objects and UITextView is not a subclass of UIViewController so the same principle does not apply.
Any ideas on how to do the flip animation?
You can use the UIView class method +transitionFromView:toView:duration:options:completion: to accomplish this. Both your text views need to be descendants of a common superview. Use the option UIViewAnimationOptionTransitionFlipFromLeft (or ...FromRight) to get a horizontal flip.
Looks like your question has been answered already here, just tweak the transform to make it a horizontal instead of vertical flip:
- (void)horizontalFlip {
[UIView animateWithDuration:someDuration animations:^{
yourView.layer.transform = CATransform3DMakeRotation(M_PI, 0.0, 1.0, 0.0);
} completion:^(BOOL finished){
// code to be executed when flip is completed
}];
}
As explained in that linked question, you can further modify this to do half the flip by using M_PI_2, then in the completion block of the first animation swap out the UITextViews and start a new animation to finish the flip.
Don't forget to #import math.h and #import <QuartzCore/Quartz.h> at the top of your file!
you can first hide the one UITextView and Show the another UITextView. To flip it, you can hide the displayed UITextView and show the hidden UITextView. You can also use animations explained here for it to create a flip effect.

UIScrollView on UIWebView and UITapGestureRecognizer conflicts

I have a UITapGestureRecognizer on a UIViewController, which has a UIScrollView and UIWebView inside. It recognizes the tap gesture only after I scroll the UIWebView. How could I prevent this ?. Basically I want the tap gesture to be detected, when I am not scrolling the web view. I looked around and the closest I found is this:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
return YES;
}
but not sure how can I use this to disable the tap while scrolling. Any idea?
Another thing I want to do is to disable the UITapGestureRecognizer, when a link on the UIWebView is clicked (shouldStartLoadWebRequest is called). I checked that the tap gesture recognizer is called, before the shouldStartLoadWebRequest is called. Basically when clicking on a link on a UIWebView, it shouldn't trigger the action invoked by the UITapGestureRecongnizer. Any idea on how to do this?
So Apple's documentation strongly recommends you don't nest a UIWebView inside a scroll view:
Important: You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.
It is possible on iOS 5 and above to get direct access to the underlying scroll view on a UIWebView (using the scrollView) property - playing around with this might help you.

UIButton firing selector inconsistantly

I have a UIButton linked up in IB correctly(I believe). The button fires inconsistently, every time I reload the view to show updated info, the button works sometimes and sometimes does not.It gives no errors. I can't find a pattern to when it works and when it doesn't, the same code is run every time I open the view and it still works when it wants. Besides linking it in IB I have also tried to addTarget in ViewDidLoad and remove the IB connection but it still has the same inconsistency,
[_buttonScreen addTarget:self action:#selector(buttonScreenClicked) forControlEvents:UIControlEventTouchUpInside];
If I add NSLog(#"Clicked"); to buttonScreenClicked I see that the method doesn't always get called, what would cause it to do this, I have made sure that I set:
[_buttonScreen setAlpha:0.1];
[_buttonScreen setHidden:NO];
[_buttonScreen setUserInteractionEnabled:YES];
I have no Image, text, or color in the button, but it still works sometimes.
I'm using AFKPageFlipper on the same view but it still had the same problem before I added AFKPageFlipper, so I don't think its that.
If anyone could point me in any direction to start trouble shooting this problem I would appreciate.
Thanks
I just had the same problem and worked it out. The 5 seconds is the clue.
Somewhere you have a gesture recognizer covering the same space as your button. More specifically you have a gesture recognizer that is eating your Taps but not your LongPresses. If you just tap the button the gesture recognizer runs off with your event; Hold your finger down long enough and the gesture recognizer no longer considers it a tap and the event is passed through to your button.
Instrument your Tap gesture recognizer handlers and the problem should pop out at you.
Make sure you don't have any other UIView descendants overlaying the button (like a transparent UIScrollView) as these will intercept the touch events first.
Also make sure that the containing view (the view with the button in) is correctly sized, by default you can place a view outside the bounds of another view and the clipsToBounds is set to false so you will see it but not be able to interact with it.
Things to try:
Do you have any other actions on the button?
Do you have any other UIViews which could possibly be accepting the key presses (above or below, or un-shown)
Also, please check that you have only one UIViewController instance for this screen. Other issues may arrise because of that.
What happens if you dont set the alpha level?
Do you release the object properly in the dealloc only ?
Hope this helps

View Transitioning

I'm new to Objective-C programming and I'm having a little trouble understanding how I transition between two views.
Basically, I have my main view (the view that loads up when the application opens) and I want to transition to a new view on pressing a button. The user will not need to go back to the main view after pressing the button -- it's basically a title screen.
Could someone please briefly explain the steps I would need to take to make this happen?
Thanks a lot.
You could make use of UIView's class method transitionFromView:toView:duration:options:completion:.
A call to switch from viewA to viewB could look like this:
[UIView transitionFromView:viewA
toView:viewB
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:^(BOOL finished){
[viewA release];
}];
As you mentioned the user won't get back to the mainView I added something to the completion parameter to get rid of viewA afterwards.
You can find the animation options in the constants of the UIView class documentation.
If it's going to be a modal view, you can push on a new modal view controller which will then later be popped off when work is complete. These are usually intended for small amounts of work
[container presentModalViewController:yourNavigationViewController animated:YES];
Otherwise you can modify the UIView stack using the two UIView transition class methods:
+ transitionWithView:duration:options:animations:completion:
+ transitionFromView:toView:duration:options:completion:
For more info on these check out Apple's UIView class docs.
If you don't just want to copy & paste the code you should follow Apple's sample code step by step and remember you can download it:
ViewTransitions sample application
The ViewTransitions sample application demonstrates how to perform transitions between two views using built-in Core Animation transitions. By looking at the code, you'll see how to use a CATransition object to set up and control transitions.

IPad dismiss Keyboard without knowing which Textfield opened it

Is there a way to do a general resignFirstResponder to hide the keyboard regardless of what textfield/view/etc calls it?
Reason is I have a lot of textfields on my view and don't want to have to resignFirstResponder for all textfields to hide the keyboard. Just want a general
[self resignFirstResponder].
Any ideas?
Thanks in advance
I know that this has already been marked as answered, but for those that run into this like I did you can just use the following method on the view that contains the textfields.
- (BOOL)endEditing:(BOOL)force
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign. UIView Documentation
[self.view endEditing:YES];
it will hide keyboard when we click on view.
You can dismiss the keyboard without any reference to UITextfield / UITextView with help of below code:
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
this will dismiss the keyboard globally without the reference.
hope this will help you.
The easiest way to do this is to have a method for whenever you want to dismiss the keyboard that looks like this:
-(void)dismissKeyboard {
[firstField becomeFirstResponder];
[firstField resignFirstResponder];
}
You can check these questions:
Is it possible to make the iPhone keyboard invisible / remove it without resigning first responder?
Hide Input Keyboard on iPhone Without Knowing First Responder?
In summary:
You can call becomeFirstResponder on some other thing that you choose. It could be a UIViewController or a UIView. I had a similar problem before, I needed to make my keyboard go away when I was pushing my view controller back to its caller, without knowing which textfield was the first responder. Then, on viewWillAppear of my view controller which I was returning back, I called [self becomeFirstResponder] and the keyboard of the pushed view was gone. Because this made whichever text field was it loose being the first responder
In my own app when I had more than one text field and would like to make the keyboard go away regardless which of the fields called it, I would just wrote a method and let each and every of them resignFirstResponder.
I assume that as a programmer, you should have the clear knowledge how many text fields are on your view controller and how you can access them, otherwise it'll get messed up and you app won't look good... :-P