Situation: J'ai un UITableViewController chargeant des données de manière asynchrone à partir d'un service. Pendant ce temps, j'aimerais placer une vue plein écran (à l'exception de la barre de navigation) sur la vue tableau, affichant mon indicateur personnalisé et mon texte.
Problème: Le problème auquel je suis confronté est que lorsque ma vue personnalisée (elle a un fond rouge) est placée sur UITableView, les lignes de la vue tableau sont affichées dans ma vue personnalisée (voir image ci-dessous).
Ce que j'ai essayé: J'ai essayé d'utiliser insertBelow et supérieur, n'a pas fonctionné. J'ai également essayé de faire: tableview.Hidden = true, mais cela masque également la vue personnalisée pour une raison quelconque, comme le montre l'image 2.
Image1: Pour une raison quelconque, je peux voir les lignes jettent mon point de vue.
Image 2: Tableview + vue personnalisée disparue lorsque hidden = true utilisé.
Mon code:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
UIView view = new UIView (new RectangleF (0, 0, this.TableView.Frame.Width, this.TableView.Frame.Height));
view.BackgroundColor = UIColor.Red;
this.TableView.AddSubview (view);
TableView.Source = new SessionTableViewSource ();
}
Le problème est que la vue d'une UITableViewController
est une UITableView
, vous ne pouvez donc pas ajouter de sous-vues au contrôleur situé en haut de la table.
Je recommanderais de passer d'une UITableViewController
à une simple UIViewController
contenant une UITableView
. De cette manière, la vue principale du contrôleur est une UIView
simple contenant une table. Vous pouvez ajouter des sous-vues à la UIView
principale et elles seront placées au-dessus de la vue de la table.
Vous pouvez utiliser self.navigationController.view
comme vue pour ajouter une sous-vue.
Vous pouvez essayer d'ajouter la vue à la fenêtre au lieu de l'imbriquer dans la vue tableau comme ceci:
UIWindow* mainWindow = [[UIApplication sharedApplication] keyWindow];
[mainWindow addSubview: overlayview];
Remarque: le code ci-dessous suppose que l'on a une vue personnalisée (ratingView dans mon cas) qui doit être présentée sur une UITableView.
J'ai lu beaucoup de réponses à ceci et à des questions similaires sur SO . Les autres réponses provenant de ces sources ont fonctionné à des degrés divers pour moi (par exemple, une vue chargée mais non montrée ou non accessible, ...). J'utilise Swift 2.0+ et je partage la solution complète pour ce faire en utilisant un UITableViewController .
Créez un point de vente sur la barre de navigation et sur la vue que vous souhaitez amener par dessus la vue de table.
//MARK:Outlets
@IBOutlet weak var navBar:UINavigationBar!
@IBOutlet var ratingView: MNGStarRating!
Dans mon cas, je souhaitais également animer la vue sur la table. J'ai donc utilisé une variable de classe pour contenir une référence au point d'inflexion et un point au-dessus de la scène (hors écran).
var centerYInflection:NSLayoutConstraint!
var aPointAboveScene = -(max(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height) * 2.0)
Puis, dans viewDidLoad
, j'ai appelé une fonction (configureRatingViewAutoLayout) qui configure et ajoute les contraintes pour que la nouvelle vue soit animée sur la vue de table.
func configureRatingViewAutoLayout() {
//REQUIRED
self.navBar.superview?.addSubview(self.ratingView)
var newConstraints:[NSLayoutConstraint] = []
newConstraints.append(self.ratingView.leadingAnchor.constraintEqualToAnchor(self.view.leadingAnchor,constant: 10))
newConstraints.append(self.ratingView.trailingAnchor.constraintEqualToAnchor(self.view.trailingAnchor,constant: 10))
newConstraints.append(self.ratingView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor))
//hides the rating view above the scene
self.centerYInflection = self.ratingView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor, constant: self.aPointAboveScene)
//the priority must be set below 1000 if you intend to change it after it has been added to a view
self.centerYInflection.priority = 750
newConstraints.append(self.centerYInflection)
//constraints must be added to the container view of the two items
self.ratingView.superview?.addConstraints(newConstraints)
}
Nota Bene - Sur un UITableViewController; le self.view est le self.tableView. Ils indiquent la même chose, donc je suppose qu’on pourrait aussi Utiliser la référence de self.tableView ci-dessus.
Quelque temps plus tard ... En réponse à un événement UIControl, j'appelle cette méthode.
@IBAction func toggleRatingView (sender:AnyObject?){
//REQUIRED
self.ratingView.superview?.layoutIfNeeded()
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.37, initialSpringVelocity: 0.99, options: [.CurveEaseOut], animations: { () -> Void in
if CGRectContainsRect(self.view.frame, self.ratingView.frame) {
//in frame ~ animate away
//I play a sound to alert the user something is happening
self.centerYInflection.constant = self.aPointAboveScene
self.centerYInflection.priority = UILayoutPriority(950)
//I disable portions of the UI
self.disableUIElements(nil)
} else {
//out of frame ~ animate in
//I play a different sound here
self.centerYInflection.constant = 0
self.centerYInflection.priority = UILayoutPriority(950)
//I enable the UI fully
self.enableUIElements(nil)
}
//REQUIRED
self.ratingView.superview?.setNeedsLayout()
self.ratingView.superview?.layoutIfNeeded()
}) { (success) -> Void in
//do something else
}
}
Ces méthodes d'assistance peuvent être configurées pour contrôler l'accès aux éléments de votre scène lors de la présentation de la vue.
func disableUIElements(sender:AnyObject?) {
//UI
}
func enableUIElements(sender:AnyObject?) {
//UI
}
Mon affichage est un affichage personnalisé dans le Storyboard (assis en dehors de la vue de table Mais connecté au contrôleur TableView). La vue a un attribut required / runtime défini par
layer.zPosition
avec une valeur de Number définie sur 2 (cela garantit qu'il se présente devant le UITableView).On pourrait aussi essayer de jouer avec bringSubviewToFront: Et sendSubviewToBack: méthodes si vous ne voulez pas définir zPosition (Je pense que zPosition est plus simple à utiliser)
UIWindow* window = [[UIApplication sharedApplication].delegate.window;
[window addSubview: your-overlayview];
Essayez ceci pour accrocher un bouton au bas de la UITableViewController
déclarer le bouton en tant que variable:
var submitButton: UIButton!
et dans viewDidLoad
:
submitButton = UIButton(frame: CGRect(x: 5, y: UIScreen.main.bounds.size.height - 50, width: UIScreen.main.bounds.size.width - 10, height: 50))
submitButton.backgroundColor = UIColor.init(red: 180/255, green: 40/255, blue: 56/255, alpha: 1.0)
submitButton.setTitle("Submit", for: .normal)
submitButton.titleLabel?.font = UIFont(name: "Arial", size: 15)
submitButton.titleLabel?.textColor = .white
submitButton.addTarget(self, action: #selector(submit), for: .touchUpInside)
submitButton.layer.cornerRadius = 5
self.view.addSubview(submitButton)
et implémenter cette méthode:
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
submitButton.frame = CGRect.init(x: submitButton.frame.Origin.x, y: UIScreen.main.bounds.size.height + scrollView.contentOffset.y - 50, width: submitButton.frame.width, height: submitButton.frame.height)
}