Question Désactivation du défilement automatique de UITableView lors de la modification de UITextField dans UITableViewCell


J'utilise la coutume UITableViewCells dans mon UITableView. Chacun de ces UITableViewCells est assez élevé et contient un UITextField au sommet.

Lorsqu'un utilisateur touche le UITextField pour le modifier, un clavier apparaît et le UITableView fait défiler automatiquement pour que la cellule soit en haut de l'écran.

Le problème est que cela fait défiler le UITableView au bas de la UITableViewCell, pas le top. Quand le UITableViewCell est élevé et a édité le UITextField est en haut de sorte que vous ne pouvez pas voir le UITextField. Je sais faire défiler le UITableView par programmation, mais je ne sais pas comment désactiver ce défilement automatique pour que je puisse faire défiler le UITableView me débrouiller tout seul. Comment puis-je faire ceci?


44
2018-03-09 15:58


origine


Réponses:


Le comportement de défilement automatique est situé dans le UITableViewController fonctionnalité.

Pour désactiver le défilement automatique, j'ai trouvé deux façons:

  1. Utiliser à la place du UITableViewController simplement un UIViewController - définir la source de données et déléguer vous-même.
  2. Remplacer le viewWillAppear méthode et ne pas appeler [super viewWillAppear: animated]

Avec les deux solutions, vous désactivez non seulement le défilement automatique, mais également d'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


61
2017-08-17 18:05



Définir 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, ensemble scrollDisabled = NO.


6
2017-08-05 10:10



Vous pouvez effectuer les opérations suivantes:

- (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;
    });
}

Ensuite, 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 tape dans un emplacement de UITextField qui sera couvert par le clavier, alors 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, avec le champ UITextField inclus, seront visibles lorsque le clavier sera affiché.


3
2018-04-12 13:52



Le problème pour moi n’était pas tant le fait qu’il défilait, mais le fait que la vue du texte soit modifiée à l’écran.

Donc, au lieu d'empêcher le défilement, je ne fais que recréer la tableview là où je veux quand l'édition 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
}

1
2018-02-27 22:33



Malheureusement, le remplacement de -viewWillAppear: ne fonctionne pas pour moi dans iOS 8.

Voici ma solution (comme dans l'implémentation de 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 show / hide de UIKeyboard, il ne faut donc PAS les observer.


1
2018-04-03 07:51



Le meilleur moyen est de sous-classe UITableView et ensuite 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
}

1
2017-12-15 16:20



Avez-vous essayé de définir "scrollsToTop" - propriété de tableview sur NO. Par défaut, c'est OUI.


-2
2018-03-10 16:20