经过大量的试验和错误,我放弃了,并提出了这个问题。我见过很多人有类似的问题,但不能得到所有的答案工作正确。
我有一个由自定义单元格组成的UITableView。单元格由相邻的5个文本字段组成(有点像网格)。
当我试图滚动和编辑UITableView底部的单元格时,我不能设法让我的单元格正确地定位在键盘上方。
我看到过很多关于改变视图大小的回答……但到目前为止,没有一种效果很好。
谁能用一个具体的代码示例来阐明这样做的“正确”方式?
经过大量的试验和错误,我放弃了,并提出了这个问题。我见过很多人有类似的问题,但不能得到所有的答案工作正确。
我有一个由自定义单元格组成的UITableView。单元格由相邻的5个文本字段组成(有点像网格)。
当我试图滚动和编辑UITableView底部的单元格时,我不能设法让我的单元格正确地定位在键盘上方。
我看到过很多关于改变视图大小的回答……但到目前为止,没有一种效果很好。
谁能用一个具体的代码示例来阐明这样做的“正确”方式?
当前回答
键盘通知可以工作,但苹果的示例代码假设滚动视图是窗口的根视图。通常情况并非如此。您必须补偿标签栏等,以获得正确的偏移量。
这比听起来容易。下面是我在UITableViewController中使用的代码。它有两个实例变量,hiddenRect和keyboardshow。
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification {
if (keyboardShown)
return;
NSDictionary* info = [aNotification userInfo];
// Get the frame of the keyboard.
NSValue *centerValue = [info objectForKey:UIKeyboardCenterEndUserInfoKey];
NSValue *boundsValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGPoint keyboardCenter = [centerValue CGPointValue];
CGRect keyboardBounds = [boundsValue CGRectValue];
CGPoint keyboardOrigin = CGPointMake(keyboardCenter.x - keyboardBounds.size.width / 2.0,
keyboardCenter.y - keyboardBounds.size.height / 2.0);
CGRect keyboardScreenFrame = { keyboardOrigin, keyboardBounds.size };
// Resize the scroll view.
UIScrollView *scrollView = (UIScrollView *) self.tableView;
CGRect viewFrame = scrollView.frame;
CGRect keyboardFrame = [scrollView.superview convertRect:keyboardScreenFrame fromView:nil];
hiddenRect = CGRectIntersection(viewFrame, keyboardFrame);
CGRect remainder, slice;
CGRectDivide(viewFrame, &slice, &remainder, CGRectGetHeight(hiddenRect), CGRectMaxYEdge);
scrollView.frame = remainder;
// Scroll the active text field into view.
CGRect textFieldRect = [/* selected cell */ frame];
[scrollView scrollRectToVisible:textFieldRect animated:YES];
keyboardShown = YES;
}
// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
// Reset the height of the scroll view to its original value
UIScrollView *scrollView = (UIScrollView *) self.tableView;
CGRect viewFrame = [scrollView frame];
scrollView.frame = CGRectUnion(viewFrame, hiddenRect);
keyboardShown = NO;
}
其他回答
我可能错过了这一点,因为我没有阅读整篇文章,但我想到的似乎很简单。我并没有在所有情况下进行测试,但它看起来应该工作得很好。
简单地根据键盘的高度调整tableview的contentInset,然后将单元格滚动到底部:
- (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);
self.myTableView.contentInset = contentInsets;
self.myTableView.scrollIndicatorInsets = contentInsets;
[self.myTableView scrollToRowAtIndexPath:self.currentField.indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
当然
- (void)keyboardWasHidden:(NSNotification *)aNotification
{
[UIView animateWithDuration:.3 animations:^(void)
{
self.myTableView.contentInset = UIEdgeInsetsZero;
self.myTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}];
}
这是不是太简单了?我遗漏了什么吗?到目前为止,它对我来说还不错,但就像我说的,我还没有把它经过折腾……
执行滚动的函数可以简单得多:
- (void) textFieldDidBeginEditing:(UITextField *)textField {
UITableViewCell *cell;
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
// Load resources for iOS 6.1 or earlier
cell = (UITableViewCell *) textField.superview.superview;
} else {
// Load resources for iOS 7 or later
cell = (UITableViewCell *) textField.superview.superview.superview;
// TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Cell!
}
[tView scrollToRowAtIndexPath:[tView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
就是这样。根本不需要计算。
我在做一些非常相似的事情它是通用的,不需要为你的代码计算特定的东西。 只需检查代码上的注释:
在MyUIViewController.h
@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableView *myTableView;
UITextField *actifText;
}
@property (nonatomic, retain) IBOutlet UITableView *myTableView;
@property (nonatomic, retain) IBOutlet UITextField *actifText;
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField;
- (IBAction)textFieldDidEndEditing:(UITextField *)textField;
-(void) keyboardWillHide:(NSNotification *)note;
-(void) keyboardWillShow:(NSNotification *)note;
@end
在MyUIViewController.m
@implementation MyUIViewController
@synthesize myTableView;
@synthesize actifText;
- (void)viewDidLoad
{
// Register notification when the keyboard will be show
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
// Register notification when the keyboard will be hide
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
// To be link with your TextField event "Editing Did Begin"
// memoryze the current TextField
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
self.actifText = textField;
}
// To be link with your TextField event "Editing Did End"
// release current TextField
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
self.actifText = nil;
}
-(void) keyboardWillShow:(NSNotification *)note
{
// Get the keyboard size
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];
// Detect orientation
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = self.myTableView.frame;
// Start animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
// Reduce size of the Table view
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
frame.size.height -= keyboardBounds.size.height;
else
frame.size.height -= keyboardBounds.size.width;
// Apply new size of table view
self.myTableView.frame = frame;
// Scroll the table view to see the TextField just above the keyboard
if (self.actifText)
{
CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];
[self.myTableView scrollRectToVisible:textFieldRect animated:NO];
}
[UIView commitAnimations];
}
-(void) keyboardWillHide:(NSNotification *)note
{
// Get the keyboard size
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];
// Detect orientation
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = self.myTableView.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
// Increase size of the Table view
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
frame.size.height += keyboardBounds.size.height;
else
frame.size.height += keyboardBounds.size.width;
// Apply new size of table view
self.myTableView.frame = frame;
[UIView commitAnimations];
}
@end
Swift 1.2+版本:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var activeText: UITextField!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("keyboardWillShow:"),
name: UIKeyboardWillShowNotification,
object: nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("keyboardWillHide:"),
name: UIKeyboardWillHideNotification,
object: nil)
}
func textFieldDidBeginEditing(textField: UITextField) {
activeText = textField
}
func textFieldDidEndEditing(textField: UITextField) {
activeText = nil
}
func keyboardWillShow(note: NSNotification) {
if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
var frame = tableView.frame
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.3)
frame.size.height -= keyboardSize.height
tableView.frame = frame
if activeText != nil {
let rect = tableView.convertRect(activeText.bounds, fromView: activeText)
tableView.scrollRectToVisible(rect, animated: false)
}
UIView.commitAnimations()
}
}
func keyboardWillHide(note: NSNotification) {
if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
var frame = tableView.frame
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(0.3)
frame.size.height += keyboardSize.height
tableView.frame = frame
UIView.commitAnimations()
}
}
}
我将把我的解决方案(或者QuickDialog的)扔进帽子里。基本上是等待动画到滚动。获得键盘动画JIT而不是神奇的数字会很好。
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if (textField == self.emailTextField) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 50 * USEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
});
}
}
我尝试了几乎相同的方法,并提出了一个更简单、更小的代码。 我创建了一个IBOutlet iTextView,并与IB中的UITextView相关联。
-(void)keyboardWillShow:(NSNotification *)notification
{
NSLog(@"Keyboard");
CGRect keyFrame = [[[notification userInfo]objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];
[UIView beginAnimations:@"resize view" context:nil];
[UIView setAnimationCurve:1];
[UIView setAnimationDuration:1.0];
CGRect frame = iTableView.frame;
frame.size.height = frame.size.height - keyFrame.size.height;
iTableView.frame = frame;
[iTableView scrollRectToVisible:frame animated:YES];
[UIView commitAnimations];
}