I have several UITextField in a scrollView,
and I custom textFields' border by setting
layer.borderColor = ...,
layer.borderRadius = 3.0,
layer.borderWidth = 0.1,
layer.masksToBounds = YES.
- (void)keyboardWillShow:(NSNotification *)notification {
CGFloat animDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect rect = [self.currentTextField superview].frame;
[UIView animateWithDuration:animDuration animations:^{
[self.scrollView scrollRectToVisible:rect animated:NO];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
CGFloat animDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect rect = [self.currentTextField superview].frame;
[UIView animateWithDuration:animDuration animations:^{
[self.scrollView scrollRectToVisible:rect animated:NO];
}];
}
Bug every time I got any textField focused or dismiss the keyboard, all the textfield's border flashes. But if I just scroll the scrollView no flashes
I finally find the resolution.
Use the CoreAnimation rasteraztion, toggle the textField's layer's shouldRasterize to true: textField.layer.shouldRasterize = true
and set the scale: textField.layer.rasterizationScale = UIScreen.mainScreen().scale
shouldRasterize instructs CoreAnimatin to cache the layer contents as an image. You then get rid off the flashing.
To avoid any unnecesary caching, you should turn off rasterization as soon as the animation is done.
The whole code is like:
- (void)keyboardWillShow:(NSNotification *)notification {
CGRect keyboardRectEnd = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat animDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect rect = [self.currentTextField superview].frame;
self.scrollViewBottomConstraint.constant = keyboardRectEnd.size.height;
[self toggleTextFieldRasterization:YES];
[UIView animateWithDuration:animDuration animations:^{
[self.scrollView scrollRectToVisible:rect animated:NO];
[self layoutIfNeeded];
} completion: ^(BOOL finished) {
[self toggleTextFieldRasterization:NO];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
CGFloat animDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect rect = [self.currentTextField superview].frame;
self.scrollViewBottomConstraint.constant = 0.0;
[self toggleTextFieldRasterization:YES];
[UIView animateWithDuration:animDuration animations:^{
[self.scrollView scrollRectToVisible:rect animated:NO];
[self layoutIfNeeded];
} completion:^(BOOL finished) {
[self toggleTextFieldRasterization:NO];
}];
}
- (void)toggleTextFieldRasterization:(BOOL)toggle {
CGFloat scale = UIScreen.mainScreen.scale;
self.textField1.layer.shouldRasterize = toggle;
self.textField1.layer.rasterizationScale = scale;
self.textField2.layer.shouldRasterize = toggle;
self.textField2.layer.rasterizationScale = scale;
self.textField3.layer.shouldRasterize = toggle;
self.textField3.layer.rasterizationScale = scale;
}
Related
I have implemented chat function in my iOS app using websocket, and it's working fine for me.
The problem is i want to increase the height of the UITextView, and the UITableView should move up according to the height of the UITextView increase. Can anyone help me?
Below is my code which i'm using in my application:
- (void)viewDidAppear:(BOOL)animated
{
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication]delegate];
[super viewDidAppear:animated];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[self.messagesTextView addGestureRecognizer:tgr];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
CGRect endFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIViewAnimationCurve curve = [note.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
UIViewAnimationOptions options = curve << 16;
[UIView animateWithDuration:duration delay:0.0 options:options animations:^{
NSLog(#"frame: %#", NSStringFromCGRect(endFrame));
CGRect frame = self.txtView.frame;
if (isMsgLong==TRUE) {
frame.origin.y = self.view.frame.size.height- CGRectGetHeight(self.txtView.frame)-216;
}
else {
frame.origin.y = CGRectGetMinY(endFrame) - CGRectGetHeight(self.txtView.frame);
}
self.txtView.frame = frame;
CGRect frame1 = self.sendButton.frame;
frame1.origin.y = CGRectGetMinY(endFrame) - CGRectGetHeight(self.sendButton.frame);
self.sendButton.frame = frame1;
frame = self.messagesTextView.frame;
frame.size.height = CGRectGetMinY(self.txtView.frame) - CGRectGetMinY(frame);
self.messagesTextView.frame = frame;
NSLog(#"did appear: %#", NSStringFromCGRect(self.txtView.frame));
} completion:nil];
}];
}
- (void)keyboardWillShow:(NSNotification *)note
{
[UIView animateWithDuration:0.3 animations:^{
NSDictionary *info = note.userInfo;
NSValue *value = info[UIKeyboardFrameEndUserInfoKey];
CGRect rawFrame = [value CGRectValue];
CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil];
NSLog(#"frame: %#", NSStringFromCGRect(self.txtView.frame));
self.txtView.transform = CGAffineTransformMakeTranslation(0, -keyboardFrame.size.height);
self.sendButton.transform = CGAffineTransformMakeTranslation(0, -keyboardFrame.size.height);
self.messagesTableView.contentInset=UIEdgeInsetsMake(0, 0,keyboardFrame.size.height,0);
//keyboardFrame.size.height
NSLog(#"frame1: %#", NSStringFromCGRect(self.txtView.frame));
isMsgLong = FALSE;
}];
}
- (void)keyboardWillHide:(NSNotification *)note
{
[UIView animateWithDuration:0.3 animations:^{
NSLog(#"frame2: %#", NSStringFromCGRect(self.txtView.frame));
self.txtView.transform = CGAffineTransformIdentity;
NSLog(#"frame3: %#", NSStringFromCGRect(self.txtView.frame));
self.sendButton.transform = CGAffineTransformIdentity;
self.messagesTableView.transform = CGAffineTransformIdentity;
isMsgLong = TRUE;
}];
}
-(void)textViewDidEndEditing:(UITextView *)textView
{
self.messagesTableView.contentInset=UIEdgeInsetsMake(0, 0, 0, 0);
self.txtView.transform = CGAffineTransformMakeTranslation(0, -216);
self.sendButton.transform = CGAffineTransformMakeTranslation(0, -216);
NSLog(#"frame5: %#", NSStringFromCGRect(self.txtView.frame));
NSInteger lastSectionIndex = [self.messagesTableView numberOfSections] - 1;
NSInteger lastRowIndex = [self.messagesTableView numberOfRowsInSection:lastSectionIndex] - 1;
if (lastRowIndex==-1) {
lastRowIndex=0;
}
NSIndexPath *pathToLastRow = [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex];
if (lastRowIndex==0) {
}
else {
[self.messagesTableView scrollToRowAtIndexPath:pathToLastRow atScrollPosition:UITableViewScrollPositionBottom animated:NO];
//UITableViewScrollPositionMiddle
}
}
This works for both iOS 6.1 and iOS 7 and if you are using Objective C you can use this Code:
- (void)textViewDidChange:(UITextView *)textView
{
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
textView.frame = newFrame;
}
Or if you'r using Swift use this:
let fixedWidth = textView.frame.size.width
textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = textView.frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
textView.frame = newFrame;
If you want support for iOS 6.1 then you should also do this as well:
textview.scrollEnabled = NO;
i am using this code for zooming this is perfect but i want zoomout after this zoomin.
CGFloat s = 3;
CGPoint p = CGPointMake(150, 300);
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
self.view.transform = tr;
CGFloat cx = w/2-s*(p.x-w/2);
CGFloat cy = h/2-s*(p.y-h/2);
self.view.center = CGPointMake(cx, cy); //was: (w*s/2,h-h*s/2);
} completion:^(BOOL finished) {}];
Try using hitTest and scroll view delegate method i.e, viewForZoomingInScrollView as follows.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return yourScrollView;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return yourImageView;
}
You can set the selected image in another scrollview and handle the zoom.
- (void)setImage:(UIImage *)image {
[self.imageView setImage:image];
[self.imageView sizeToFit];
//add this image view as subview of scroll view here and set content size accordingly.
CGFloat zoomScale = 1.0;
if (self.imageView.frame.size.width < self.imageView.frame.size.height) {
zoomScale = (self.scrollView.frame.size.width / self.imageView.frame.size.width);
} else {
zoomScale = (self.scrollView.frame.size.height / self.imageView.frame.size.height);
}
[self.scrollView setContentSize:self.imageView.frame.size];
[self.scrollView setMinimumZoomScale:zoomScale];
[self.scrollView setMaximumZoomScale:1.0];
[self.scrollView setZoomScale:zoomScale];
[self.scrollView setContentOffset:CGPointMake((self.imageView.frame.size.width - self.scrollView.frame.size.width) / 2,
(self.imageView.frame.size.height - self.scrollView.frame.size.height) / 2)];
}
I just want to make the UITextField to go up when keyboard was presented. I achieved it by setting the frame of UITextField after keyboard was presented. It is working for ordinary cases. But, if user enabled prediction in default keyboard then predictive text area gets placed above the UITextField. In that case I want the text field to move up. I tried setting inputAccessoryView of textfield. But app crashed with no report .So how can I set inputAccessoryView of textfield to achieve my requirement.
textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 0, bottomToolbarView.frame.size.width, bottomToolbarView.frame.size.height)];
textField.delegate = self;
textField.textAlignment = NSTextAlignmentCenter;
textField.inputAccessoryView = bottomToolbarView;
[textField setReturnKeyType:UIReturnKeyGo];
[textField setPlaceholder:#"Enter Employee Id"];
[textField setBackgroundColor:[UIColor colorWithRed:1.000 green:0.720 blue:0.611 alpha:1.000]];
[bottomToolbarView addSubview:textField];
try this code in textfield Did Begin Editing delegate method
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];
& on didEndEditing delegate method
-(void)textFieldDidEndEditing:(UITextField *)textField1
{
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];
}
This question already has answers here:
How can I make a UITextField move up when the keyboard is present - on starting to edit?
(98 answers)
Closed 9 years ago.
I have created a form in IOS using scrollview with some text fields. the view looks like this,
When I begin to edit either state or below fields, the keyboard hides that field. like this,
what should i do to see the below fields (i.e., state and below)??
You can try this code
Add following code at top of your viewcontroller.m file
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 = 162;
CGFloat animatedDistance;
Inside textFieldShouldBeginEditing
-(BOOL) textFieldShouldBeginEditing:(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];
return YES;
}
Inside textFieldShouldEndEditing
- (BOOL) textFieldShouldEndEditing:(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];
}
You should definitely search for this in stack-overflow itself, before posting a question. Anyways, you can find the answer here.
Conform to protocol UITextFieldDelegate
Have a BOOL variable moved to signal, whether your view is moved or not.
Then implement the delegate methods.
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if(!moved) {
[self animateViewToPosition:self.view directionUP:YES];
moved = YES;
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
[textField resignFirstResponder];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
if(moved) {
[self animateViewToPosition:self.view directionUP:NO];
}
moved = NO;
return YES;
}
-(void)animateViewToPosition:(UIView *)viewToMove directionUP:(BOOL)up {
const int movementDistance = -60; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? movementDistance : -movementDistance);
[UIView beginAnimations: #"animateTextField" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
viewToMove.frame = CGRectOffset(viewToMove.frame, 0, movement);
[UIView commitAnimations];
}
You need to use TPAvoidingKeyBoard Library into your app your problem is solved..
https://github.com/michaeltyson/TPKeyboardAvoiding
See this link. Download this project and add it into your project.
Then first you have to add scrollview to your view and then all your textfield into that scrollview add that TPAvoidingScrollView To Custom Class.
Your code is good. but you have to change UIScrollView y position instead of height. I have change your code and update. please update this
step 1: In the ViewDidLoad method of your class set up to listen for messages about the keyboard:
// Listen for keyboard appearances and disappearances
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
step 2: up/down your scrollview by implementing selector methods in same class
- (void)keyboardDidShow: (NSNotification *) notif{
//Keyboard becomes visible
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y - 220,
scrollView.frame.size.width,
scrollView.frame.size.height); //move up
}
- (void)keyboardDidHide: (NSNotification *) notif{
//keyboard will hide
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y + 220,
scrollView.frame.size.width,
scrollView.frame.size.height); //move down
}
Try this code
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField==tfLocation)
{
[self.view setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-50, self.view.frame.size.width, self.view.frame.size.height)];
}
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self.view setFrame:CGRectMake(self.view.frame.origin.x, 0, self.view.frame.size.width, self.view.frame.size.height)];
}
I have several buttons located at different sites in the view (storyboard), and I want that when I click on each of them to go to a given point,
To do this, I keep their location and initial size by:
CGPoint originalCenter1;
CGRect originalsize1;
CGPoint originalCenter2;
CGRect originalsize2;
in viewDidLoad
originalCenter1 = self.boton1.center;
originalsize1 = self.boton1.frame;
originalCenter2 = self.boton2.center;
originalsize2 = self.boton2.frame;
and the IBAction associated with each button, the animation ...
-(IBAction)move:(id)sender{
UIButton * pressedbutton = (UIButton*)sender;
[UIView animateWithDuration:3.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform scale = CGAffineTransformMakeScale(3.0, 3.0);
pressedbutton.transform = scale;
switch(pressedbutton.tag)
{
case 0:
pressedbutton.center = CGPointMake(784, 340);
break;
case 1:
pressedbutton.center = CGPointMake(784, 340);
break;
When already all have moved, I have a button Refresh that puts me to the initial position.
-(IBAction)refresh:(id)sender{
self.boton1.frame = originalsize1;
self.boton1.center = originalCenter1;
self.boton1.alpha=1;
self.boton2.frame = originalsize2;
self.boton2.center = originalCenter2;
self.boton2.alpha=1;
The problem is that the next time that pulse buttons, move to the position shown in the animation but the "scale" effect, doesn't work !!
Any help ??
Thanks.
I think you should use block try this...
- (IBAction)tap:(UITapGestureRecognizer *)gesture
{
CGPoint tapLocation = [gesture locationInView:self.view1];
for (UIView *view in self.view1.subviews) {
if (CGRectContainsPoint(view.frame, tapLocation)) {
[UIView animateWithDuration:5.0 animations:^{
[self setRandomLocationForView:view];
}];
}
}
}
- (void)setRandomLocationForView:(UIView *)view
{
[view sizeToFit];
CGRect sinkBounds = CGRectInset(self.view1.bounds, view.frame.size.width/2, view.frame.size.height/2);
CGFloat x = your location.x;
CGFloat y = yout location.y;
view.center = CGPointMake(x, y);
}