web-dev-qa-db-fra.com

Changer la hauteur de UITableView de manière dynamique

Je souhaite modifier la hauteur de ma vue de table à partir d'un autre contrôleur de vue en fonction de la somme des hauteurs de ses cellules, car elles sont dynamiques. Est-ce possible? Merci

Ajouter:

Ce que j'ai fondamentalement, c'est un UserProfileViewController qui a un aperçu sur la moitié de l'écran. J'ajoute ici d'autres contrôleurs de vue:

enter image description here

enter image description here

Dans le cas du bouton mural, voici comment j'ajoute le contrôleur de vue et sa vue de table suivante:

- (IBAction)wallButtonPressed:(id)sender
{
    //Check if there is an instance of the viewcontroller we want to display. If not make one and set it's tableview frame to the container's view bounds
    if(!_userWallViewController) {
        self.userWallViewController = [[WallViewController alloc] init];
//        self.userWallViewController.activityFeedTableView.frame = self.containerView.bounds;

    }

    [self.userWallViewController.containerView addSubview:self.userWallViewController.activityFeedTableView];
    //If the currentviewcontroller adn it's view are already added to the hierarchy remove them
    [self.currentViewController.view removeFromSuperview];
    [self.currentViewController removeFromParentViewController];

    //Add the desired viewcontroller to the currentviewcontroller
    self.currentViewController = self.userWallViewController;

    //Pass the data needed for the desired viewcontroller to it's instances
    self.userWallViewController.searchURLString = [NSString stringWithFormat:@"event/user/%@/", self.userID];
    self.userWallViewController.sendCommentURLString = [NSString stringWithFormat:@"event/message/%@", self.userID];

    [self.userWallViewController.activityFeedTableView reloadData];

    self.userWallViewController.totalCellHeight = ^(float totalCellHeight){

        self.scrollView.contentSize = CGSizeMake(320.0, totalCellHeight);
        CGRect newFrame = self.userWallViewController.containerView.frame;
        newFrame.size.height = totalCellHeight + 33.0;
        self.userWallViewController.containerView.frame = newFrame;

        self.userWallViewController.activityFeedTableView.frame = self.containerView.bounds;
    };

    //Add this containerview to the desired viewcontroller's containerView
    self.userWallViewController.containerView = self.containerView;


    //Add the needed viewcontroller and view to the parent viewcontroller and the containerview
    [self addChildViewController:self.userWallViewController];
    [self.containerView addSubview:self.userWallViewController.view];

    //CLEAN UP THE CONTAINER VIEW BY REMOVING THE PREVIOUS ADDED TABLE VIEWS
    [self.userFansViewController.userSimpleTableView removeFromSuperview];
    [self.fanOfViewController.userSimpleTableView removeFromSuperview];
    [self.userPublishedMovellaListViewController.gridView removeFromSuperview];

    [self.userPublishedMovellaListViewController removeFromParentViewController];

    self.userPublishedMovellaListViewController = nil;
}

et dans ce contrôleur de vue, c’est là que j’initialise ma tableview:

-(UITableView *)activityFeedTableView
{
    if (!_activityFeedTableView) {
        _activityFeedTableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 850.0) style:UITableViewStylePlain];
    }
    return _activityFeedTableView;
}

Je calcule la somme totale de la hauteur de la cellule. Le problème est que la méthode de la hauteur de la cellule est appelée chemin après l'appel du getter de la tableview. Il me faudrait donc un moyen de savoir quand la méthode de la hauteur des cellules est effectuée pour toutes les cellules et ensuite, je peux redimensionner ma vue de table. Merci

62
alex

Il n’existe pas de fonction système permettant de modifier la hauteur de la table en fonction du contenu de la vue de table. Cela dit, il est possible de modifier par programme la hauteur de la vue table en fonction du contenu, plus précisément en fonction du contentSize de la vue table (ce qui est plus facile que de calculer manuellement la hauteur vous-même). Quelques-uns des détails varient selon que vous utilisez ou non le nouvel autolayout intégré à iOS 6.

Mais en supposant que vous configuriez le modèle sous-jacent de votre vue table dans viewDidLoad, si vous souhaitez ensuite ajuster la hauteur de la vue table, vous pouvez le faire dans viewDidAppear:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [self adjustHeightOfTableview];
}

De même, si vous effectuez un reloadData (ou ajoutez ou supprimez des lignes) pour une table, assurez-vous d’appeler manuellement adjustHeightOfTableView, par exemple:

- (IBAction)onPressButton:(id)sender
{
    [self buildModel];
    [self.tableView reloadData];

    [self adjustHeightOfTableview];
}

La question est donc de savoir ce que notre adjustHeightOfTableview devrait faire. Malheureusement, cela dépend du fait que vous utilisiez l'autolayout iOS 6 ou non. Vous pouvez déterminer si l'autolayout est activé en ouvrant votre storyboard ou votre NIB et en accédant à "Inspecteur de fichier" (par exemple, appuyez sur option+command+1 ou cliquez sur le premier onglet du panneau à droite):

enter image description here

Supposons une seconde que l'autolayout soit désactivé. Dans ce cas, c'est assez simple et adjustHeightOfTableview ajusterait simplement le frame de la tableview:

- (void)adjustHeightOfTableview
{
    CGFloat height = self.tableView.contentSize.height;
    CGFloat maxHeight = self.tableView.superview.frame.size.height - self.tableView.frame.Origin.y;

    // if the height of the content is greater than the maxHeight of
    // total space on the screen, limit the height to the size of the
    // superview.

    if (height > maxHeight)
        height = maxHeight;

    // now set the frame accordingly

    [UIView animateWithDuration:0.25 animations:^{
        CGRect frame = self.tableView.frame;
        frame.size.height = height;
        self.tableView.frame = frame;

        // if you have other controls that should be resized/moved to accommodate
        // the resized tableview, do that here, too
    }];
}

Cependant, si votre autolayout était activé, adjustHeightOfTableview ajusterait une contrainte de hauteur pour votre vue de table:

- (void)adjustHeightOfTableview
{
    CGFloat height = self.tableView.contentSize.height;
    CGFloat maxHeight = self.tableView.superview.frame.size.height - self.tableView.frame.Origin.y;

    // if the height of the content is greater than the maxHeight of
    // total space on the screen, limit the height to the size of the
    // superview.

    if (height > maxHeight)
        height = maxHeight;

    // now set the height constraint accordingly

    [UIView animateWithDuration:0.25 animations:^{
        self.tableViewHeightConstraint.constant = height;
        [self.view setNeedsUpdateConstraints];
    }];
}

Pour que cette dernière solution basée sur des contraintes fonctionne avec l'autolayout, nous devons tout d'abord prendre en compte quelques éléments:

  1. Assurez-vous que votre table a une contrainte de hauteur en cliquant sur le bouton central dans le groupe de boutons ici, puis choisissez d'ajouter la contrainte de hauteur:

    add height constraint

  2. Ajoutez ensuite un IBOutlet pour cette contrainte:

    add IBOutlet

  3. Veillez à ajuster les autres contraintes afin qu'elles ne soient pas en conflit si vous ajustez la taille de la table par programme. Dans mon exemple, la table avait une contrainte d'espace de fuite qui la verrouillait au bas de l'écran. Je devais donc l'ajuster de sorte que, plutôt que d'être verrouillée à une taille particulière, elle puisse être supérieure ou égale à une valeur. avec une priorité plus basse, de sorte que la hauteur et le haut de la tableview gouverne le jour:

    adjust other constraints

    Ce que vous ferez ici avec d'autres contraintes dépendra entièrement des autres contrôles que vous avez sur votre écran, sous la vue de table. Comme toujours, composer avec des contraintes est un peu délicat, mais cela fonctionne sans aucun doute, même si les détails de votre situation dépendent entièrement de ce que vous avez sur la scène. Mais j'espère que vous avez l'idée. En bout de ligne, avec autolayout, veillez à ajuster vos autres contraintes (le cas échéant) de manière à ce qu'elles soient flexibles pour tenir compte de la hauteur de la vue de table changeante.

Comme vous pouvez le constater, il est beaucoup plus facile d’ajuster par programme la hauteur d’une table si vous n’utilisez pas la lecture automatique, mais dans le cas contraire, je présente les deux alternatives.

174
Rob

créez votre cellule par xib ou storyboard. donne le contenu de sa sortie. maintenant appelez-le dans CellForRowAtIndexPath. par exemple. si vous souhaitez définir la hauteur de la cellule en fonction du texte de l'étiquette du commentaire. enter image description here

alors définissez vous commentsLbl.numberOfLine = 0;enter image description here

alors définissez vous commentsLbl.numberOfLine = 0;

puis dans ViewDidLoad

 self.table.estimatedRowHeight = 44.0 ;
self.table.rowHeight = UITableViewAutomaticDimension;

et maintenant

-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;}
20
Mohit tomar

Beaucoup de réponses ici n'honorent pas les changements de table ou sont beaucoup trop compliquées. Utiliser une sous-classe de UITableView qui définira correctement intrinsicContentSize est une solution beaucoup plus simple lorsque vous utilisez autolayout. Aucune contrainte de hauteur, etc. nécessaire.

class UIDynamicTableView: UITableView
{
    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return CGSize(width: UIViewNoIntrinsicMetric, height: self.contentSize.height)
    }

    override func reloadData() {
        super.reloadData()
        self.invalidateIntrinsicContentSize()
    }
} 

Définissez la classe de votre TableView sur UIDynamicTableView dans le générateur d'interface et observez la magie de ce tableau car sa taille changera après un appel à reloadData().

10
LimeRed

Cela peut être massivement simplifié avec une seule ligne de code dans viewDidAppear:

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        tableViewHeightConstraint.constant = tableView.contentSize.height
    }
7
Justin Vallely

La solution de Rob est très gentille, seule chose qui dans sa méthode -(void)adjustHeightOfTableview appelle l'appel de

[self.view needsUpdateConstraints]

ne fait rien, il retourne simplement un drapeau, appelant plutôt

[self.view setNeedsUpdateConstraints]

fera l'effet désiré.

5
Csaba

Utiliser un code simple et facile

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        let myCell = tableView.dequeueReusableCellWithIdentifier("mannaCustumCell") as! CustomCell
        let heightForCell = myCell.bounds.size.height;

        return heightForCell;
    }
3
Maninderjit Singh

pour redimensionner ma table, j’ai opté pour cette solution dans mon contrôleur tableview qui convient parfaitement:

[objectManager getObjectsAtPath:self.searchURLString
                         parameters:nil
                            success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                                NSArray* results = [mappingResult array];
                                self.eventArray = results;
                                NSLog(@"Events number at first: %i", [self.eventArray count]);
                                CGRect newFrame = self.activityFeedTableView.frame;
                                newFrame.size.height = self.cellsHeight + 30.0;
                                self.activityFeedTableView.frame = newFrame;

                                self.cellsHeight = 0.0;

                            }
                            failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                                                message:[error localizedDescription]
                                                                               delegate:nil
                                                                      cancelButtonTitle:@"OK"
                                                                      otherButtonTitles:nil];
                                [alert show];
                                NSLog(@"Hit error: %@", error);
                            }];

La partie de redimensionnement est dans une méthode, mais voici juste pour que vous puissiez le voir. Maintenant, le seul problème que je rencontre est le redimensionnement de la vue de défilement dans l’autre contrôleur de vue, car je ne sais pas du tout quand la vue de la table a fini de redimensionner. Pour le moment, je le fais avec performSelector: afterDelay: mais ce n'est vraiment pas une bonne façon de le faire. Des idées?

2
alex

J'ai trouvé l'ajout de contraintes par programmation beaucoup plus facile que dans le storyboard.

    var leadingMargin = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.LeadingMargin, relatedBy: NSLayoutRelation.Equal, toItem: self.mView, attribute: NSLayoutAttribute.LeadingMargin, multiplier: 1, constant: 0.0)

    var trailingMargin = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.TrailingMargin, relatedBy: NSLayoutRelation.Equal, toItem: mView, attribute: NSLayoutAttribute.TrailingMargin, multiplier: 1, constant: 0.0)

    var height = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: screenSize.height - 55)

    var bottom = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.BottomMargin, relatedBy: NSLayoutRelation.Equal, toItem: self.mView, attribute: NSLayoutAttribute.BottomMargin, multiplier: 1, constant: screenSize.height - 200)

    var top = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.TopMargin, relatedBy: NSLayoutRelation.Equal, toItem: self.mView, attribute: NSLayoutAttribute.TopMargin, multiplier: 1, constant: 250)

    self.view.addConstraint(leadingMargin)
    self.view.addConstraint(trailingMargin)
    self.view.addConstraint(height)
    self.view.addConstraint(bottom)
    self.view.addConstraint(top)
0
Prajyot