如何在键盘出现时向上滚动视图?
我知道这个问题一再被问过,但没有任何东西似乎对我有用。大部分的解决方案都是过时的,其余的都是非常大的代码块,比实际的项目编码大十倍。我有一些垂直排列的UITextFields,但是当键盘启动编辑一个时,它会覆盖文本字段。我想知道是否有一个简单的初学者的方式来滚动视图,然后在编辑开始和结束时退后?如何在键盘出现时向上滚动视图?
谢谢。
我已经制定了解决方案,使用滚动和非滚动视图使用键盘通知和检测当前第一响应者,但有时我使用这个微不足道的解决方案:简单的方法是通过文本检测开放键盘现场代表的textViewDidBeginEditing:
方法并向上移动整个视图。最简单的方法是沿着将self.view.bounds.origin.y
更改为-100(或其他)的方法。使用相应的textViewShouldEndEditing:
方法将其设置为相反,在这种情况下为100。更改bounds
是一个相对的过程。改变它后,框架移动,但边界原点仍为零。
谢谢。这是我到目前为止的代码:' - (BOOL)textViewDidBeginEditing:(UITextField *)textField {UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -100; [self.view setFrame:frame]; [UIView commitAnimations]; '但是我得到一个警告,说“控制达到非无效功能的结束”。我不知道如何解决这个问题,对不起,我仍然是这方面的初学者。 – John 2012-01-02 23:15:19
np。在方法的末尾添加'return YES;'来表示你允许编辑。不要忘记将此类设置为该文本视图的代表。如果你需要的话,有一个叫做“textFieldDidBeginEditing:”的UITextFieldDelegates的相应方法。 – 2012-01-03 00:10:55
太棒了,这个伎俩,非常感谢。但还有一个问题,我如何将该类设置为该文本视图的代表?对不起,如果它是一个愚蠢的问题哈哈。 – John 2012-01-03 00:31:02
因为我发现它,我使用TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding。
这是伟大的工作,而且非常易于安装:
- 添加
UIScrollView
到您的视图控制器的XIB - 设置滚动视图类
TPKeyboardAvoidingScrollView
(依然在厦门国际银行,通过身份检查) - 将所有的滚动视图中的控件
您也可以通过编程创建它,如果你想。
在UITableViewController
里面有同样需要的类;只有在您支持4.3以下版本的iOS时才需要。
我在这里有一个滚动视图和3个文本字段。我有一个简单的代码从我自己的应用程序:
h文件是:
#import <UIKit/UIKit.h>
@interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate>
@property (nonatomic, retain) NSDictionary *dict_contactDetail;
@property (nonatomic, retain) IBOutlet UILabel *lbl_name;
@property (nonatomic, retain) IBOutlet UITextField *txtField_tel;
@property (nonatomic, retain) IBOutlet UITextField *txtField_address;
@property (nonatomic, retain) IBOutlet UITextField *txtField_email;
@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
@end
.m文件:
#import "AddContactViewController.h"
@interface AddContactViewController()
@end
@implementation AddContactViewController
@synthesize dict_contactDetail;
@synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// NSLog(@"dict_contactDetail : %@", dict_contactDetail);
UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonSystemItemDone target:self action:@selector(addEmergencyContact:)];
self.navigationItem.rightBarButtonItem = rightButton;
lbl_name.text = [NSString stringWithFormat:@"%@ %@", [dict_contactDetail valueForKey:@"fname"], [dict_contactDetail valueForKey:@"lname"]];
txtField_tel.returnKeyType = UIReturnKeyDone;
txtField_email.returnKeyType = UIReturnKeyDone;
txtField_address.returnKeyType = UIReturnKeyDone;
}
-(void)addEmergencyContact:(id)sender
{
scrollView.frame = CGRectMake(0, 0, 320, 460);
}
#pragma mark - text field delegates
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if([textField isEqual:txtField_tel])
{
[scrollView setContentOffset:CGPointMake(0, 70)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
if([textField isEqual:txtField_address])
{
[scrollView setContentOffset:CGPointMake(0, 140)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
if([textField isEqual:txtField_email])
{
[scrollView setContentOffset:CGPointMake(0, 210)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
scrollView.frame = CGRectMake(0, 0, 320, 460);
[textField resignFirstResponder];
return YES;
}
@end
我花了一段时间在这个问题上并聚集件代码来创建一个最终方案。我的问题与UITableView滚动和键盘打开/关闭有关。
你需要在你的类中的两个分部方法:
void EditingBegin(UITextField sender)
{
// Height of tallest cell, you can ignore this!
float tableMargin = 70.0f;
float tableHeight = _tableView.Frame.Size.Height;
float keyBoardHeight = KeyboardHeight();
NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows;
RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section);
RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section);
float lastCellY = rectLast.Y - rectFirst.Y;
if (lastCellY > tableHeight - keyBoardHeight)
{
float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
}
float cellPosition = this._tableView.RectForSection(this._section).Y;
if (cellPosition > tableHeight - keyBoardHeight)
{
if (this._tableView.ContentInset.Bottom == 0.0f)
{
float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
}
else
{
this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true);
}
}
}
partial void EditingEnd(UITextField sender)
{
UIView.BeginAnimations(null);
UIView.SetAnimationDuration(0.3f);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f);
UIView.CommitAnimations();
}
,然后在您的视图控制器类:
public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
{
base.WillAnimateRotation(toInterfaceOrientation, duration);
float bottom = this.TableView.ContentInset.Bottom;
if (bottom > 0.0f)
{
if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown)
{
bottom = bottom * UIScreen.MainScreen.Bounds.Width/UIScreen.MainScreen.Bounds.Height;
}
else
{
bottom = bottom * UIScreen.MainScreen.Bounds.Height/UIScreen.MainScreen.Bounds.Width;
}
UIEdgeInsets insets = this.TableView.ContentInset;
this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f);
}
}
如果你有一个UITableView
或UIScrollView
它更好地改变值contentOffset
而不是对frame
进行更改。
工作Peter's Answer,添加此方法类工作得很好:
- (void)textViewDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGPoint offset = self.tableView.contentOffset;
offset.y += 200; // You can change this, but 200 doesn't create any problems
[self.tableView setContentOffset:offset];
[UIView commitAnimations];
}
就是这样,没有必要添加textViewDidEndEditing
方法。
我应该不需要这么说,但是这个工作你UITextField
或UITextView
必须是你的控制器的委托。
谁面临的功能问题@BenLu和其他用户永远不会获取调用是因为以下原因: 作为委托inbuild功能bydefaults返回void而不是布尔,这是应该的,如下所示:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = -100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = 100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
从Peter的回答开始,我在Swift 3.0的iOS 10.1下开发了以下方法。我为textView做了这个,所以我实现了UITextViewDelegate函数textViewDidBeginEditing和textViewDidEndEditing,我在这里调整视图的边界。如您所见,我将原点Y值设置为较小的正数以向上滚动,然后返回0以返回原始位置。
这是我的ViewController的相关代码。你不需要动画,但它增加了一个很好的接触。
func textViewDidBeginEditing(_ textView: UITextView)
{
if UIScreen.main.bounds.height < 568 {
UIView.animate(withDuration: 0.75, animations: {
self.view.bounds.origin.y = 60
})
}
}
func textViewDidEndEditing(_ textView: UITextView)
{
if UIScreen.main.bounds.height < 568 {
UIView.animate(withDuration: 0.75, animations: {
self.view.bounds.origin.y = 0
})
}
}
的可能重复[如何使一个的UITextField向上移动时,键盘的存在(http://stackoverflow.com/questions/1126726/how-to-make-a-uitextfield-move-up-when -keyboard-is-present) – 2012-01-03 01:51:34