可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using custom UITableViewCell
s inside my UITableView
. Each of these UITableViewCell
s is pretty high and contains a UITextField
at the top.
When a user taps the UITextField
in order to edit it, a keyboard appears and the UITableView
scrolls automatically so that the cell is at the top of the screen.
The problem is that this scrolls the UITableView
to the bottom of the UITableViewCell
, not the top. When the UITableViewCell
is high and edited the UITextField
is at the top so you can't see the UITextField
. I know how to scroll the UITableView
programmatically, but I just don't know how to disable this automatic scrolling so that I can scroll the UITableView
on my own. How can I do this?
回答1:
The autoscroll-behavior is located in the UITableViewController
functionality.
To disable the automatic scrolling I found two ways:
- Use instead of the
UITableViewController
simply a UIViewController
- set the datasource and delegate on your own.
- Override the
viewWillAppear
method and don't call [super viewWillAppear: animated]
With both solution you disable not only the Autoscroll, but also some other nice but not essential features, that are described in the overview of Apple´s class reference:
https://developer.apple.com/documentation/uikit/uitableviewcontroller
回答2:
Define properties for your UITableViewController
:
@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;
Before you call becomeFirstResponder
:
// Save the table view's y content offset
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;
Add the following code to your table view controller:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.scrollDisabled) {
[self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
}
...
}
After you call resignFirstResponder
, set scrollDisabled = NO
.
回答3:
You can do the following:
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification object:nil];
}
- (void)unregisterForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
self.tableView.scrollEnabled = NO;
}
- (void)keyboardDidShow:(NSNotification *)notification
{
double delayInSeconds = 0.3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
self.tableView.scrollEnabled = YES;
});
}
Then implement this UIScrollViewDelegate method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (! self.tableView.scrollEnabled)
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
!!! But be warned, that if the user taps in a location in the UITextField that will be covered by the Keyboard, then it won't scroll.
From my point of view, the best thing to do is to make sure that all the cells from top to then one with the UITextField included, will be visible when then Keyboard will show.
回答4:
The issue for me was not so much that it scrolled but that it took the text view being edited off the screen.
So instead of preventing the scrolling, I just rescroll the tableview to where I want when the editing is triggered, like this:
public func textViewShouldBeginEditing(textView: UITextView) -> Bool {
dispatch_async(dispatch_get_main_queue()) {
tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
}
return true
}
回答5:
Unfortunately, overriding -viewWillAppear: doesn't work for me in iOS 8.
Here is my solution (as in UITableViewController implementation):
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillHideNotification object:nil];
}
Since the auto-scrolling behaviour is invoked by UIKeyboard's show/hide notifications, so just NOT observe them.
回答6:
The best way is to subclass UITableView
and then override setContentOffset(_ contentOffset: CGPoint, animated: Bool)
and not to call super.setContentOffset(_ contentOffset: CGPoint, animated: Bool)
. In this method is where the view controller is doing the automatic scroll.
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
//Do nothing
}
回答7:
Did you try to set "scrollsToTop" - tableview's property to NO. By default it is YES.
回答8:
You can try doing the following:
self.tableView.scrollEnabled = NO;
This should disable the scrollview in the tableview.