web-dev-qa-db-fra.com

UITableView contentOffSet ne fonctionne pas correctement

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.

19
JiteshW

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

28
maz

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);
}
19
deRonbrown

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)
        }
17
Matthew Cawley

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];
3
Kishor

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.

2
techniao

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. 

2
Mexx

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

2
Kappe

Je l'ai corrigé avec layoutIfNeeded ()

    self.articlesCollectionView.reloadData()
    self.articlesCollectionView.layoutIfNeeded()
    self.articlesCollectionView.setContentOffset(CGPoint(x: 0, y: 40), animated: false)
1
Blank

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. 

enter image description here

0
Dhara

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.

0

Dans iOS 7/8/9 simple self.automaticallyAdjustsScrollViewInsets = NO; résolu le problème dans mon cas

0
Saumil Shah

Le problème peut être avec la taille de la barre de recherche. Essayez la ligne de code suivante.

[searchBar sizeToFit];
0
uranpro

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.

0
parilogic

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
}
0
drdrdrdr