J'ajuste l'état d'un contrôleur de vue de détail, juste avant qu'il soit poussé sur une navigationController
:
[self.detailViewController detailsForObject:someObject];
[self.navigationController pushViewController:self.detailViewController
animated:YES];
Dans la DetailViewController
un scrollView réside. Quel contenu je redimensionne en fonction de l'objet transmis:
- (void)detailsForObject:(id)someObject {
// set some textView's content here
self.contentView.frame = <rect with new calculated size>;
self.scrollView.contentSize = self.contentView.frame.size;
self.scrollView.contentOffset = CGPointZero;
}
Maintenant, tout cela fonctionne, mais scrollView ajuste sa valeur contentOffset
lors de l’animation par insertion du navigateurContrôleur. La contentOffset
sera définie sur la différence entre le dernier contentSize et le nouveau calculé. Cela signifie que la deuxième fois que vous ouvrez le detailsView, les détails défileront vers un emplacement indésirable. Même si je règle la contentOffset
sur CGPointZero
explicitement.
J'ai constaté que la réinitialisation de la contentOffset
dans - viewWillAppear
n'a aucun effet. Le mieux que je puisse faire est de réinitialiser le contentOffset dans viewDidAppear
, ce qui provoque un mouvement de haut en bas notable du contenu:
- (void)viewDidAppear:(BOOL)animated {
self.scrollView.contentOffset = CGPointZero;
}
Existe-t-il un moyen d'empêcher une UIScrollView
d'ajuster sa contentOffset
lorsque sa contentSize
est modifiée?
Se produit lors du transfert d'une UIViewController
contenant une UIScrollView
à l'aide d'une UINavigationController
.
IOS 7
_ {Solution 1 (Code)} _
Définissez @property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets
sur NO
.
_ {Solution 2 (Storyboard))
Décocher le Adjust Scroll View Insets
iOS 6
Solution (Code)} _
Définissez les propriétés UIScrollView
de contentOffset
et contentInset
dans viewWillLayoutSubviews
. Exemple de code:
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.scrollView.contentOffset = CGPointZero;
self.scrollView.contentInset = UIEdgeInsetsZero;
}
La cause de ce problème reste incertaine, bien que j'ai trouvé une solution. En réinitialisant la taille du contenu et le décalage avant de les ajuster, UIScrollView ne s'animera pas:
- (void)detailsForObject:(id)someObject {
// These 2 lines solve the issue:
self.scrollView.contentSize = CGSizeZero;
self.scrollView.contentOffset = CGPointZero;
// set some textView's content here
self.contentView.frame = <rect with new calculated size>;
self.scrollView.contentSize = self.contentView.frame.size;
self.scrollView.contentOffset = CGPointZero;
}
J'ai eu le même problème avec un UIScrollview, où le problème était causé par la non définition de contentSize. Après avoir défini contentSize sur le nombre d'éléments, ce problème a été résolu.
self.headerScrollView.mainScrollview.contentSize = CGSizeMake(320 * self.sortedMaterial.count, 0);
J'ai rencontré le problème et, dans un cas précis - je ne modifie pas la taille - j'ai utilisé les éléments suivants:
float position = 100.0;//for example
SmallScroll.center = CGPointMake(position + SmallScroll.frame.size.width / 2.0, SmallScroll.center.y);
Idem fonctionnerait avec y: anotherPosition + SmallScroll.frame.size.height / 2.0
Donc, si vous n'avez pas besoin de redimensionner, c'est une solution rapide et sans douleur.
Je rencontrais un problème similaire, où UIKit définissait le contentOffset de mon scrollView lors des animations Push.
Aucune de ces solutions ne fonctionnait pour moi, peut-être parce que je prenais en charge iOS 10 et iOS 11.
J'ai pu résoudre mon problème en sous-classant mon scrollview pour empêcher UIKit de modifier mes décalages une fois que le scrollview avait été supprimé de la fenêtre:
/// A Scrollview that only allows the contentOffset to change while it is in the window hierarchy. This can keep UIKit from resetting the `contentOffset` during transitions, etc.
class LockingScrollView: UIScrollView {
override var contentOffset: CGPoint {
get {
return super.contentOffset
}
set {
if window != nil {
super.contentOffset = newValue
}
}
}
}
ScrollView est-il la vue racine du DetailViewController? Si c'est le cas, essayez d'encadrer scrollView dans une UIView
plaine et faites de cette dernière la vue racine de DetailViewController. Étant donné que UIView
s n'a pas de propriété contentOffset
, ils sont immunisés contre les réglages de décalage de contenu effectués par le contrôleur de navigation (en raison de la barre de navigation, etc.).