Dans viewWillAppear
, j'ai ajouté UISearchBar
comme aperçu de UITableView
. Lorsque l'affichage est chargé, je cache UISearchbar
sous UINavigationBar
à l'aide de contentOffSet of UITableView
. Lorsque l'utilisateur déroule la vue de table, la barre de recherche s'affiche.
Après avoir ajouté la tête, je le cache en utilisant le code ci-dessous.
self.tableView.contentOffset = CGPointMake(0, 40); //My searhbar height is 40
Mais parfois, contentOffSet
ne se cache pas. Quelle peut être l'erreur.
Cela a fonctionné pour moi:
// contentOffset will not change before the main runloop ends without queueing it, for iPad that is
dispatch_async(dispatch_get_main_queue(), ^{
// The search bar is hidden when the view becomes visible the first time
self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchBar.bounds));
});
Mettez-le dans votre -viewDidLoad ou -viewWillAppear
Je ne sais pas quelle est la raison (je n’ai pas le temps de faire des recherches pour le moment), mais j’ai résolu ce problème en utilisant performSelector
après un délai égal à 0. Exemple:
- (void)viewWillAppear:(BOOL)animated {
...
[self performSelector:@selector(hideSearchBar) withObject:nil afterDelay:0.0f];
}
- (void)hideSearchBar {
self.tableView.contentOffset = CGPointMake(0, 44);
}
Dans les versions précédentes du SDK iOS, des méthodes telles que viewWillAppear
étaient exécutées sur le thread principal. Elles s'exécutent maintenant sur un thread en arrière-plan, ce qui explique pourquoi le problème se produit maintenant.
La plupart des callbacks ont tendance à se déclencher sur un thread d'arrière-plan. Par conséquent, vérifiez toujours que le thread est sécurisé lorsque vous effectuez des appels d'interface utilisateur.
Transmettez la modification de l'offset de contenu sur le thread principal:
Objectif c
dispatch_async(dispatch_get_main_queue(), ^{
CGPoint offset = CGPointMake(0, self.searchBar.bounds.height)
[self.tableView setContentOffset:offset animated:NO];
});
Swift 3
DispatchQueue.main.async {
let offset = CGPoint.init(x: 0, y: self.searchBar.bounds.height)
self.tableView.setContentOffset(offset, animated: false)
}
Cela a fonctionné pour moi.
self.tableView.beginUpdates()
self.tableView.setContentOffset( CGPoint(x: 0.0, y: 0.0), animated: false)
self.tableView.endUpdates()
Objectif c :
[_tableView beginUpdates];
[_tableView setContentOffset:CGPointMake(0, 0)];
[_tableView endUpdates];
Cela peut être dû à l'attribut "Adjust Scroll View Insets" sur le View Controller . Voir ceci: https://stackoverflow.com/a/22022366
EDIT: Assurez-vous de vérifier la valeur de 'contentInset' pour voir ce qui se passe, car cela a également un effet sur l'affichage de défilement . Cette valeur est modifiée après viewWillAppear: lorsque "Ajuster les incrustations de vue de défilement" , ce qui semble être ce que d’autres essaient d’éviter en utilisant des files d’attente et autres.
Dans mon cas, le problème était que j'ai appelé
[_myGreatTableView reloadData];
avant d’obtenir le _tableView.contentOffset.y
. Cela a toujours retourné '0'.
Donc je ai changé l'ordre de ces méthodes et maintenant ça marche.
Ceci est un comportement assez étrange à mon avis, car offset renvoyait 0 mais l'interface utilisateur conservait toujours la position de défilement de la table.
Après une heure de tests, la seule façon de fonctionner à 100% est la suivante:
-(void)hideSearchBar
{
if([self.tableSearchBar.text length]<=0 && !self.tableSearchBar.isFirstResponder)
{
self.tableView.contentOffset = CGPointMake(0, self.tableSearchBar.bounds.size.height);
self.edgesForExtendedLayout = UIRectEdgeBottom;
}
}
-(void)viewDidLayoutSubviews
{
[self hideSearchBar];
}
avec cette approche, vous pouvez toujours masquer la barre de recherche si est vide
Je l'ai corrigé avec layoutIfNeeded ()
self.articlesCollectionView.reloadData()
self.articlesCollectionView.layoutIfNeeded()
self.articlesCollectionView.setContentOffset(CGPoint(x: 0, y: 40), animated: false)
Le problème est le masquage automatique. Sélectionnez votre tableau et assurez-vous d'avoir sélectionné toutes les lignes, comme dans l'image ci-dessous.
La ligne de code fonctionne comme il se doit.
Explication de contentOffset
d'une UITableView
:
Par exemple, si vous avez une vue de table de hauteur 100. Son contenu peut être supérieur à sa vue, par exemple 150. contentOffset
indiquera à la table d'où le contenu doit partir. Dites contentOffset = (0, 40)
, le contenu sera affiché après 40 de sa hauteur.
Remarque: une fois le contenu défilé, la contentOffset
précédemment définie n’a aucun effet.
Dans iOS 7/8/9 simple self.automaticallyAdjustsScrollViewInsets = NO; résolu le problème dans mon cas
Le problème peut être avec la taille de la barre de recherche. Essayez la ligne de code suivante.
[searchBar sizeToFit];
Vous devez masquer vous-même la barre de recherche lorsque vous faites défiler le tableau. Donc, ne le mettez pas comme un en-tête UITableView
. Vous pouvez le cacher en réglant sa hauteur à zéro. De cette façon, si la vue de votre tableau est définie sur redimensionnement automatique, elle s’agrandira.
Si votre table aura toujours au moins une ligne, faites défiler jusqu'à la première ligne du tableau et la barre de recherche sera automatiquement masquée.
let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath (firstIndexPath, animé: false, scrollPosition: .Top)
Si vous placez le code ci-dessus sur viewDidLoad , une erreur se produira, car la tableView n'est pas encore chargée. Vous devez donc le mettre dans viewDidAppear car, à ce stade, la tableView a déjà été chargée.
Si vous le mettez sur viewDidAppear , chaque fois que vous ouvrez le tableau, il défilera vers le haut.
Peut-être que vous ne souhaitez pas ce comportement si la table reste ouverte, comme s'il s'agissait d'un contrôleur de vue UITabBar ou lorsque vous effectuez une séquence puis revenez. Si vous souhaitez simplement qu’il défile vers le haut lors du chargement initial, vous pouvez créer une variable pour vérifier s’il s’agit d’un chargement initial, de sorte qu’il ne défile qu’une seule fois vers le haut.
Commencez par définir une variable appelée isInitialLoad dans la classe du contrôleur de vue et définissez-la sur "true":
var isInitialLoad = true
Et ensuite, vérifiez si isInitialLoad est vrai sur viewDidAppear et si c'est vrai, faites défiler vers le haut et définissez la variable isInitialLoad sur false:
if isInitialLoad {
let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)
isInitialLoad = false
}