UIScrollView does not move view ontop of keyboard iPad - objective-c

I have several text fields on screen. When I tap inside of the one towards the bottom, the keyboard appears over them.
I've referred to apple's documentation and used the following code to try and tackle this.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (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 app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
What i'd like to happen, when the keyboard appears the text fields that in side the scroll field will move up. Any help is appreciated.

Use This Code for Move the view up..........
-(void) textFieldDidBeginEditing:(UITextField*)textField
{
[self slideViewUpForTextField:textField];
}
-(void) slideViewUpForTextField:(UITextField *)textField
{
CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.origin.y + 3.0 * 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 < 0.0)
heightFraction = 0.0;
else 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);
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
And write these on top of the class
And After #import"".....
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 158;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
This is also write ....
-(void) textFieldDidEndEditing:(UITextField*) textField
{
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}

Related

keyboard obeserver ios

I have a UIView and i'm trying to make it follow the keyboard when the user move the keyboard. imagine the user having a scrollview and a open keyboard, the user want to scroll down which makes the keyboard to close half way, the keyboard origin.y change. the problem is when the keyboard is open and moving no event is being called else you literally close the keyboard.
I tried using the keyboard delegate + textfield delegate which is:
* UIKeyboardWillShowNotification
* UIKeyboardDidShowNotification
* UIKeyboardWillHideNotification
* UIKeyboardDidHideNotification
* UIKeyboardWillChangeFrameNotification
* textFieldDidBeginEditing:
* textFieldShouldBeginEditing:
* textFieldDidEndEditing:
* textFieldShouldEndEditing:
All those methods are being called only when keyboard is about to open/dismiss and what is happening is that when the user is moving the keyboard the UIView wont move as it wait for one of those observers to be called.
What i am basically looking for is a way to observe the keyboard origin.y (shown height) whenever its value change
Put this code below
#import
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 140;
textfieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
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 < 0.0)
{
heightFraction = 0.0;
}
else 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);
}
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField
{
NSInteger nextTag = textField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder)
{
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
}
else
{
//Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We // We do not want UITextField to insert line-breaks.
}

Bounce UIImageView back when dragged off screen

What I need is when a UIImageView is dragged off of the screen it to bounce back when it gets let go. I have it working in the left and top sides this is what I am doing.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!CGRectContainsPoint(self.view.frame, imageView.frame.origin)){
CGFloat newX = 0.0f;
CGFloat newY = 0.0f;
// If off screen upper and left
if (imageView.frame.origin.x < 0.0f){
CGFloat negX = imageView.frame.origin.x * -1;
newX = negX;
}else{
newX = imageView.frame.origin.x;
}
if (imageView.frame.origin.y < 0.0f){
CGFloat negY = imageView.frame.origin.y * -1;
newY = negY;
}else{
newY = imageView.frame.origin.y;
}
CGRect newPoint = CGRectMake(newX, newY, imageView.frame.size.width, imageView.frame.size.height);
[UIView beginAnimations:#"BounceAnimations" context:nil];
[UIView setAnimationDuration:.5];
[letterOutOfBounds play];
[imageView setFrame:newPoint];
[UIView commitAnimations];
}
}
}
So I would like to achieve the same thing for the right and bottom sides. But I have been stuck at this for awhile. Any Ideas?
How about something like the following?
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIImageView *imageView = nil;
BOOL moved = NO;
CGRect newPoint = imageView.frame;
// If off screen left
if (newPoint.origin.x < 0.0f){
newPoint.origin.x *= -1.0;
moved = YES;
}
// if off screen up
if (newPoint.origin.y < 0.0f){
newPoint.origin.y *= -1.0;
moved = YES;
}
// if off screen right
CGFloat howFarOffRight = (newPoint.origin.x + newPoint.size.width) - imageView.superview.frame.size.width;
if (howFarOffRight > 0.0)
{
newPoint.origin.x -= howFarOffRight * 2;
moved = YES;
}
// if off screen bottom
CGFloat howFarOffBottom = (newPoint.origin.y + newPoint.size.height) - imageView.superview.frame.size.height;
if (howFarOffBottom > 0.0)
{
newPoint.origin.y -= howFarOffBottom * 2;
moved = YES;
}
if (moved)
{
[UIView beginAnimations:#"BounceAnimations" context:nil];
[UIView setAnimationDuration:.5];
[letterOutOfBounds play];
[imageView setFrame:newPoint];
[UIView commitAnimations];
}
}
As I read your code, the logic of "if off the left side, move it back on to the view by the same distance it was off the screen." To be honest, that doesn't quite make sense to me (why, when bouncing back, does the coordinate depend upon how far off the screen it was), but I've tried to honor that in the "off screen right" and "off screen bottom" logic. Obviously my logic is using the superview of imageView to determine the width of the containing view, but if that's not appropriate, replace it with whatever is.
Edit:
I personally do this stuff with gesture recognizers, such as:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.imageView addGestureRecognizer:pan];
self.imageView.userInteractionEnabled = YES;
Thus, a gesture recognizer to animate moving the image back would be:
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGRect originalFrame; // you could make this an ivar if you want, but just for demonstration purposes
if (gesture.state == UIGestureRecognizerStateBegan)
{
originalFrame = self.imageView.frame;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint translate = [gesture translationInView:gesture.view];
CGRect newFrame = originalFrame;
newFrame.origin.x += translate.x;
newFrame.origin.y += translate.y;
gesture.view.frame = newFrame;
}
else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled)
{
CGRect newFrame = gesture.view.frame;
newFrame.origin.x = fmaxf(newFrame.origin.x, 0.0);
newFrame.origin.x = fminf(newFrame.origin.x, gesture.view.superview.bounds.size.width - newFrame.size.width);
newFrame.origin.y = fmaxf(newFrame.origin.y, 0.0);
newFrame.origin.y = fminf(newFrame.origin.y, gesture.view.superview.bounds.size.height - newFrame.size.height);
// animate how ever you want ... I generally just do animateWithDuration
[UIView animateWithDuration:0.5 animations:^{
gesture.view.frame = newFrame;
}];
}
}
Or, if you want a gesture recognizer that just prevents the dragging of the image off the screen in the first place, it would be:
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGRect originalFrame;
if (gesture.state == UIGestureRecognizerStateBegan)
{
originalFrame = self.imageView.frame;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint translate = [gesture translationInView:gesture.view];
CGRect newFrame = originalFrame;
newFrame.origin.x += translate.x;
newFrame.origin.x = fmaxf(newFrame.origin.x, 0.0);
newFrame.origin.x = fminf(newFrame.origin.x, gesture.view.superview.bounds.size.width - newFrame.size.width);
newFrame.origin.y += translate.y;
newFrame.origin.y = fmaxf(newFrame.origin.y, 0.0);
newFrame.origin.y = fminf(newFrame.origin.y, gesture.view.superview.bounds.size.height - newFrame.size.height);
gesture.view.frame = newFrame;
}
}
By the way, in iOS 7, you can give the animation of the image view back to its original location a little bounciness by using the new animationWithDuration with the usingSpringWithDampening and initialSpringVelocity parameters:
[UIView animateWithDuration:1.0
delay:0.0
usingSpringWithDamping:0.3
initialSpringVelocity:0.1
options:0
animations:^{
// set the new `frame` (or update the constraint constant values that
// will dictate the `frame` and call `layoutViewsIfNeeded`)
}
completion:nil];
Alternatively, in iOS7, you can also use UIKit Dynamics to add a UISnapBehavior:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.viewToAnimate snapToPoint:CGPointMake(self.viewToAnimate.center.x, self.view.frame.size.height - 50)];
// optionally, you can control how much bouncing happens when it finishes, e.g., for a lot of bouncing:
//
// snap.damping = 0.2;
// you can also slow down the snap by adding some resistance
//
// UIDynamicItemBehavior *resistance = [[UIDynamicItemBehavior alloc] initWithItems:#[self.viewToAnimate]];
// resistance.resistance = 20.0;
// resistance.angularResistance = 200.0;
// [self.animator addBehavior:resistance];
[self.animator addBehavior:snap];
I think the easiest way is to check whether your imageView has gone out of your self.view.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!CGRectContainsRect(self.view.frame, imageView.frame)){
// Your animation to bounce.
}
}

keyboard hides textfield for different orientation in ipad

In my iPad application, I have few textView and textField's. When I click on textField, the keyboard covers the textField. So I am implementing the below code to move the textview up. But on rotation to portraitUpsideDown its not working fine. It slides the screen down in opposite direction. So how do I solve this problem??
-(void) animateTextField: (UITextView *) textField up: (BOOL) up
{
int txtPosition = (textField.frame.origin.y - 540);
const int movementDistance = (txtPosition < 0 ? 0 : txtPosition); // 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];
}
-(void)textViewDidBeginEditing:(UITextView *)textField
{
[self animateTextField: textField up: YES];
}
-(void)textViewDidEndEditing:(UITextView *)textField
{
[self animateTextField: textField up: NO];
}
-(BOOL)textFieldShouldReturn:(UITextView *)theTextField
{
[theTextField resignFirstResponder];
return YES;
}
This solution is for iPhone, but it considers both orientations.
You can adapt a bit and voilá:
http://cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html
Crazy,
Just add another function:
- (void) animateTextView: (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];
}
Then call it like:
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self animateTextView: textView up: YES];
}
- (void)textViewDidEndEditing:(UITextView *)textView {
[self animateTextView: textView up: NO];
}
If your method like this.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Try this. I don't know exactly. But I am trying to help you. May be x and y coordinate cannot be changed in any orientation. so try this.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(interfaceOrientation=UIInterfaceOrienationPotraitUpsideDown){
//Declare txtPos globally...
txtPos=(textField.frame.origin.y + 540);
}
if(interfaceOrientation=UIInterfaceOrienationPotrait)
{
txtPos=(textField.frame.origin.y - 540);
}
return(YES);
}
in animate method.
assign textPos to txtPosition variable..
You should use keyboard will show and will hide notification to capture keyboard event and adjust your view accordingly.
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardDidHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = CGRectGetHeight(keyboardFrame);
CGFloat animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
UIViewAnimationCurve animationCurve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIViewAnimationOptions animationOption = animationCurve << 16;
[UIView animateWithDuration:animationDuration delay:0 options:animationOption animations:^{
// adjust height using keyboardHeight
} completion:^(BOOL finished) {
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = CGRectGetHeight(keyboardFrame);
CGFloat animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
UIViewAnimationCurve animationCurve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIViewAnimationOptions animationOption = animationCurve << 16;
[UIView animateWithDuration:animationDuration delay:0 options:animationOption animations:^{
// adjust height using keyboardHeight
} completion:^(BOOL finished) {
}];
}
This blog post explains this in detail
http://charlie.cu.cc/2015/10/solution-to-the-ios-software-keyboard-cover-part-of-the-ui/

How to copy cells between tables as the pulse app

I need to copy cells between 2 table views.
I have a more-or-less working solution. However, it is not smooth, and I would love to do something similar to the pulse app reorder feeds option...
Something special in the way that pulse works, is that the reorder animation is the same as in a normal reorder of cells, but still the cell can move between tables.
This is what I have now:
- (BoardColumnView *) addColumn:(NSString *)title type:(ColumnType)type{
BoardColumnView *col = [BoardColumnView createColumn:title];
[self.columns addObject:col];
// Add a pinch gesture recognizer to the table view.
UILongPressGestureRecognizer* draggingRecognizer = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(moveActionGestureRecognizerStateChanged:)
];
draggingRecognizer.minimumPressDuration = 0.5;
draggingRecognizer.delegate = self;
[col.tableView addGestureRecognizer:draggingRecognizer];
[draggingRecognizer release];
return col;
}
#pragma mark -
#pragma mark UIGestureRecognizer Delegate/Actions
- (BOOL) gestureRecognizerShouldBegin: (UIGestureRecognizer *) gestureRecognizer
{
ALog(#"Drag detected");
return YES;
}
- (void) moveActionGestureRecognizerStateChanged: (UIGestureRecognizer *) recognizer
{
switch ( recognizer.state )
{
default:
case UIGestureRecognizerStateFailed:
// do nothing
break;
case UIGestureRecognizerStatePossible:
case UIGestureRecognizerStateCancelled:
{
ALog(#"Canceled");
[UIView beginAnimations: #"SnapBack" context: NULL];
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration: 0.5];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(finishedSnap:finished:context:)];
CGRect f = self.dragView.frame;
f.origin = _dragOriginCellOrigin;
self.dragView.frame = f;
[UIView commitAnimations];
break;
}
case UIGestureRecognizerStateEnded:
{
// move the real cell into place
[UIView beginAnimations: #"SnapToPlace" context: NULL];
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration: 0.5];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(finishedSnap:finished:context:)];
CGRect r = self.dragView.frame;//[self.content rectForItemAtIndex: _emptyCellIndex];
CGRect f = self.dragView.frame;
f.origin.x = r.origin.x + floorf((r.size.width - f.size.width) * 0.5);
f.origin.y = r.origin.y + floorf((r.size.height - f.size.height) * 0.5);
NSLog( #"Gesture ended-- moving to %#", NSStringFromCGRect(f) );
self.dragView.frame = f;
self.dragView.transform = CGAffineTransformIdentity;
self.dragView.alpha = 1.0;
[UIView commitAnimations];
break;
}
case UIGestureRecognizerStateBegan:
{
ALog(#"Start move..");
// find the cell at the current point and copy it into our main view, applying some transforms
_lastColumn = (BoardColumnView *)[(UITableView *)recognizer.view superview];
_targetColumn = _lastColumn;
if (_lastIndexPath) {
[_lastIndexPath release];
_lastIndexPath = nil;
}
_lastIndexPath = [_lastColumn.tableView indexPathForRowAtPoint:[recognizer locationInView: _lastColumn]];
UITableViewCell *sourceCell = [_lastColumn.tableView cellForRowAtIndexPath:_lastIndexPath];
CGRect frame = [_lastColumn convertRect: sourceCell.frame fromView: self.content];
self.dragView = [[[UIImageView alloc] initWithImage:[sourceCell screenshot]] autorelease];
self.dragView.opaque = YES;
self.dragView.backgroundColor = _lastColumn.backgroundColor;
self.dragView.center = [recognizer locationInView: self.view];
//self.dragView.cornerRadius = 8; // if you like rounded corners
self.dragView.layer.shadowOffset = CGSizeMake(-5, 2);
self.dragView.layer.shadowRadius = 5;
self.dragView.layer.shadowOpacity = 0.5;
[content addSubview: self.dragView];
[content bringSubviewToFront:self.dragView];
// grab some info about the origin of this cell
_dragOriginCellOrigin = frame.origin;
[UIView beginAnimations: #"" context: NULL];
[UIView setAnimationDuration: 0.2];
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
// transformation-- larger, slightly transparent
self.dragView.transform = CGAffineTransformMakeScale( 1.2, 1.2 );
self.dragView.alpha = 0.7;
[UIView commitAnimations];
/* // reload the grid underneath to get the empty cell in place
[self.content reloadItemsAtIndices: [NSIndexSet indexSetWithIndex: index]
withAnimation: AQGridViewItemAnimationNone];
*/
break;
}
case UIGestureRecognizerStateChanged:
{
// update draging cell location
self.dragView.center = [recognizer locationInView: self.view];
//Determinar sobre que columna esta flotando..
CGRect global;
if (_targetColumn) {
_targetColumn = nil;
}
for (BoardColumnView *col in self.columns) {
UITableView *table = col.tableView;
global = [table convertRect:self.dragView.frame fromView:content];
if ([table pointInside:global.origin withEvent:nil]) {
ALog([NSString stringWithFormat: #"Esta sobre la tabla %#", col.column.name]);
_targetColumn = col;
break;
}
}
if ( !_targetColumn )
{
ALog(#"Esta en zona muerta");
}
break;
}
}
}
- (void) finishedSnap: (NSString *) animationID finished: (NSNumber *) finished context: (void *) context
{
if (_targetColumn && _lastIndexPath) {
ALog(#"Moviendo a nuevo destino");
CGRect frame = [_targetColumn convertRect: self.dragView.frame fromView: self.content];
NSIndexPath *destPath = [_targetColumn.tableView indexPathForRowAtPoint: frame.origin];
[UIView beginAnimations: #"" context: NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
self.dragView.backgroundColor = _targetColumn.backgroundColor;
//Si inserta entre tareas en destino...
_lastColumn.totalRows -= 1;
_targetColumn.totalRows += 1;
[_lastColumn.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:_lastIndexPath] withRowAnimation:UITableViewRowAnimationTop];
if (destPath) {
[_targetColumn.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:destPath] withRowAnimation:UITableViewRowAnimationBottom];
} else {
[_targetColumn.tableView reloadData];
}
[UIView commitAnimations];
} else {
ALog(#"Cancelado el moviento, regresar a home");
UITableViewCell * sourceCell = [_lastColumn.tableView cellForRowAtIndexPath:_lastIndexPath];
if (sourceCell) {
[UIView beginAnimations: #"Back" context: NULL];
[UIView setAnimationCurve: UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration: 0.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
//self.dragView.transform = CGAffineTransformIdentity;
self.dragView.frame = [self.content convertRect: sourceCell.frame fromView: _lastColumn];
//self.dragView.alpha = 0.0;
[UIView commitAnimations];
}
}
}
- (void)animationDidStop:(id)animationID finished:(BOOL)flag context:(id)context {
// dismiss our copy of the cell
ALog(#"Eliminando drag view");
[self.dragView removeFromSuperview];
self.dragView = nil;
_lastColumn = nil;
_targetColumn = nil;
if (_lastIndexPath) {
_lastIndexPath = nil;
}
}
UPDATE: I've created an open source project to show my progress so far:
https://bitbucket.org/elmalabarista/dragdroptableviews

iPhone SDK: TextView, Keyboard in Landscape mode

How do I make sure that the textview is shown and the keyboard is not obscuring the textview, while in landscape.
Using UICatalog I created a TextViewController which works. In it there are two methods for calling the keyboard and making sure that textView is positioned above the keyboard. his just works great in Portrait mode.
I got the Landscape mode working, but on the textView is still being put to the top of the iPhone to compensate for the keyboard in portrait mode.
I changed the methods for showing the keyboards.
Below is the code for this methods: (I will just let see the code for show, since the hide code will be the reverse..
- (void)keyboardWillShow:(NSNotification *)aNotification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait) {
// the keyboard is showing so resize the table's height
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.height -= keyboardRect.size.height;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
} else if (orientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"Left"); // Verijderen later
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.width -= keyboardRect.size.height;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
} else if (orientation == UIInterfaceOrientationLandscapeRight){
NSLog(#"Right"); // verwijderen later.
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.width -= keyboardRect.size.width;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
}
I know that I have to change the line frame.size.height -= keyboardRect.size.height but I do not seem to get it working.
I tried frame.size.width -= keyboardRect.size.height that did not work. Losing the keyboardRect and frame all together work, however off course the keyboard obscures the textview........
I found the above code wouldn't work when in Landscape Mode on iPad
Note: I am moving all Fields, as in my case that's what i needed :-)
- (void)keyboardWillShow:(NSNotification*)aNotification {
// Only do for Landscape Mode
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation])){
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.x -= keyboardSize.height-44;
frame.origin.y -= keyboardSize.height-44;
frame.size.height += keyboardSize.height-44;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardInUse = YES;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation])){
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-44;
frame.origin.x += keyboardSize.height-44;
frame.size.height -= keyboardSize.height-44;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
}
keyboardInUse = NO;
}
If you think you need different code for the different orientations, you're doing something else wrong. Once the orientation has changed and your superview has responded, the value that needs changing should always be the frame's height.
Here is a code that I use for this purpose. It works on both iPad and iPhone is landscape and portrait modes (inspired by a code from Apple documentation):
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float offset;
if UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
offset = kbSize.height;
else
offset = kbSize.width;
[UIView animateWithDuration:0.5
animations:^{
CGRect frameTxtField = myTextField.frame;
frameTxtField.origin.y -= offset;
myTextField.frame = frameTxtField;
}
];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float offset;
if UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
offset = kbSize.height;
else
offset = kbSize.width;
[UIView animateWithDuration:0.5
animations:^{
CGRect frameTxtField = myTextField.frame;
frameTxtField.origin.y += offset;
myTextField.frame = frameTxtField;
}
];
}
Don't forget to call the registerForKeyboardNotifications method (e.g., in viewDidLoad).