web-dev-qa-db-fra.com

Ajouter une vue sur une table (UITableViewController)

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.

See lines

Image1: Pour une raison quelconque, je peux voir les lignes jettent mon point de vue.

Hidden true

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 ();
    }
13
Mittchel

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.

31
redent84

Vous pouvez utiliser self.navigationController.view comme vue pour ajouter une sous-vue.

40
sagus_helgy

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];
3
jonas vermeulen

Solution rapide/scénarimage

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

}

Mises en garde

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)

 2

 3

2
Tommie C.
UIWindow* window = [[UIApplication sharedApplication].delegate.window;
[window addSubview: your-overlayview];
2
jianpx

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)
}
1
Sh_Khan