Adjusting interface when keyboard appears for UITextField or UITextView - cocoa-touch

I have a table with each cell containing a label and a text field. Problem is that when i go to edit the last row, keyboard hides the lower portion of the table, and i can't see what is being typed. How can i move my interface above the keyboard so i see what is being typed?
Thanks,
Mustafa

You'll want to register your viewController for UIKeyboardDidShowNotification and UIKeyboardWillHideNotification events. When you get these, you should adjust the bounds of your table; the keyboard is 170 pixels height, so just shrink or grow your table bounds appropriately, and it should properly adjust to the keyboard.

This problem is complex depending on your UI scenario. Here I will discuss a scenario that where UITextField or UITextview resides in a UITableViewCell.
You need to use NSNotificationCenter to detect UIKeyboardDidShowNotification event.
see http://iosdevelopertips.com/user-interface/adjust-textfield-hidden-by-keyboard.html. You need to shrink the UITableView frame size so that it occupies only the screen area that is not covered by the keyboard.
If you tap a UITableViewCell, the OS will automatically position the cell within the viewing area of UITableView. But it does not happen when you tap a UITextView or UITableViewCell even though it resides in a UITableViewCell.
You need to call
[myTableView selectRowAtIndexPath:self.indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom];`
to programmatically "tap" the cell.
If you implement both points, you will see the UITextView/Field position right above the keyboard. Bare in mind that the UITableViewCell where the UITableView/Field resides cannot be taller than the "not covered" area. If this is not the case for you, there is a different approach for it but I will not discuss here.

Check out this question: A UITableView list of editable text fields

Just make sure that you have enough scrolling space below that. Because according to my knowledge the iPhone automatically adjusts and shows the focused textbox at the time its keyboard appears.

Removing/commenting the lines where the rect hight is being modified seems to solve the problem. Thanks.
Modified Code:
# define kOFFSET_FOR_KEYBOARD 150.0 // keyboard is 150 pixels height
// Animate the entire view up or down, to prevent the keyboard from covering the author field.
- (void)setViewMovedUp:(BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// Make changes to the view's frame inside the animation block. They will be animated instead
// of taking place immediately.
CGRect rect = self.view.frame;
CGRect textViewRect = self.textViewBeingEdited.frame;
CGRect headerViewRect = self.headerView.frame;
if (movedUp) {
// If moving up, not only decrease the origin but increase the height so the view
// covers the entire screen behind the keyboard.
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
// rect.size.height += kOFFSET_FOR_KEYBOARD;
} else {
// If moving down, not only increase the origin but decrease the height.
rect.origin.y += kOFFSET_FOR_KEYBOARD;
// rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
self.view.frame = rect;
[UIView commitAnimations];
}

[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification
object:nil];
keyboardVisible = NO;
- (void)keyboardWasShown:(NSNotification *)aNotification {
if ( keyboardVisible )
return;
if( activeTextField != MoneyCollected)
{
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-300;
frame.size.height += keyboardSize.height-50;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardVisible = YES;
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
if ( viewMoved )
{
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-300;
frame.size.height -= keyboardSize.height-50;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
keyboardVisible = NO;
}

tabelview.contentInset = UIEdgeInsetsMake(0, 0, 210, 0);
[tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:your_indexnumber inSection:Your_section]
atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
try this my coding this will help for u

Related

Resizing UITextView when keyboard appears in iOS7

This question has been asked a couple of times, but I wasn't really able to find an answer...
In iOS6 I used the following to resize an UITextView whenever the keyboard appeared. Under iOS7 behavior is not as it should be (in my case, it seems like nothing is resizing at all). I suspect the cause to be the auto-layout / constraint behavior of iOS7. Any suggestions? ("notePad" is my UITextView)?
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
//NSLog(#"KeyboardSize: %f.%f", kbSize.width, kbSize.height);
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, (kbSize.width > kbSize.height ?
kbSize.height : kbSize.width), 0);
self.notePad.contentInset = contentInsets;
self.notePad.scrollIndicatorInsets = contentInsets;
}
If you're using auto-layout at your views the following method may help you.
First define a IBOutlet for your bottom layout guide constraint and link with storyboard element.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;
Second add observers for keyboard notifications.
- (void)observeKeyboard {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Finally the methods that handles keyboard changes.
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];
int kbHeight = finalKeyboardFrame.size.height;
int height = kbHeight + self.textViewBottomConst.constant;
self.textViewBottomConst.constant = height;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
self.textViewBottomConst.constant = 10;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
This method supports orientation changes and different keyboard sizes. Hope it helps.
Your code is logically correct. When keyboard appear you shouldn't almost never change the frame of an object with the scrollview behaviour, but you should only change the insets.
The insets should change relative to the current version because iOS7 take care of adjust for navigation bar. If you provide a new insets probably you will broke something in UI.
Your code is broken on iOS7 for two main reason:
You must add auto layout constraint to textview container. (Probably your text view is bigger then you expect)
You shouldn't change insets in absolute way.
Here are the steps to properly configure a textview:
In xib (or storyboard) add constraint to top, left, right, bottom to the container (in my case {0, 0, 0, 0} as shown below
Register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
In keyboardWillShow and keyboardWillHide don't change the frame, but change the insets relatively to the existing one.
- (void)keyboardWillShow:(NSNotification *)notification
{
// Take frame with key: UIKeyboardFrameEndUserInfoKey because we want the final frame not the begin one
NSValue *keyboardFrameValue = [notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
UIEdgeInsets contentInsets = self.textView.contentInset;
contentInsets.bottom = CGRectGetHeight(keyboardFrame);
self.textView.contentInset = contentInsets;
self.textView.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
UIEdgeInsets contentInsets = self.textView.contentInset;
contentInsets.bottom = .0;
self.textView.contentInset = contentInsets;
self.textView.scrollIndicatorInsets = contentInsets;
}
Then remember to remove observers
#BoranA has the correct answer, but requires tweaking for full functionality for ALL keyboards.
Follow the code below:
Attach the below to your Vertical Space - Bottom Layout Guide - TextField
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;
Second add observers for keyboard notifications.
- (void)observeKeyboard {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Add this to your viewDidLoad
[self observeKeyboard];
Finally the methods that handles keyboard changes.
- (void)keyboardWillShow:(NSNotification *)notification {
//THIS WILL MAKE SURE KEYBOARD DOESNT JUMP WHEN OPENING QUICKTYPE/EMOJI OR OTHER KEYBOARDS.
kbHeight = 0;
height = 0;
self.textViewBottomConst.constant = height;
self.btnViewBottomConst.constant = height;
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];
int kbHeight = finalKeyboardFrame.size.height;
int height = kbHeight + self.textViewBottomConst.constant;
self.textViewBottomConst.constant = height;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
self.textViewBottomConst.constant = 10;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
I found I had to call [self layoutIfNeeded] in order my insets to take effect.
My keyboard notification method looks like this (I prefer to animate the change):
-(void)keyboardWillShow:(NSNotification*)notification;
{
NSDictionary *userInfo = [notification userInfo];
NSValue *keyboardBoundsValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGFloat keyboardHeight = [keyboardBoundsValue CGRectValue].size.width;
CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
NSInteger animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
[UIView animateWithDuration:duration delay:0. options:animationCurve animations:^{
[[self textView] setContentInset:UIEdgeInsetsMake(0., 0., keyboardHeight, 0.)];
[[self view] layoutIfNeeded];
} completion:nil];
}
You need to resize your UITextView when your keyboard appears.
So have a look to a previous answer I made here.
You need to call the following method to resize your UITextView depending of the width of your keyboard and the text :
- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width
{
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:text];
CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
Your code using my method :
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// Get your text to NSAttributedString
NSAttributedString *as = [[NSAttributedString alloc] initWithString:self.notePad.text];
// Resize UITextView
self.notePad.frame = CGRectMake(0, 0, CGRectGetWidth(self.notePad.frame), [self textViewHeightForAttributedText:as andWidth:kbSize.width)]);
}
I’d been battling with this for a week and I found that adding the keyboard size’s height to the bottom contentInset didn’t work.
What worked was subtracting it from the top, like so:
UIEdgeInsets insets = UIEdgeInsetsMake(-(kbSize.height), 0.0, 0.0, 0.0);
[self.textView setContentInset:insets];

Scroll to textfield when focus and keyboard hide text field

I have multiple text fields and when i focus on the textbox, it will automatically scroll up and the keyboard hide the textfield.
Any idea how to scroll the textfield to the focus field when click?
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
The code snippet that you posted I think is the one from the Apple's documentation, which assumes a basic view hierarchy with a UIScrollView (or one of its subclasses, like UITableView) filling the entire screen. If your view layout is more complex, or you need to support multiple orientations, the text field won't scroll to visible because rectangle calculations will be wrong. You need to tweak the code a bit and my suggestion is that you approach the problem this way:
The new contentInsent height for your scroll view should be equal to the height of the intersection rectangle between the keyboard and your scroll view.
In code:
- (void)keyboardWasShown:(NSNotification*)aNotification
{
CGRect kbRawRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect scrollViewFrame = [self.scrollView.window convertRect:self.scrollView.frame fromView:self.scrollView.superview];
// Calculate the area that is covered by the keyboard
CGRect coveredFrame = CGRectIntersection(scrollViewFrame, kbRawRect);
// Convert again to window coordinates to take rotations into account
coveredFrame = [self.scrollView.window convertRect:self.scrollView.frame fromView:self.scrollView.superview];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, coveredFrame.size.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
CGRect activeFieldRect = [self.activeField convertRect:self.activeField.bounds toView:self.scrollView];
[self.scrollView scrollRectToVisible:activeFieldRect animated:YES];
}
Notice that I've used the convenient UIScrollView's scrollRectToVisible function to abstract the final scrolling operation as much as possible.

Autolayout Constraint - Keyboard

Im stuck trying to animate a table view smoothly which has an autolayout contraint. I have a reference to the constraint "keyboardHeight" in my .h and have linked this up in IB. All i want to do is animate the table view with the keyboard when it pops up. Here is my code:
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
CGFloat height = keyboardFrame.size.height;
[UIView animateWithDuration:animationDuration animations:^{
self.keyboardHeight.constant = -height;
[self.view setNeedsLayout];
}];
}
The thing is the animation block is instantaneous and I see white space appear before the keyboard has finished its animation. So basically I see the white background of the view as the keyboard is animating. I cannot make the animation last for as long as the keyboard is animating.
Am i approaching this the wrong way? Thanks in advance!
Try it this way:
self.keyboardHeight.constant = -height;
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
Remember this pattern because this should be the correct way to update constraint-based layouts (according to WWDC). You can also add or remove NSLayoutConstraints as long as you call setNeedsUpdateConstraints after.
If you're using UITableViewController, keyboard size should be automatically accommodated by iOS to adjust the contentInsets. But if your tableView is inside a UIViewController, you probably wanted to use this:
KeyboardLayoutConstraint in the Spring framework. Simplest solution I've found so far.
Try the next code. In this case table view lays out at the bottom edge of the screen.
- (void)keyboardWillShow:(NSNotification *)notification { // UIKeyboardWillShowNotification
NSDictionary *info = [notification userInfo];
NSValue *keyboardFrameValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
CGFloat keyboardHeight = isPortrait ? keyboardFrame.size.height : keyboardFrame.size.width;
// constrBottom is a constraint defining distance between bottom edge of tableView and bottom edge of its superview
constrBottom.constant = keyboardHeight;
// or constrBottom.constant = -keyboardHeight - in case if you create constrBottom in code (NSLayoutConstraint constraintWithItem:...:toItem:...) and set views in inverted order
[UIView animateWithDuration:animationDuration animations:^{
[tableView layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification { // UIKeyboardWillHideNotification
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
constrBottom.constant = 0;
[UIView animateWithDuration:animationDuration animations:^{
[tableView layoutIfNeeded];
}];
}
The approach I took is to add a view which follows the size of the keyboard. Add it below your tableview, or text input or whatever and it will push things up when the keyboard appears.
This is how I set up the view hierarchy:
NSDictionary *views = #{#"chats": self.chatsListView, #"reply": self.replyBarView, #"fakeKeyboard":self.fakeKeyboardView};
[self.view addVisualConstraints:#"V:|-30-[chats][reply][fakeKeyboard]|" views:views];
And then the key bits of the keyboard-size-following view look like this:
- (void)keyboardWillShow:(NSNotification *)notification
{
// Save the height of keyboard and animation duration
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
self.desiredHeight = CGRectGetHeight(keyboardRect);
self.duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
[self animateSizeChange];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
self.desiredHeight = 0.0f;
[self animateSizeChange];
}
- (CGSize)intrinsicContentSize
{
return CGSizeMake(UIViewNoIntrinsicMetric, self.desiredHeight);
}
- (void)animateSizeChange
{
[self invalidateIntrinsicContentSize];
// Animate transition
[UIView animateWithDuration:self.duration animations:^{
[self.superview layoutIfNeeded];
}];
}
The nice thing about letting this particular view handle its resizing is that you can let the view controller ignore it, and you can also re-use this view any place in your app you want to shift everything up.
The full file is here:
https://gist.github.com/shepting/6025439

Setting UIView Frame

I'm trying to resize my UITextView when the keyboard appears, but I don't know what I'm doing wrong.
I have these three lines of code called when the keyboard appears:
CGSize kbSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
textView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-kbSize.height);
NSLog(#"%f,%f,%f,%f", textView.frame.origin.x, textView.frame.origin.y, textView.frame.size.width, textView.frame.size.height);
For some really odd reason my keyboard doesn't appear and here is what is logged:
0.000000,-180.000000,480.000000,180.000000
Why is the CGRects y origin getting set to -180 when it is hardcoded in at 0?
EDIT: textView is a UITextView I created programatically. I didn't use Interface Builder.
EDIT2: It seems that the problem is that the view is autoresizing when rotated.
You can try this :
- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up {
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
keyboardFrame.size.height -= tabBarController.tabBar.frame.size.height;
newFrame.size.height -= keyboardFrame.size.height * (up?1:-1);
textView.frame = newFrame;
[UIView commitAnimations];
}
Hope it'll help

Get UITableviewCell position from "visible" area or window

I create an iPhone app base on uitableview and uitabbar. On each cell of tableview i have an "add to favorite button".
When i pressed this button, i want to make the cell "jump" from her position to the favorite item of the tabbar (same as download effect in installous)
The effect work well if i'am on top 10 cell, but if i scroll in the tableView the effect is not good because start position is calculate from uitableview size.
It's possible to know the position of a cell from the visible area. ?
Exemple : for the fortieth cell position is x:0,y:1600,w:320,y:50, i want the position from the top of the screen not from the top of the uiview so something like this x:0,y:230,w:320,y:50
Yes you can use rectForRowAtIndexPath: you'll just have to pass in the indexPath of your row you've clicked.
rectForRowAtIndexPath:
Returns the drawing area for a row
identified by index path.
...
EDIT
Conversion:
CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];
CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];
So here is the code i used : (it can be optimized i'm sure) :
First add NSindexPath ** property to your custom cell.
*Implement this in your tableview controller : *
-(void)addCellToFavorisWithAnimation:(ResultSearchOffreCell*)cell{
/* Generate image from cell
----------------------------------------------------------*/
UIGraphicsBeginImageContextWithOptions(cell.bounds.size, cell.opaque, [[UIScreen mainScreen] scale]);
[cell.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Launch first animation (go to top-right)
//----------------------------------------------------------*/
CGRect rectInTableView = [self.tableView rectForRowAtIndexPath:cell.indexPath];
CGRect rectInSuperview = [self.tableView convertRect:rectInTableView toView:[self.tableView superview]];
cellAnimationContainer = [[UIImageView alloc] initWithFrame:rectInSuperview];
[cellAnimationContainer setFrame:CGRectMake(cellAnimationContainer.frame.origin.x, cellAnimationContainer.frame.origin.y+50 , cellAnimationContainer.frame.size.width, cellAnimationContainer.frame.size.height)];
[cellAnimationContainer setImage:img];
AppDelegate_Shared *appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate.window addSubview:cellAnimationContainer];
[UIView beginAnimations:#"addFavorite-Step1" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:0.2];
[cellAnimationContainer setFrame:CGRectMake(20,cellAnimationContainer.frame.origin.y-10, cellAnimationContainer.frame.size.width, cellAnimationContainer.frame.size.height)];
[cellAnimationContainer setAlpha:0.7];
[UIView commitAnimations];
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
/* Launch second animation => go to favoris Tab and remove from self.view
---------------------------------------------------------------------------*/
if([anim isEqual:#"addFavorite-Step1"])
{
[UIView beginAnimations:#"addFavorite-Step2" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[cellAnimationContainer setAlpha:0.4];
[cellAnimationContainer setFrame:CGRectMake(150, 420, 20, 20)];
[UIView commitAnimations];
}
else if([anim isEqual:#"addFavorite-Step2"])
{
[cellAnimationContainer removeFromSuperview];
[cellAnimationContainer release];
}
}
Yes this is possible like that
-(void)click:(id)sender
{
int clickcelltag;
clickcelltag=sender.tag;
NSIndexPath *index =[NSIndexPath indexPathForRow:clickcelltag inSection:0];
[userreviewtblview scrollToRowAtIndexPath:index atScrollPosition:UITableViewScrollPositionTop animated:YES];//userreviewtblview is a UITableView name
}
Hope this will help you :-)