I have a short audio clip that plays when a button is pressed. I want to create a slide-up controller from the bottom that contains a pause/play button and a slider bar displaying the length of the audio. I also want the view behind the controller to remain scrollable while the controller is visible. I believe this excludes using a UIAlertView or UIActionSheetView as both cause the view below to remain static. What is the best way to implement this?
EDIT: i found a helpful tutorial here: http://iosdevelopertips.com/user-interface/sliding-views-on-and-off-screen-creating-a-reusable-sliding-message-widget.html
and I was able to modify this to get something of what I want. However, if I would like to animate using a nib file where/how would i call this?
#import "SlidingMessageController.h"
#interface SlidingMessageController(private)
- (void)hideMsg;
#end
#implementation SlidingMessageController
#pragma mark -
#pragma mark Private Methods
- (void)hideMsg;
{
// Slide the view off screen
CGRect frame = self.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.75];
frame.origin.y = 480;
frame.origin.x = 0;
self.frame = frame;
//to autorelease the Msg, define stop selector
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context
{
[self removeFromSuperview];
[self release];
}
#pragma mark -
#pragma mark Initialization
- (id)initWithDirection:(int)dir;
//- (id)initWithTitle:(NSString *)title message:(NSString *)msg
{
if (self = [super init])
{
//Switch direction based on slideDirection konstant
switch (dir) {
case kSlideUp: //slideup
// Notice the view y coordinate is offscreen (480)
// This hides the view
// What should I be doing here if I want to get the nib file???
self.frame = CGRectMake(0,480,320, 90);
[self setBackgroundColor:[UIColor blackColor]];
[self setAlpha:.87];
newY = 380;
newX = 0;
myDir = 0;
break;
default:
break;
}
}
return self;
}
#pragma mark -
#pragma mark Message Handling
- (void)showMsgWithDelay:(int)delay
{
// UIView *view = self.view;
CGRect frame = self.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.75];
// Slide up based on y axis
// A better solution over a hard-coded value would be to
// determine the size of the title and msg labels and
// set this value accordingly
frame.origin.y = newY;
frame.origin.x = newX;
self.frame = frame;
[UIView commitAnimations];
// Hide the view after the requested delay
[self performSelector:#selector(hideMsg) withObject:nil afterDelay:delay];
}
#pragma mark -
#pragma mark Cleanup
- (void)dealloc
{
if ([self superview])
[self removeFromSuperview];
[super dealloc];
}
#end
What do you mean with a "slide-up controller"? Just a view that slides up from the bottom? If so, you can just create a UIView with the buttons in it, and animate it. For the animation you can use UIView beginAnimations:context: and commitAnimations.
Related
I have paging UIScrollView with images. I want to implement animated zooming of image to fullscreen on some gesture. And another animation to zoom image back to scroll view. Like in Photos app on iPad or like videos in Safari.
Of course it would not be UIImageView. It would be some wrapper class with image inside. The main question is how to present fullscreen view. Is it must be modal view or not.
Any help is appreciated.
Check on touching the image
if it is small convert into full size.
if it is large convert into small size.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (isLarge) [self makeSmall];
else [self makeFull];
}
- (void)makeFull {
[[self superview] bringSubviewToFront:self];
isLarge = YES;
CGRect largeFrame = [self superview].bounds;
original = self.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[self setFrame:largeFrame];
[internal setFrame:self.bounds];
[UIView commitAnimations];
}
- (void)makeSmall {
isLarge = NO;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[self setFrame:original];
[internal setFrame:self.bounds];
[UIView commitAnimations];
}
I found a solution to this that involves both gesture recognizers and animated transitions. You remove the scrollview and add the fullscreen image. Then reverse that to return to the just the scrollview.
Use the frame of the window to determine size for the new UIImage.
The types of gesture recognizers can be adjusted to suit your needs!
-(void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice:)];
tapTwice.numberOfTapsRequired = 2;
[self.imageView addGestureRecognizer:tapTwice];
}
- (void)tapOnce:(id)tapOnce {
[UIView transitionWithView:self.view
duration:0.7
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
[self.fullScreenImage removeFromSuperview];
}
completion:nil];
}
- (void)tapTwice:(id)tapTwice {
if(self.fullScreenImage == nil){
self.fullScreenImage = [[UIImageView alloc] initWithFrame:self.view.window.frame];
UITapGestureRecognizer *tapOnce = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnce:)];
tapOnce.numberOfTapsRequired = 1;
[tapOnce requireGestureRecognizerToFail:tapTwice];
[self.fullScreenImage addGestureRecognizer:tapOnce];
[self.fullScreenImage setUserInteractionEnabled:YES];
//self.fullScreenImage = [load your image here]
}
[UIView transitionWithView:self.view.window
duration:0.7
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
[self.view.window addSubview:self.fullScreenImage];
}
completion:nil];
}
Download this sample for Image gallery sample code and get through it. It would definitely helps you to understand how to implement your idea.
Like below you can use for zooming the image view.
UIView * viewForScroll;
UIImageView *imgviewForScroll;
UIScrollView *scrollToRead = [[UIScrollViewalloc]initWithFrame:CGRectMake(175, 5, 300, 311)];
scrollToRead.backgroundColor = [UIColordarkGrayColor];
scrollToRead.showsHorizontalScrollIndicator = YES;
scrollToRead.delegate = self;
[scrollToRead setContentSize:CGRectMake(0, 0, 300, 400).size];
scrollToRead.maximumZoomScale = 2;
scrollToRead.minimumZoomScale = 1;
[self.view addSubview:scrollToRead];
[scrollToRead release];
viewForScroll = [[UIViewalloc]initWithFrame:CGRectMake(0,0,300,400)];
[scrollToRead addSubview:viewForScroll];
[viewForScroll release];
imgviewForScroll = [[UIImageViewalloc]initWithFrame:CGRectMake(0,0,300,400)];
imgviewForScroll.image = [UIImageimageWithContentsOfFile:[arrayComicContentobjectAtIndex:0]];
[viewForScroll addSubview:imgviewForScroll];
[imgviewForScroll release];
//=========UIScrollView Delegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return viewForScroll;
}
Like to know if you need any further clarifications
I have a container class which is a view controller.
It holds the UITextView for notes and has another view controller as a subview, called it PDFViewController. That one has an array of view controllers, called them PageViewController's, in it and a UIScrollView so i can swipe through the different view controllers from the array.
Each of the PageViewController's has also an UIScrollView, so i can zoom the different pages.
But when I show my UITextView i cannot edit or write anything.
It shows a blinking cursor, but no keyboard and can't write text.
When i highlight a word from the default text, it shows me some dictionary options but the words won't be replaced.
I just don't know where the problem might be.
container.m (View Controller)
- (void) initNotes {
notesVisible = FALSE;
notes = [[UITextView alloc]initWithFrame:CGRectMake(10, 10, note_width, note_height)];
notes.backgroundColor = [UIColor yellowColor];
notes.font = [UIFont fontWithName:#"Arial" size:24];
notes.text = #"Hier ist Platz für Ihre Notizen";
container = [[UIView alloc] initWithFrame:CGRectMake(start_x, start_y, container_width, container_height)];
container.backgroundColor = [UIColor yellowColor];
[container.layer setShadowColor:[[UIColor blackColor] CGColor]];
[container.layer setShadowOffset:CGSizeMake(2.0, 3.0)];
[container.layer setShadowOpacity:0.6];
[container.layer setShadowRadius:5];
container.layer.shouldRasterize = YES;
[container addSubview:notes];
[self.view addSubview:container];
}
- (void) showTextView {
[UIView beginAnimations:#"MoveAndStrech" context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
container.frame = CGRectMake(start_x, self.view.center.y-container_height, container_width, container_height);
[UIView commitAnimations];
notesVisible = !notesVisible;
}
- (void) hideTextView {
[UIView beginAnimations:#"MoveAndStrech" context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
container.frame = CGRectMake(start_x, start_y, container_width, container_height);
// [notes resignFirstResponder];
[UIView commitAnimations];
notesVisible = !notesVisible;
}
#implementation PDFViewController
- (void)awakeFromNib
{
painting = false;
dataInstance = [PDFDataInstance sharedInstance];
chapter = [dataInstance chapter];
[self getNumberOfPages];
kNumberOfPages = dataInstance.pages;
// Register observer to be called when a cell from BookmarkPDFController is pressed
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didSelectBookmark:)
name:#"bookmarkPressedinPDFView" object:nil];
// Register observer to be called when a cell from BookmarkPDFController is pressed
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(togglePainting:)
name:#"togglePainting" object:nil];
// view controllers are created lazily
// in the meantime, load the array with placeholders which will be replaced on demand
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (unsigned i = 0; i < kNumberOfPages; i++)
{
[controllers addObject:[NSNull null]];
}
self.viewControllers = controllers;
[controllers release];
// a page is the width of the scroll view
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.delegate = self;
scrollView.directionalLockEnabled = YES;
currentPage = [[chapter currentPage] integerValue];
// pages are created on demand
// load the visible page
// load the page on either side to avoid flashes when the user starts scrolling
//
// Load pages based on currentPage cause of when coming from bookmarks
[self loadScrollViewWithPage:currentPage];
[self loadScrollViewWithPage:currentPage+1];
// update the scroll view to the appropriate page
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * currentPage;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:YES];
}
- (void)loadScrollViewWithPage:(int)page
{
if (page < 0)
return;
if (page >= kNumberOfPages)
return;
// replace the placeholder if necessary
PageViewController *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null])
{
//page+1 cause CGPDF indexing starts with 1
controller = [[PageViewController alloc] initWithPageNumberAndUrl:page+1: [chapter urlOnFilesystem]];
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (controller.view.superview == nil)
{
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];
}
}
TextView delegates
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(#"begin editing");
}
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText
{
NSLog(#"something changed");
return YES;
}
Just want to add another possibility here. In the iOS simulator, make sure the "Hardware/Keyboard/Connect Hardware Keyboard" is not checked. It took me a couple of hours to figure out this. I guess I toggled that option by accidently pressing the shortcut. Not good experience :(
As pictured, Connect Hardware Keyboard should be UN-checked.
Is the UITextView receiving touches? Implement the UITextViewDelegate methods and see if they get called (esp textViewDidBeginEditing: and textView: shouldChangeTextInRange: replacementText:). This way you'll know for sure whether the text view is indeed handling the touches or not.
If it does, then I don't see anything wrong with your code (except you might have accidentally added a view overlapping the textview)
No one asked , but have you set :
notes.editable = YES ;
?
Make sure that in the delegate of your textview. Following method is returning YES.
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
return YES;
}
After you have set the notes delegates, do the following.
- (void)textViewDidBeginEditing:(UITextView *)textView {
if ([textView isEqual:notes]) {
NSLog(#"notes begin editing");
}
}
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText {
if ([aTextView isEqual:notes]) {
NSLog(#"something changed in notes");
}
return YES;
}
This should confirm delegates of notes are indeed getting called.
you need to implement your container class with UITextViewDelegate
and add notes.delegate=self; just after initialize the notes object in initNotes method.
Check for 2 things:
Is notes.editable = YES; if so please change it to NO.
2.Check whether your UITextView delegates are called are not. If not Please make sure you include in your implementation file and set notes.delegate = self.
Try without container, just use the UITextView (notes) as the container itself.
Every time you used container use notes instead.
And then dont:
[container addSubview:notes];
[self.view addSubview:container];
Just:
[self.view addSubview:notes];
Tell me how it goes
I had similar behavior, the UITextView not responding to touches and the keyboard not showing.
My UITextView was layered on top of a UICollectionView which was receiving all the touches even though the UITextView was visibly on top.
I fixed it by adjusting the frame of the UICollectionView so that the UITextView has nothing behind it. After that, all the delegate methods were called like a charm.
Hope this helps.
please Refer this one. where ContantView is your view/textfield and _bubbletable is your table.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
[UIView animateWithDuration:0.2f animations:^{
CGRect frame = _ContantView.frame;
frame.origin.y -= kbSize.height;
_ContantView.frame = frame;
frame = _bubbleTable.frame;
frame.size.height -= kbSize.height;
_bubbleTable.frame = frame;
}];
}
i am placing a tableview,textview,buttons in a view as like this.
when ever i click on the textview keypad hides textview.To animate up textview i am writing the code as fallows.
- (void) textViewDidBeginEditing:(UITextView *)textView {
[self animateTextField:textView up:YES];
}
- (void) textViewDidEndEditing:(UITextView *)textView {
[self animateTextField:textView up:NO];
}
- (void) animateTextField: (UITextView*) textView up: (BOOL) up {
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
But it does n't take any effect.
And To hide the keypad i am writing this code
-(void) touchesBegan :(NSSet *) touches withEvent:(UIEvent *)event {
[mytextview resignFirstResponder];
}
it is also does n't take any effect.
can any one please help me.
Thank u in advance.
For resigning keyboard;
Make a ToolBar with bar button and add an IBAction for this and set its y coordinate below the 480(screen hieght)
-(IBAction)hide
{
[mytextview resignFirstResponder];
}
and in viewWillAppear use
myTextView.inputAccessoryView=tlBar;
And add two notification in viewWillAppear for keyboard
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
and then use these methods for Animation
-(void) keyboardWillShow:(NSNotification *) note
{
if(isAnimate)
[self viewAnimateUpper];
}
-(void)viewAnimateUpper
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
CGRect viewFrame=self.view.frame;
viewFrame.origin.y -=95;//according to you
self.view.frame=viewFrame;
[UIView commitAnimations];
}
-(void)viewAnimatedown
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
CGRect viewFrame=self.view.frame;
viewFrame.origin.y +=95;//according to you
self.view.frame=viewFrame;
[UIView commitAnimations];
}
-(void) keyboardWillHide:(NSNotification *) note
{
if(isAnimate)
{
[self viewAnimatedown];
}
}
Edit:
use textviewShouldBegainEditing
and in this set a boolvariable to yes if your desired textView call this method
isAnimate=YES;
I didn't find a chance to see you view,since my browser says "The image cant be dispalyed,It contains errors."
So try the following options.
Chk whether you have set the delegate of the textField to the files owner.If you have set and still not working,please try the below one.Its like animating the entire view up and down on textedits.
Please make use of the below code.This works for me.What you have to do is double click the .xib file where you want to add text fields.The view along with a window containing file's owner,first responder and a view will also be opened.
Use cmd+shift+l to open the library and add another view.In your .h file add a IBOutlet for the view as IBOutlet UIView *secondview and map to the file's owner.
Now put the text fields whichever has to moved in the second view.Now the default view which will appear when open the .xib file will contain nothing.It will be blank and the controls whichever you have to display will be on the second view.
In the .m file add the second view to the main view as
[self.view addSubview:secondView];
and use this code by customizing the text field names as you wish.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
CGRect viewFrame = self.view.frame;
if(textField==textfield1)
{
[textfield1 resignFirstResponder];
[textfield2 becomeFirstResponder];
}
else if(textField== textfield2)
{
[textfield2 resignFirstResponder];
[textfield3 becomeFirstResponder];
}
else if(textField== textfield3)
{
[textfield3 resignFirstResponder];
[textfield4 becomeFirstResponder];
}
else if(textField== textfield4)
{
[textfield4 resignFirstResponder];
}
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect viewFrame = secondView.frame;
CGRect textFieldRect =[secondView.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =[secondView.window convertRect:secondView.bounds fromView:secondView];
CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =midline - viewRect.origin.y- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[secondView setFrame:viewFrame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = secondView.frame;
viewFrame.origin.y +=animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[secondView setFrame:viewFrame];
[UIView commitAnimations];
}
Let me know does this worked.
I need to create a expandable and collapsible UIView of some sort and am not able to pay for a third party control.
This is basically how I would like it to behave:
At the top there should be a UIButton (or similar) that allows the user to toggle between expanded and collapsed.
When expanded I want to be able to place other UIView (e.g. calendar)and when collapsed the surrounding controls should move up.
Does anyone have any ideas how to implement this simply - noob here :(
Subclass a ViewController and have two methods that your button can fire like 'collapse' and 'expand', this might get you started: You can assign new selectors to UIButtons dynamically:
[button addTarget:self action:#selector(eventMethod:)
forControlEvents:UIControlEventTouchUpInside];
Code:
#define COLAPSED_HEIGHT 30
-(void)expand
{
CGRect s= [self getScrerenBoundsForCurrentOriantation];
CGRect f = self.view.frame;
f.origin.y =s.size.height-self.view.frame.size.height;
[UIView beginAnimations:#"expand" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
self.view.frame=f;
//CHANGE YOUR EXPAND/COLLAPSE BUTTON HERE
[UIView commitAnimations];
self.thumbScrollerIsExpanded=YES;
}
-(void)collapseView
{
//re-factored so that this method can be called in ViewdidLoad
CGRect s= [self getScrerenBoundsForCurrentOriantation];
CGRect f = self.view.frame;
f.origin.y =(s.size.height-COLAPSED_HEIGHT);
self.view.frame = f;
self.thumbScrollerIsExpanded=NO; //thumbScrollerIsExpanded is a BOOL property
}
- (void)collapse
{
[UIView beginAnimations:#"collapse" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
[self collapseView];
//CHANGE YOUR EXPAND/COLLAPSE BUTTON HERE
[UIView commitAnimations];
}
-(CGRect)getScrerenBoundsForCurrentOriantation
{
return [self getScrerenBoundsForOriantation:[[UIDevice currentDevice] orientation]];
}
-(CGRect)getScrerenBoundsForOriantation:(UIInterfaceOrientation)_orientation
{
UIScreen *screen = [UIScreen mainScreen];
CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
if (UIInterfaceOrientationIsLandscape(_orientation))
{
CGRect temp;
temp.size.width = fullScreenRect.size.height;
temp.size.height = fullScreenRect.size.width;
fullScreenRect = temp;
}
return fullScreenRect;
}
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
if ([animationID isEqualToString:#"expand"])
{
//example
}
else if ([animationID isEqualToString:#"collapse"])
{
//example
}
}
You could try adding a UIView (either in xib or programmatically) off screen, then use a UIView animation to slide it into your main viewing area.
The button would have an IBAction which would toggle the animation (slide in/slide out). You can slide it off screen then set UIView's hidden property to true. When you recall the IBAction, have it check if the view's hidden property is true. If it is, you know to play the animation of it sliding in, if not, then you play the animation of sliding out.
I like to replicate the form behavior of Safari on the iPhone in my own app. If you enter data in an web form you get a separate UIToolbar (previous, next, done) just above the UIKeyboardView. Same for choosing an option: you get the same UIToolbar just above an UIPickerView.
I am looking for demos / sourcode / ideas how to implement this. Would I create my own subview with that toolbar and textview / pickerview? Is there a more elegant way? Especially something that leverages becomeFirstResponder of UITextfield?
So i created a UIViewCOntroller subclass to manage this.
on that i wrote this function to add.
-(void) addToViewWithAnimation:(UIView *) theView
{
UIView* myview = self.view;
CGRect frame = myview.frame;
frame.origin.y = 420;
myview.frame = frame;
UIView* bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 420)];
bgView.backgroundColor = [UIColor blackColor];
bgView.alpha = 0.6;
backgroundView = bgView;
[theView addSubview: bgView]; // this adds in the dark background
[theView addSubview:self.view]; // this adds in the pickerView with toolbar.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
frame = myview.frame;
frame.origin.y = 420 - frame.size.height;
myview.frame = frame;
[UIView commitAnimations];
}
I then created the view in IB, here is what my class Header looked like at the end of that. (there is also a UItoolbar on the view i just do not have a reference to it in my Controller)
#interface PropertyPickerController : UIViewController {
IBOutlet UIPickerView* Picker;
IBOutlet UIButton* DoneButton;
IBOutlet UIButton* CancelButton;
UIView* backgroundView;
NSArray* SimpleObjects;
id PickerObjectDelegate;
SEL PickerObjectSelector;
}
To then hide the view i use.
-(void) removeFromSuperviewWithAnimation
{
UIView* myview = self.view;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(AnimationDidStop:)];
[UIView setAnimationDuration:0.5];
// set fram below window.
CGRect frame = myview.frame;
frame.origin.y = 420;
myview.frame = frame;
backgroundView.alpha = 0; //fades shade to nothing
[UIView commitAnimations];
}
-(void) AnimationDidStop:(id) object
{
[self.view removeFromSuperview]; //removes view after animations.
[backgroundView removeFromSuperview];
}
And last but not least all the delegate functions for the picker.
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
FBSimpleObject* object = (FBSimpleObject*)[SimpleObjects objectAtIndex:row];
return object.Name;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{ return 1;}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [SimpleObjects count];
}
- (IBAction)CancelButtonClick
{
[self removeFromSuperviewWithAnimation];
}
- (IBAction)DoneButtonClick
{
//This performs a selector when the done button is clicked, makes the controller more versatile.
if(PickerObjectDelegate && PickerObjectSelector)
{
NSMethodSignature* signature = [PickerObjectDelegate methodSignatureForSelector:PickerObjectSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:PickerObjectDelegate];
[invocation setSelector:PickerObjectSelector];
[invocation setArgument:&object atIndex:2];
[invocation retainArguments];
[invocation invoke];
}
}
This is how you do the ToolBar. Basically i use the same concept with a ViewController subclass, and i dont use the standard push view or modal display options. (the example here actually places a Textbox and a toolbar on top of the keyboard.
#interface BugEditCommentController : UIViewController {
UITextView* Comment;
UIToolbar* Toolbar;
}
-(void) addToViewWithAnimation:(UIView*) theView;
To activate this view usually you would call [object becomeFirstResponder];
so if you add this to your view Controller constructor, all you need to do is call [object becomeFirstResponder];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];
abd if you implement this method on your controller (defined in the above code)
-(void) keyboardWillShow:(NSNotification *) note
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect toolbarFrame = Toolbar.frame;
CGRect keyboardFrame;
CGPoint keyboardCenter;
[[note.userInfo valueForKey:UIKeyboardCenterEndUserInfoKey] getValue:&keyboardCenter];
[[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardFrame];
//CGRect toolbarRect = Toolbar.center;
toolbarFrame.origin.y= keyboardCenter.y - ((keyboardFrame.size.height/2) + (toolbarFrame.size.height));
Toolbar.frame = toolbarFrame;
[UIView commitAnimations];
}
-(void) keyboardWillHide:(id) object
{
//you could call [self removeFromSuperviewHere];
}
-(void) removeFromsuperViewWithAnimation
{
[Comment resignFirstResponder];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(AnimationDidStop:)];
CGRect frame = Toolbar.frame;
frame.origin.y = 480;
Toolbar.frame = frame;
[self.view viewWithTag:1].alpha = 0; //fade transparent black background to clear.
[UIView commitAnimations];
}
-(void)AnimationDidStop:(id) object
{
[self.view removeFromSuperview];
}
hope the additional info helps.
I'm looking for the solution for this issue too.
I found this was the best solution, you can use this SCKit to add tool bar to dismiss the UIPickerView or the UIDatePicker as you want.
Following is github link: https://github.com/scelis/SCKit/tree/
Have fun!