2013-02-23 80 views
19

我已經嘗試了大部分StackOverflow上的示例。我也用蘋果的。我似乎對他們的問題是,他們沒有考慮UITextField在UITableView中。我已經做了很多次,但沒有這樣做。我有一個自定義的UITableViewCell和UITextField。在常規UIViewController上的UITableViewCell中的上方滾動UITextField

在我的UITableView(不是UITableViewController)上,我需要能夠避免隱藏UITableView下的UITextField。

我有這個截至目前:

-(void)viewDidLoad 
{ 
.... 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(keyboardWillShow:) 
               name:UIKeyboardWillShowNotification 
               object:nil]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(keyboardWillHide:) 
               name:UIKeyboardWillHideNotification 
               object:nil]; 

.... 
} 

- (void)scrollToRectOfTextField { 
    UITableViewCell *cell = (UITableViewCell*)[self.activeTextField superview]; 
    CGRect r = CGRectMake(self.activeTextField.frame.origin.x, 
          cell.frame.origin.y+self.activeTextField.frame.origin.y, 
          self.activeTextField.frame.size.width, 
          self.activeTextField.frame.size.height); 
    [self.tableView scrollRectToVisible:r animated:YES]; 
} 

- (void)keyboardDidShow:(NSNotification *)notification 
{ 
    if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone) { 
     NSDictionary *userInfo = [notification userInfo]; 
     CGSize size = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; 
     NSLog(@"TableView: %@", NSStringFromCGRect(self.tableView.frame)); 
     CGRect newTableViewFrame = CGRectMake(self.tableView.frame.origin.x, 
               self.tableView.frame.origin.y, 
               self.tableView.frame.size.width, self.tableView.frame.size.height - size.height); 
     self.tableView.frame = newTableViewFrame; 
     NSLog(@"New TableView: %@", NSStringFromCGRect(self.tableView.frame)); 


     self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height-size.height); 
    } 
} 


- (void)keyboardWillHide:(NSNotification *)notification 
{ 
    NSDictionary *userInfo = [notification userInfo]; 
    CGSize size = [[userInfo objectForKey: UIKeyboardFrameEndUserInfoKey] CGRectValue].size; 
    self.tableView.frame = CGRectMake(self.tableView.frame.origin.x, 
             self.tableView.frame.origin.y, 
             self.tableView.frame.size.width, 
             self.tableView.frame.size.height + size.height); 

    NSLog(@"%@", NSStringFromCGRect(self.tableView.frame)); 
} 


-(void)textFieldDidBeginEditing 
{ 
    [self scrollToRectOfTextField]; 
} 

這似乎推了一堆空白了過去我的鍵盤。另請注意,我的UITextField上也有一個inputAccessoryView。

哦,我不能使用任何第三方類。我喜歡TPKeyboardAvoidingScrollView,但我不能使用任何第三方。

+0

當你叫'[自scrollToRectOfTextField]'? – 2013-02-23 03:00:54

+0

此外,如果您爲tableview的底部邊緣設置動畫而不是嘗試更改框架,您將獲得更平滑的動畫。 – 2013-02-23 03:01:35

+0

這是一個很好的問題。它並沒有被用在我從中拉出來的例子中。 – 2013-02-23 03:08:30

回答

49

我花了整整一天的時間來解決這個問題。我在這裏發佈了它,然後找到了一個博客鏈接和一個非常簡單的解決方案。它看起來像這樣:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField { 
    CGPoint pointInTable = [textField.superview convertPoint:textField.frame.origin toView:self.tableView]; 
    CGPoint contentOffset = self.tableView.contentOffset; 

    contentOffset.y = (pointInTable.y - textField.inputAccessoryView.frame.size.height); 

    NSLog(@"contentOffset is: %@", NSStringFromCGPoint(contentOffset)); 

    [self.tableView setContentOffset:contentOffset animated:YES]; 

    return YES; 
} 


-(BOOL)textFieldShouldEndEditing:(UITextField *)textField 
{ 
    [textField resignFirstResponder]; 

    if ([textField.superview.superview isKindOfClass:[UITableViewCell class]]) 
    { 
     UITableViewCell *cell = (UITableViewCell*)textField.superview.superview; 
     NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; 

     [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:TRUE]; 
    } 

    return YES; 
} 

Check this for iOS 8

+0

我得到它的工作,但我不得不刪除IfEndEditing的If語句。另外,如果你需要像我一樣有多個文本框,你還必須實現textFieldDidBeginEditing和textFieldDidEndEditing。只需複製並粘貼與ShouldBegin和ShouldEnd相同的代碼即可。這將允許用戶從textField跳轉到textField,同時保持相同的功能。 如果你正在努力W/NSIndexPath,這裏是一個方式,就是任意iOS版本不兼容:http://stackoverflow.com/questions/9577392/uitextfield-subview-of-uitableviewcell-get-indexpath-of-cell/ 9577406#9577406 – user1107173 2013-07-09 22:53:50

+1

不要使用superviews鏈。這不是可靠的設計。使用indexPaths和textField views標籤的字典來查找哪個文本字段是下一個響應者,並使其成爲firstResponder。 – 2015-07-15 13:00:25

+1

如果您在文本字段調用'becomeFirstResponder'而不是點擊它,則這不起作用。 – Babiker 2015-11-05 06:34:48

19

我試過@inturbidus張貼iOS8上的鏈接,但遺憾的是它並沒有爲我工作。經過一番挖掘之後,事實證明,蘋果公司在他們的網站上確實有示例代碼,以便像在UITableViewController中那樣自然地工作。這是Objective-C版本的Apple鏈接,我也在這裏添加了快速版本。從蘋果

Objective-C的鏈接(滾動到列表5-1):Objective-C的版本

var activeField: UITextField? 

func textFieldDidBeginEditing(textField: UITextField) { 
    self.activeField = textField 
} 

func textFieldDidEndEditing(textField: UITextField) { 
    self.activeField = nil 
} 

func registerForKeyboardNotifications() { 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil) 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) 
}  

func keyboardWasShown(aNotification: NSNotification) { 
    let info = aNotification.userInfo as! [String: AnyObject], 
    kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue().size, 
    contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0) 

    self.tableView.contentInset = contentInsets 
    self.tableView.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. 
    var aRect = self.view.frame 
    aRect.size.height -= kbSize.height 

    if !CGRectContainsPoint(aRect, activeField!.frame.origin) { 
     self.tableView.scrollRectToVisible(activeField!.frame, animated: true) 
    } 
} 

func keyboardWillBeHidden(aNotification: NSNotification) { 
    let contentInsets = UIEdgeInsetsZero 
    self.tableView.contentInset = contentInsets 
    self.tableView.scrollIndicatorInsets = contentInsets 
} 
+0

我沒有添加鏈接,@Hector做到了。 – 2015-08-09 14:43:11

+1

我知道這是一箇舊的答案,但我想補充任何遇到此問題的人:我的tableview沒有覆蓋整個視圖到底部,我不得不稍微糾正kbSize.height,因爲只有部分UITableView由鍵盤覆蓋。如果我使用這個解決方案,這個行滾動出UITableView並且不可見。所以這行'contentInsets = UIEdgeInsets(頂部:0,左:0,下:kbSize.height,右:0)'在'keyboardWasShow'變爲'UIEdgeInsets(頂部:0,左:0,下:kbSize.height -margin,right:0)'。 – 2017-05-09 19:40:35

6

感謝@Salman爲鏈接的https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

斯威夫特適應。
只需注意Apple視圖在正常視圖中用於滾動視圖。
在表中查看你必須點和activeField的矩形轉換爲表的座標,所以我改變功能keyboardWasShown一些行:

func keyboardWasShown(aNotification: NSNotification) { 
     let info = aNotification.userInfo as! [String: AnyObject], 
     kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue().size, 
     contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0) 

     self.tableBasket.contentInset = contentInsets 
     self.tableBasket.scrollIndicatorInsets = contentInsets 

     var aRect = self.view.frame 
     aRect.size.height -= kbSize.height 

     let pointInTable = activeField!.superview!.convertPoint(activeField!.frame.origin, toView: tableView) 
     let rectInTable = activeField!.superview!.convertRect(activeField!.frame, toView: tableView) 

     if !CGRectContainsPoint(aRect, pointInTable) { 
      self.tableView.scrollRectToVisible(rectInTable, animated: true) 
     } 
} 

而如果你的觀點有tabBarController,記住將與的TabBar高度contentInsets代替UIEdgeInsetsZero (如果沒有,你最後的底部行可能的TabBar下隱伏):

func keyboardWillBeHidden(aNotification: NSNotification) { 
     //UIEdgeInsetsZero is used in view without tabBar 
     //let contentInsets = UIEdgeInsetsZero 
     let tabBarHeight = self.tabBarController!.tabBar.frame.height 
     let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: tabBarHeight, right: 0) 
     self.tableView.contentInset = contentInsets 
     self.tableView.scrollIndicatorInsets = contentInsets 
    } 
} 
+0

謝謝。我已將代碼重寫爲Obj-C,並在使用tableview時修復了Apple代碼的問題。 – skornos 2015-10-07 11:54:59

+0

BTW:如果你正在使用self.edgesForExtendedLayout = UIRectEdgeNone那麼這裏提到 – skornos 2015-10-07 12:02:53

1

滾動的UITextField鍵盤上方的一個UITableViewCell定期迅速的UIViewController 3和Xcode的8.1 ​​

1)設置代表= UITextFieldDelegate

override func viewWillAppear(_ animated: Bool) { 

     NotificationCenter.default.addObserver(self, selector: #selector(DayViewController.keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil); 
     NotificationCenter.default.addObserver(self, selector: #selector(DayViewController.keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil); 

    } 
     func textFieldDidBeginEditing(_ textField: UITextField) { 
      self.activeField = textField 
    } 
     func textFieldDidEndEditing(_ textField: UITextField) { 
     self.activeField = nil 
    } 


//MARK: - Keyboard Show and Hide Methods 
    func keyboardWillShow(notification: NSNotification) 
    { 
     let info = notification.userInfo! as! [String: AnyObject], 
     kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue.size, 
     contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0) 

     self.FourthTblMainTableView.contentInset = contentInsets 
     self.FourthTblMainTableView.scrollIndicatorInsets = contentInsets 

     var aRect = self.FourthTblMainTableView.frame 
     aRect.size.height -= kbSize.height 
    } 
    func keyboardWillHide(notification: NSNotification) 
    { 
     let contentInsets = UIEdgeInsets.zero 
     self.FourthTblMainTableView.contentInset = contentInsets 
     self.FourthTblMainTableView.scrollIndicatorInsets = contentInsets 
    } 
4

我製成的混合物與馬特的答案,並也塞勒曼。 這適用於tableView中的許多文本字段。Swift 3

基本上是得到了BOTTOM Y點的文字輸入感動。一旦我們有,我檢查如果鍵盤覆蓋textInput,如果做到這一點,我會改變tableView的contentOffset

首先註冊通知。在init如果是一個UIView或viewDidLoad中如果是一個UIViewController:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 

然後設置文本字段觸摸作爲電流輸入

var inputActive: UITextField! 

func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { 
    inputActive = textInput 
    return true 
} 

最後執行的通知方法:

func keyboardWillShow(notification: NSNotification) { 
    var userInfo = notification.userInfo! 
    if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { 
     // Get my height size 
     let myheight = tableView.frame.height 
     // Get the top Y point where the keyboard will finish on the view 
     let keyboardEndPoint = myheight - keyboardFrame.height 
     // Get the the bottom Y point of the textInput and transform it to the currentView coordinates. 
     if let pointInTable = inputActive.superview?.convert(inputActive.frame.origin, to: tableView) { 
      let textFieldBottomPoint = pointInTable.y + inputActive.frame.size.height + 20 
      // Finally check if the keyboard will cover the textInput 
      if keyboardEndPoint <= textFieldBottomPoint { 
       tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint 
      } else { 
       tableView.contentOffset.y = 0 
      } 
     } 
    } 
} 

func keyboardWillHide(notification: NSNotification) { 
    tableView.contentOffset.y = 0 
} 

幾件事情要添加。 填充是一些額外的距離,我在我的情況下添加了20分。 另外在我的情況下,UITableView被添加到UIViewController,但是這也應該在UITableViewController中工作

希望這有助於!

+0

我認爲這將是有益的給你解釋得在你的代碼是如何工作的一點點,它正在做什麼是不需要改變keyboardWillBeHidden。 – GrumpyCrouton 2017-06-09 17:40:48

+0

@GrumpyCrouton感謝您的建議。我在代碼上添加了一些評論,並對我的工作做了一些解釋。 =] – Victor 2017-06-09 18:20:16

+1

非常感謝!你贏了upvote :) – GrumpyCrouton 2017-06-09 18:21:52

1

這個答案是Xamarin iOS用戶,但有人可以很容易地修改它,使其與雨燕或目的C.

的解決方案是非常簡單的,並已在我的情況,我需要一個細胞的工作完美工作出現在屏幕的上半部分,以便單元格的文本字段位於鍵盤上方。因此,我所做的是以下幾點:

我實現textField.ShouldBeginEditing方式如下:

myTextField.ShouldBeginEditing = textField => 
{ 
    myTableView.ScrollToRow(indexPath, UITableViewScrollPosition.Top, true); 

    return true; 
}; 

其中:

myTextField將是小區的文本字段,

myTableView是表格視圖,

indexPath是表格視圖內單元的索引路徑。

正如我前面提到的,這個解決方案在我的情況下是完美的,所以我想我可以與你們分享它,以防它對你有用。快樂編碼:)

+0

didnt工作,文本框仍然鍵盤 – kemdo 2017-11-10 08:41:30

2

我的解決方案(上的Xcode 8.3.3,斯威夫特3工作,iOS版10.3.1):

class MyTableViewController: UITableViewController { 

    override func viewWillAppear(_ animated: Bool) { 
     NotificationCenter.default.addObserver(self, selector: #selector(actionKeyboardDidShow(with:)), name: .UIKeyboardDidShow, object: nil) 
     NotificationCenter.default.addObserver(self, selector: #selector(actionKeyboardWillHide(with:)), name: .UIKeyboardWillHide, object: nil) 
    } 

    override func viewDidDisappear(_ animated: Bool) { 
     NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil) 
     NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil) 
    } 

    @objc private func actionKeyboardDidShow(with notification: Notification) { 
     guard let userInfo = notification.userInfo as? [String: AnyObject], 
      let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue 
      else { return } 

     var contentInset = self.tableView.contentInset 
     contentInset.bottom += keyboardFrame.height 

     self.tableView.contentInset = contentInset 
     self.tableView.scrollIndicatorInsets = contentInset 
    } 

    @objc private func actionKeyboardWillHide(with notification: Notification) { 
     guard let userInfo = notification.userInfo as? [String: AnyObject], 
      let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue 
      else { return } 

     var contentInset = self.tableView.contentInset 
     contentInset.bottom -= keyboardFrame.height 

     self.tableView.contentInset = contentInset 
     self.tableView.scrollIndicatorInsets = contentInset 
    } 

} 
+0

隱藏我想你想UIKeyboardFrameEndUserInfoKey在DidShow。開始是動畫開始處的框架 – Aneel 2017-11-27 14:30:04

相關問題