J'essaie d'avoir une barre de navigation transparente dans IOS 7 app. Il y a une image plein écran dans mon application. J'ai également un UITableView sur cette image. Quand j'utilise le code ci-dessous, l'image s'adapte à l'écran comme je le veux mais UITableView passe sous la barre de navigation.
dans viewDidLoad
j'utilise
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
self.navigationController.view.backgroundColor = [UIColor clearColor];
ça va aller quand je change pour self.navigationController.navigationBar.translucent = NO;
mais je perds la transparence au niveau de la barre de navigation.
Vous pouvez définir les contentInsets de votre tableView de manière à ce qu'il se trouve initialement sous la barre de navigation, mais défilerait derrière (le contenu se chevaucherait)
self.tableView.contentInset = UIEdgeInsetsMake(44,0,0,0);
Ou vous pouvez décaler le cadre de la tableview. Ensuite, le contenu défilant serait coupé en dessous de la barre de navigation (ce qui ne serait pas très beau aussi)
Mon cas a aidé celui-ci (version modifiée du code de Bill Chan):
Version de l'objectif C:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect rect = self.navigationController.navigationBar.frame;
float y = rect.size.height + rect.Origin.y;
self.tableView.contentInset = UIEdgeInsetsMake(y, 0, 0, 0);
}
Le fait est que la table doit être abaissée à la hauteur de navigationBar (rect.size.height
) plus la hauteur de la barre d’état (rect.Origin.y
);
Version Swift (également compatible avec Swift 2):
override func viewDidLayoutSubviews() {
if let rect = self.navigationController?.navigationBar.frame {
let y = rect.size.height + rect.Origin.y
self.tableView.contentInset = UIEdgeInsetsMake( y, 0, 0, 0)
}
}
J'ai eu le même problème avec iOS 9. Lorsque j'ai ouvert ViewController pour la première fois, tableView se trouvait sous la barre supérieure. Ensuite, après avoir fait défiler le tableau, tout fonctionne correctement.
Définissez la position y de la vue table à la hauteur de la barre de navigation et à la hauteur de la barre d'état (soit height
)
c'est à dire,
height = 64; // height of navigation bar = 44(In portait), height of status bar = 20
tableView.frame = CGRectMake(tableView.frame.Origin.x, height , tableView.frame.size.width, tableView.frame.size.height);
Si vous utilisez autolayout, changez simplement la mise à jour de la contrainte tableView top au lieu de changer de cadre.
et changez automatiquement viewControllerAdjustsScrollViewInsets en NO
self.automaticallyAdjustsScrollViewInsets = NO;
Si vous prenez en charge différents cadres de mise à jour d'orientation et contentInset à (52), car la hauteur de la barre de navigation en mode paysage est 32.
vérifier ceci échantillon
Cela fonctionne à la fois en mode paysage et en mode portrait dans iOS8:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect rect = self.navigationController.navigationBar.frame;
float y = -rect.Origin.y;
self.tableView.contentInset = UIEdgeInsetsMake(y ,0,0,0);
}
Mieux vaut ne pas coder en dur les valeurs Inset car elles pourraient être basées sur l’orientation du périphérique.
Code:
func setTableViewContentInset() {
let contentInsetHeight = topLayoutGuide.length
let contentInset = UIEdgeInsetsMake(contentInsetHeight, 0, 0, 0)
tableView.contentInset = contentInset
tableView.scrollIndicatorInsets = contentInset
}
func scrollToTop() {
if tableView.indexPathsForVisibleRows?.count > 0 {
let topIndexPath = NSIndexPath(forRow: 0, inSection: 0)
tableView.scrollToRowAtIndexPath(topIndexPath, atScrollPosition: .Top, animated: false)
}
}
func scrollToTopOfVisibleCells() {
if let visibleIndexPaths = tableView.indexPathsForVisibleRows where tableView.indexPathsForVisibleRows?.count > 0 {
let topMostVisibleIndexPath = visibleIndexPaths[0]
tableView.scrollToRowAtIndexPath(topMostVisibleIndexPath, atScrollPosition: .Top, animated: false)
}
}
//MARK: Load Views
override func viewDidLoad() {
super.viewDidLoad()
setTableViewContentInset()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
scrollToTop()
}
//MARK: Trait collection change
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
setTableViewContentInset()
scrollToTopOfVisibleCells()
}
La plupart du temps, les solutions qui introduisent une constante magique ne sont pas adaptées. Par exemple, si le prochain iPhone introduit une hauteur de barre de navigation différente, nous devrons mettre à jour notre code.
Heureusement, Apple nous a fourni des moyens plus clairs de résoudre ce problème, par exemple topLayoutGuide :
La propriété topLayoutGuide entre en jeu lorsqu'un contrôleur de vue est à l'avant-plan à l'écran. Il indique la plus grande étendue verticale du contenu que vous ne souhaitez pas afficher derrière une barre UIKit transparente ou translucide (telle qu'une barre d'état ou de navigation).
Par programmation, vous pouvez obtenir l’extrait de code suivant (vous pouvez également obtenir ce résultat via IB):
override func viewDidLoad() {
super.viewDidLoad()
automaticallyAdjustsScrollViewInsets = false
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.topAnchor.constraint(equalTo:
topLayoutGuide.bottomAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
Remarque: topLayoutGuide est obsolète dans iOS 11, nous devrions plutôt utiliser la propriété safeAreaLayoutGuide de UIView.
Je suis novice en développement iOS et Stack Overflow, alors pardonnez-moi si mon message n’est pas parfait.
Je connaissais aussi ce problème et, lorsque j’utilisais les encarts de contenu de mon UITableView, il fonctionnait parfaitement lors du premier chargement ou lors de la visite à partir de mes autres onglets; Cependant, si je revenais à la vue, elle aurait le "rembourrage" supplémentaire. J'ai trouvé un moyen de contourner le problème pour que mon UITableView soit correctement placé à chaque fois.
Lorsque vous chargez pour la première fois UITableView, ou un onglet, des incrustations sont nécessaires pour que le tableau démarre correctement sous la barre de navigation, mais lorsque vous revenez en arrière, il n’a pas besoin des incrustations car, pour une raison quelconque, il calcule correctement le placement des éléments. le UITableView. C'est pourquoi vous pouvez obtenir un rembourrage supplémentaire.
La solution consiste à utiliser un booléen pour déterminer si vous avez navigué, afin qu'il puisse déterminer correctement s'il a besoin des incrustations de contenu ou non.
Dans -(void)viewDidLoad
je règle hasNavigatedFurther = NO
. Ensuite:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (!hasNavigatedFurther) {
self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
} else {
self.tableView.contentInset = UIEdgeInsetsZero;
//In order to allow visiting between tabs and retaining desired look
hasNavigatedFurther = NO;
}
}
Pour que cela fonctionne, vous devez définir hasNavigatedFurther = YES
juste avant votre code qui insère une autre vue dans la pile de navigation.
-(void)btnTouched:(id)sender {
hasNavigatedFurther = YES;
NextViewController* nvc = [NextViewController new];
[self.navigationController pushViewController:nvc animated:YES];
}
Seul ce code résout le problème:
@IBOutlet weak var tableView: UITableView!
func viewDidLoad() {
super.viewDidLoad()
self.tableView.contentInset = UIEdgeInsetsZero
}
Je suis arrivé avec la solution suivante, qui, lors de la navigation vers le contrôleur de vue pour la première fois, ajuste le contentInset
de la vue de la table à la hauteur de la barre de navigation, en prenant en compte le remplissage éventuel de la cellule supérieure. Lorsque je retourne à ce contrôleur de vue après avoir placé un autre contrôleur de vue sur la pile, je réajuste ensuite le contentInset
à UIEdgeInsetsZero
:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self adjustEdgeInsetsForTableView];
}
- (void)adjustEdgeInsetsForTableView {
if(self.isMovingToParentViewController) {
self.tableViewForm.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height + padding, 0, 0, 0);
} else {
self.tableViewForm.contentInset = UIEdgeInsetsZero;
}
}
Contraindre la vue tableau au bas de la barre de navigation. La vue de la table sera automatiquement compensée par 44, mais dans le code, nous pouvons simplement faire ceci:
tableView.contentInset = UIEdgeInsets(top: -44, left: 0, bottom: 0, right: 0)
La barre est transparente et n'a pas de couleur, mais la vue sous forme de tableau ne la chevauche pas du tout. Remarquez que le mot "crochet" est coupé bien que la barre de navigation soit transparente. Cela ne fonctionnera que si vous contraignez le bord supérieur de la vue du tableau à 0 dans la barre de navigation. PAS 0 de la vue de dessus.
J'ai combiné les solutions de @Adam Farrell et @Tash Pemhiwa, et finalement le code ci-dessous fonctionne pour moi:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self adjustEdgeInsetsForTableView];
}
- (void)adjustEdgeInsetsForTableView
{
if(self.isMovingToParentViewController) {
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
} else {
self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
}
}
J'espère que cela aidera les personnes qui perdent quelques heures sur ce comportement étrange de l'assurance-chômage.