119 votes

Comportement bizarre uitableview dans iOS11. Cellules défilement vers le haut avec une animation de pousser de navigation

J'ai récemment migré un peu de code pour la nouvelle iOS beta 11 5 SDK.

Maintenant, je reçois un très déroutant comportement de UITableView. La tableview lui même n'est pas de fantaisie. J'ai personnalisé les cellules, mais dans la plupart, c'est juste pour leur hauteur.

Quand je pousse mon point de vue contrôleur avec tableview je obtenir un supplément d'animation où les cellules "faites défiler vers le haut" (ou éventuellement l'ensemble de la tableview image est modifiée) et descendre le long de push/pop de navigation de l'animation. Veuillez voir le gif:

wavy tableview

J'ai créer manuellement tableview en loadView méthode et de configuration automatique des contraintes de mise en forme pour être égale à la pointe, derrière, en haut, en bas de la tableview de superview. Le superview est la racine de vue de vue-contrôleur.

- Vue-contrôleur de pousser code est très standard: self.navigationController?.pushViewController(notifVC, animated: true)

Le même code prévoit un comportement normal sur iOS 10.

Pourriez-vous svp me pointer dans la direction de ce qui est mal?

EDIT: j'ai fait un très simple tableview contrôleur et je peux reproduire le même comportement là. Code:

class VerySimpleTableViewController : UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel?.text = String(indexPath.row)
        cell.accessoryType = .disclosureIndicator

        return cell
    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        let vc = VerySimpleTableViewController.init(style: .grouped)

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

EDIT 2: j'ai pu étroit question à ma personnalisation de UINavigationBar. J'ai une personnalisation comme ceci:

rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)

createFilledImage crée de la place de l'image avec la taille et la couleur.

Si je commente cette ligne je revenir à un comportement normal.

Je vous serais reconnaissant de toute réflexion sur ce sujet.

153voto

Maggy Hillen Points 1576

Cela est dû à l' UIScrollView's (UITableView est une sous-classe de UIScrollview) nouvelle - contentInsetAdjustmentBehavior de la propriété, qui est fixé à l' .automatic par défaut.

Vous pouvez remplacer ce comportement avec l'extrait de code suivant dans le viewDidLoad de toutes les contrôleurs:

    tableView.contentInsetAdjustmentBehavior = .never

https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior

23voto

Lal Krishna Points 5552

En plus de la réponse de maggy

OBJECTIVE-C

if (@available(iOS 11.0, *)) {
    scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}

Ce problème a été causé par un bug dans iOS 11, où l' safeAreaInsetsde le point de vue du contrôleur de la vue ont été définies de manière incorrecte lors de la navigation la transition, qui doit être fixé dans iOS 11.2. Réglage de la contentInsetAdjustmentBehavior de .never n'est pas une bonne solution parce qu'il aura probablement d'autres effets secondaires indésirables. Si vous ne utiliser une solution de rechange, assurez-vous de le retirer pour les versions d'iOS >= 11.2

-mentionné par smileyborg (Ingénieur Logiciel chez Apple)

6voto

BigDanceMouse Points 69

Vous pouvez modifier ce comportement à la fois tout au long de l’application à l’aide de NSProxy en didFinishLaunchingWithOptions par exemple :

6voto

Santa Claus Points 4237

Voici comment j'ai réussi à résoudre ce problème tout en permettant iOS 11 pour régler les encarts automatiquement. Je suis l'aide d' UITableViewController.

  • Sélectionnez l'option "Étendre les bords sous les barres du haut" et "Étendre les bords sous opaque bars" dans votre vue-contrôleur dans le storyboard (ou par programmation). La zone de sécurité encarts empêchera votre point de vue de passer sous la barre du haut.
  • Cochez la case "Encarts de la Zone de Sécurité" bouton sur votre table dans votre storyboard. (ou tableView.insetsContentViewsToSafeArea = true) - Cela pourrait ne pas être nécessaire, mais c'est ce que j'ai fait.
  • Définir le contenu de l'encart de l'ajustement du comportement de Défilement Axes" (ou tableView.contentInsetAdjustmentBehavior = .scrollableAxes) - .always peut également travailler mais je n'ai pas tester.

Une autre chose à essayer si tout le reste échoue:

Remplacer viewSafeAreaInsetsDidChange UIViewController méthode pour obtenir l'affichage de la table de travail mis en défilement de la vue encarts de la zone de sécurité des encarts. Ceci est en liaison avec le "Jamais", dans les Maggy de réponse.

- (void)viewSafeAreaInsetsDidChange {
    [super viewSafeAreaInsetsDidChange];
    self.tableView.contentInset = self.view.safeAreaInsets;
}

Remarque: self.tableView et self.view devrait être la même chose pour UITableViewController

3voto

El Horrible Points 98

Cela ressemble plus à un bug qu'un comportement intentionnel. Cela se produit lorsque la barre de navigation n'est pas translucide ou lorsque l'arrière-plan de l'image est réglé.

Si vous venez de définir contentInsetAdjustmentBehavior pour .jamais, le contenu des encarts ne sera pas réglé correctement sur iPhone X, par exemple, le contenu serait aller dans le fond de la zone, sous les barres de défilement.

Il est nécessaire de faire deux choses:
1. prévenir le scrollView animation sur push/pop
2. conserver .comportement automatique car il est nécessaire pour iPhone X. Sans cela par exemple dans le portrait, contenu aller au-dessous du bas de la barre de défilement.

Nouvelle solution simple: dans XIB: il suffit d'ajouter de nouvelles UIView sur le dessus de votre écran principal avec le haut, attaque et de fuite de superview et la hauteur à 0. Vous n'avez pas à le connecter à d'autres sous-vues ou quoi que ce soit.

Vieille solution:

Remarque: Si vous utilisez UIScrollView en mode paysage, il n'est toujours pas réglé horizontale encarts correctement(un autre bug?), donc, vous devez pin scrollView leader/suiveur de safeAreaInsets de l'IB.

Note 2: la Solution ci-dessous a un problème que si tableView défile vers le bas, et vous poussez contrôleur et de la pop de retour, il ne sera pas au fond plus.

override func viewDidLoad()
{
    super.viewDidLoad()

    // This parts gets rid of animation when pushing
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .never
    }
}

override func viewDidDisappear(_ animated: Bool)
{
    super.viewDidDisappear(animated)
    // This parts gets rid of animation when popping
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .never
    }
}

override func viewDidAppear(_ animated: Bool)
{
    super.viewDidAppear(animated)
    // This parts sets correct behaviour(insets are correct on iPhone X)
    if #available(iOS 11, *)
    {
        self.tableView.contentInsetAdjustmentBehavior = .automatic
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X