2012-01-02 73 views
36

我知道这个问题一再被问过,但没有任何东西似乎对我有用。大部分的解决方案都是过时的,其余的都是非常大的代码块,比实际的项目编码大十倍。我有一些垂直排列的UITextFields,但是当键盘启动编辑一个时,它会覆盖文本字段。我想知道是否有一个简单的初学者的方式来滚动视图,然后在编辑开始和结束时退后?如何在键盘出现时向上滚动视图?

谢谢。

+0

的可能重复[如何使一个的UITextField向上移动时,键盘的存在(http://stackoverflow.com/questions/1126726/how-to-make-a-uitextfield-move-up-when -keyboard-is-present) – 2012-01-03 01:51:34

回答

28

我已经制定了解决方案,使用滚动和非滚动视图使用键盘通知和检测当前第一响应者,但有时我使用这个微不足道的解决方案:简单的方法是通过文本检测开放键盘现场代表的textViewDidBeginEditing:方法并向上移动整个视图。最简单的方法是沿着将self.view.bounds.origin.y更改为-100(或其他)的方法。使用相应的textViewShouldEndEditing:方法将其设置为相反,在这种情况下为100。更改bounds是一个相对的过程。改变它后,框架移动,但边界原点仍为零。

+6

谢谢。这是我到目前为止的代码:' - (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

+1

np。在方法的末尾添加'return YES;'来表示你允许编辑。不要忘记将此类设置为该文本视图的代表。如果你需要的话,有一个叫做“textFieldDidBeginEditing:”的UITextFieldDelegates的相应方法。 – 2012-01-03 00:10:55

+0

太棒了,这个伎俩,非常感谢。但还有一个问题,我如何将该类设置为该文本视图的代表?对不起,如果它是一个愚蠢的问题哈哈。 – John 2012-01-03 00:31:02

24

因为我发现它,我使用TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding

这是伟大的工作,而且非常易于安装:

  • 添加UIScrollView到您的视图控制器的XIB
  • 设置滚动视图类TPKeyboardAvoidingScrollView(依然在厦门国际银行,通过身份检查)
  • 将所有的滚动视图中的控件

您也可以通过编程创建它,如果你想。


UITableViewController里面有同样需要的类;只有在您支持4.3以下版本的iOS时才需要。

+0

很酷,谢谢,我现在就试试这个。这可能是一个愚蠢的问题,但我已经设置了笔尖,将在笔尖顶部添加一个滚动视图来搞乱它? (我也在图像视图中设置了背景) – John 2012-01-02 23:18:38

+0

只需将视图添加到笔尖,然后将其他元素移动到视图中。您的所有元素属性(IBOutlet,配置)将保留。如果你搞砸了,取消最后一步(或恢复到你最近的提交!) – Guillaume 2012-01-02 23:26:05

+0

如果库由Micheal Tyson完成,那么我正在使用它。简单。 – abbood 2013-08-12 08:10:52

-1

我在这里有一个滚动视图和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 
1

我花了一段时间在这个问题上并聚集件代码来创建一个最终方案。我的问题与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); 
     } 
    } 
0

如果你有一个UITableViewUIScrollView它更好地改变值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方法。


我应该不需要这么说,但是这个工作你UITextFieldUITextView必须是你的控制器的委托

3

谁面临的功能问题@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]; 
} 
0

从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 
     }) 
    } 
} 
相关问题