I have a UISearchBar that needs to be compressed (see screenshot) and then expand to a larger size when it is touched or isActive.
How would I go about doing this? Currently my search bar is placed in the view via IB.
thanks
Use this delegate of the search bar :
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[self setTheSearchBarWithRect:newRect];//newRect is CGRect;
}
-(void)setTheSearchBarWithRect:(CGRect)frame{
[UIView animateWithDuration:(1.5f)
delay:0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
yourSearchBar.frame = frame;
}
completion:^(BOOL finished){
}];
}
and in the below delegate call the above function with its original frame.
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar;
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar;
I would suggest adding a NSNotifcation listener for the keyboard showing/hiding notifications and based on this adjust the UISearchBar frame:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(adjustFrame:) name:UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(adjustFrame:) name:UIKeyboardWillHideNotification object:nil];
}
We need to remove the listener when the view is going to disappear:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[nc removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
And now we need the 2 custom functions to adjust the frame:
- (void)adjustFrame:(NSNotification *) notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationBeginsFromCurrentState:YES];
if ([[notification name] isEqual:UIKeyboardWillHideNotification]) {
// revert back to the normal state.
self.searchBar.frame = CGRectMake (100,50,100,self.searchBar.frame.size.Height);
}
else {
//resize search bar
self.searchBar.frame = CGRectMake (10,50,200,self.searchBar.frame.size.Height);
}
[UIView commitAnimations];
}
You should just change search bar frame (location and size) on editing start and ending.
for example:
on start
sbar.frame = CGRectMake(sbar.frame.origin.x - 100., sbar.frame.origin.y, sbar.frame.size.x + 100., sbar.frame.size.y);
on edit end just back control at original place:
sbar.frame = CGRectMake(sbar.frame.origin.x + 100., sbar.frame.origin.y, sbar.frame.size.x - 100., sbar.frame.size.y);
Related
I want my view to scroll down when keyboard hides, the thing is that for the first time the view comes from outside of its frame(first image I have attached) but if I hide keyboard for the second time the view scrolls down in a correct way(second figure).
Here is the code related to this part:
- (void)viewDidUnload
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
}
- (void)keyboardDidShow:(NSNotification *)notification
{
[_scrollView setScrollEnabled:TRUE];
}
- (void)keyboardDidHide:(NSNotification *)notification
{
[UIView animateWithDuration:4 animations:^{
NSDictionary* info = [notification userInfo];
//---obtain the size of the keyboard---
NSValue* aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [self.view convertRect:[aValue CGRectValue] fromView:nil];
//---resize the scroll view back to the original size (without keyboard)---
CGRect viewFrame = [self.view frame];
viewFrame.size.height += keyboardRect.size.height;
self.scrollView.frame = viewFrame;
}];
}
Hi can someone help me create this feature, I would like to have a text box at the bottom of my app, and as soon as the user clicks on it, it should raise that text box to the middle of screen right above the keyboard. Similar to skype app, thanks!
Try This
#define kKeyboardAnimationDuration 0.3
#interface YourViewController:UIViewController
{
BOOL keyboardIsShown;
}
And then in your implementation
- (void)viewDidLoad
{
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:self.view.window];
keyboardIsShown = NO;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
#pragma mark - Keyboard Events
- (void)keyboardWillShow:(NSNotification *)n
{
if (keyboardIsShown)
{
return;
}
NSDictionary* userInfo = [n userInfo];
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect viewFrame = self.view.frame;
viewFrame.origin.y-= (keyboardSize.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:kKeyboardAnimationDuration];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = YES;
}
- (void)keyboardWillHide:(NSNotification *)n
{
NSDictionary* userInfo = [n userInfo];
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect viewFrame = self.view.frame;
viewFrame.origin.y+= (keyboardSize.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:kKeyboardAnimationDuration];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = NO;
}
I have several UITextFields listed below each other and would like to move the active field appropriately when the keyboard slides up.
I have added my controller as an observer to UIKeyboardWillShowNotifications and that works fine when the user first taps a text field. If he taps one of the other text fields without making the keyboard go away first no UIKeyboardWillShowNotifications appears though and I get no chance to adjust the position of the new active text field. I guess it somehow makes sense that no UIKeyboardWillShowNotification appears as the keyboard just stays there but...
What to do??
I do not see how I can add my adjusting code somewhere else as I need the keyboard size information which is kept in the userInfo in the keyboard notification.
Thanks a lot,
Stine
EDIT: Maybe it will be more clear what I need if I paste some of my code here:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(cellInputViewWillOpen:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(cellInputViewWillClose) name:UIKeyboardWillHideNotification object:nil];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
- (void) cellInputViewWillOpen:(NSNotification *)aNotification {
CGRect keyboardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];
keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]];
self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, cell.frame.origin.y - ((self.tableView.frame.size.height - keyboardFrame.size.height) / 2.0f));
self.tableView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, keyboardFrame.size.height - 44.0f, 0.0f);
[UIView commitAnimations];
}
- (void) cellInputViewWillClose {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
self.tableView.contentInset = UIEdgeInsetsZero;
[UIView commitAnimations];
}
Use textField:didBeginEditing instead. You may need to keep track separately of if your keyboard is already showing so you don't scroll twice.
EDIT : I didn't realise you were talking about a table view, sorry. In that case you can adjust the scroll view contents as you are already doing, then use the table view scroll to index path methods when you change the selection using the table view delegate methods.
i had created a navigation based small application. When I click to the table row, it display controller having UIScrollView and number of TextFields added in it, when i returned back to main controller, then again i navigate to that controller, it do not scroll and still contain previous values in textfield. I am not able to know where is the problem.
Here is my code:
rootcontroller.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch(indexPath.row)
{
case 1:
if(insertViewController == nil)
insertViewController = [[insertView alloc] initWithNibName:#"insertView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:insertViewController animated:YES];
break;
//[insertViewController release];
}
}
insertviewcontoller.m
#import "insertView.h"
#import "RootViewController.h"
#import "Foundation/Foundation.h"
#define kTabBarHeight 5.0
#define kKeyboardAnimationDuration 1.0
#implementation insertView
#synthesize scroll;
- (void)viewDidLoad {
[super viewDidLoad];
//for scrolling
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:self.view.window];
keyboardIsShown = NO;
//make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
CGSize scrollContentSize = CGSizeMake(320, 345);
self.scroll.contentSize = scrollContentSize;
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)keyboardWillHide:(NSNotification *)n
{
NSDictionary* userInfo = [n userInfo];
// get the size of the keyboard
NSValue* boundsValue = [userInfo objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [boundsValue CGRectValue].size;
// resize the scrollview
CGRect viewFrame = self.scroll.frame;
// I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
viewFrame.size.height += (keyboardSize.height - kTabBarHeight);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
// The kKeyboardAnimationDuration I am using is 0.3
[UIView setAnimationDuration:kKeyboardAnimationDuration];
[self.scroll setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = NO;
}
- (void)keyboardWillShow:(NSNotification *)n
{
// This is an ivar I'm using to ensure that we do not do the frame size adjustment on the UIScrollView if the keyboard is already shown. This can happen if the user, after fixing editing a UITextField, scrolls the resized UIScrollView to another UITextField and attempts to edit the next UITextField. If we were to resize the UIScrollView again, it would be disastrous. NOTE: The keyboard notification will fire even when the keyboard is already shown.
if (keyboardIsShown) {
return;
}
NSDictionary* userInfo = [n userInfo];
// get the size of the keyboard
NSValue* boundsValue = [userInfo objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [boundsValue CGRectValue].size;
// resize the noteView
CGRect viewFrame = self.scroll.frame;
// I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
// The kKeyboardAnimationDuration I am using is 0.3
[UIView setAnimationDuration:kKeyboardAnimationDuration];
[self.scroll setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = YES;
}
- (void)dealloc {
[super dealloc];
[scroll release];
[nmtf release];
[phtf release];
[addtf release];
}
update viewDidLoad method into viewWillAppear:(BOOL)animated in your insertviewcontoller.m page
I am using keyboardWasShown and keyboardWillBeHidden notification for sliding the view to get the visible text view.
I have a UITabBar application with six tabs.
In each view I am using the UINavigationController.
In the detail view of each UITableViewCell I am using the keyboard notifications.
So the problem is that the keyboard notifications work for the first time that I will use . on on the other tabs it won't work .
The code is as follows :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification
object:nil];
and the methods
- (void)keyboardWasShown:(NSNotification *)aNotification {
if ( keyboardShown )
return;
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= keyboardSize.height-100;
frame.size.height += keyboardSize.height-100;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
keyboardShown = YES;
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
if ( viewMoved && tvAddreview) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-100;
frame.size.height -= keyboardSize.height-100;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
keyboardShown = NO;
}
you should dothis in eachClass like this:
-(void) viewWillAppear: (BOOL)animated
{
[super viewWillAppear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification
object:nil];
[nc addObserver:self
selector:#selector(keyboardWasHidden:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void) viewWillDisappear: (BOOL)animated{
[super viewWillDisappear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[nc removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
because the notifications are on the application level not to your class level. So if you have added them in one class and not in all classes, then going to the next class. the notification will still call the the key keyboardWasShown: and the other from the class in which you added the notifications hence your local variables like...
viewMoved = YES;
keyboardShown = YES;
will throw the bad excess exceptions
In your case it is also required to do in all 6 view controllers
Hope this helps.