J'utilise custom UITableViewCell
s dans ma UITableView
. Chacune de ces UITableViewCell
s est assez élevée et contient une UITextField
au sommet.
Lorsqu'un utilisateur appuie sur la UITextField
pour la modifier, un clavier apparaît et la UITableView
défile automatiquement de sorte que la cellule se trouve en haut de l'écran.
Le problème est que cela fait défiler la UITableView
vers le bas de la UITableViewCell
, pas vers le haut. Lorsque la UITableViewCell
est élevée et modifiée, la UITextField
est en haut de sorte que vous ne pouvez pas voir la UITextField
. Je sais comment faire défiler la UITableView
par programme, mais je ne sais pas comment désactiver ce défilement automatique pour pouvoir faire défiler la UITableView
par moi-même. Comment puis-je faire ceci?
Le comportement de défilement automatique est situé dans la fonctionnalité UITableViewController
.
Pour désactiver le défilement automatique, j'ai trouvé deux méthodes:
UITableViewController
simplement un UIViewController
- définissez vous-même la source de données et le délégué.viewWillAppear
et n'appelez pas [super viewWillAppear: animated]
Avec les deux solutions, vous désactivez non seulement le défilement automatique, mais également certaines autres fonctionnalités intéressantes, mais non essentielles, décrites dans la présentation de la référence de classe d’Apple:
https://developer.Apple.com/documentation/uikit/uitableviewcontroller
Définissez les propriétés de votre UITableViewController
:
@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;
Avant d'appeler becomeFirstResponder
:
// Save the table view's y content offset
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;
Ajoutez le code suivant à votre contrôleur de vue de table:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.scrollDisabled) {
[self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
}
...
}
Après avoir appelé resignFirstResponder
, définissez scrollDisabled = NO
.
Vous pouvez faire ce qui suit:
- (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;
});
}
Puis implémentez cette méthode UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (! self.tableView.scrollEnabled)
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}
!!! Mais soyez averti que si l'utilisateur appuie sur un emplacement du champ UITextField qui sera couvert par le clavier, il ne défilera pas.
De mon point de vue, la meilleure chose à faire est de s'assurer que toutes les cellules de haut en bas, l'une avec le UITextField inclus, seront visibles lorsque le clavier affichera.
Le problème pour moi n’était pas tant de faire défiler le texte que de faire défiler l’écran texte hors de l’écran.
Ainsi, au lieu d’empêcher le défilement, je ne fais que réinscrire la vue tableau à l’endroit où je veux lorsque la modification est déclenchée, comme ceci:
public func textViewShouldBeginEditing(textView: UITextView) -> Bool {
dispatch_async(dispatch_get_main_queue()) {
tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
}
return true
}
Malheureusement, la substitution de -viewWillAppear: ne fonctionne pas pour moi dans iOS 8.
Voici ma solution (comme dans l'implémentation UITableViewController):
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillHideNotification object:nil];
}
Étant donné que le comportement de défilement automatique est invoqué par les notifications d’affichage/masquage de UIKeyboard, ne les observez donc pas.
La meilleure méthode consiste à sous-classer UITableView
, puis à remplacer setContentOffset(_ contentOffset: CGPoint, animated: Bool)
et à ne pas appeler super.setContentOffset(_ contentOffset: CGPoint, animated: Bool)
. Dans cette méthode, le contrôleur de vue effectue le défilement automatique.
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
//Do nothing
}