web-dev-qa-db-ja.com

UITableViewの高さを動的に変更する

セルは動的であるため、セルの高さの合計に基づいて、別のViewControllerからTableViewの高さを変更したいです。まったく可能ですか?ありがとう

拡張機能:

私が基本的に持っているのは、画面の半分にcontainerviewがあるUserProfileViewControllerです。そこで、他のさまざまなビューコントローラーを追加します。

enter image description here

enter image description here

壁ボタンの場合、これは私がviewcontrollerを追加する方法であり、その後のtableviewです:

- (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;
}

そして、そのviewcontrollerでは、これがtableviewを初期化する場所です:

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

私はセルの高さの合計を計算していますが、問題は、テーブルビューのゲッターが呼び出された後にセルの高さメソッドが呼び出されることです。したがって、すべてのセルに対してセルの高さメソッドがいつ実行されたかを知るための何らかの方法が必要になります。その後、テーブルビューのサイズを変更できます。ありがとう

62
alex

テーブルビューの内容に基づいてテーブルの高さを変更するシステム機能はありません。そうは言っても、内容に基づいて、特にTableViewのcontentSizeに基づいてTableViewの高さをプログラムで変更することができます(手動で高さを手動で計算するよりも簡単です)。いくつかの詳細は、iOS 6の一部である新しい自動レイアウトを使用しているかどうかによって異なります。

ただし、viewDidLoadでTable Viewの基礎となるモデルを設定していると仮定して、TableViewの高さを調整する場合は、viewDidAppearでこれを実行できます。

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

    [self adjustHeightOfTableview];
}

同様に、TableViewでreloadData(または行の追加または削除)を実行する場合、そこでもadjustHeightOfTableViewを手動で呼び出してください。たとえば:

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

    [self adjustHeightOfTableview];
}

それで、質問は、私たちのadjustHeightOfTableviewが何をすべきかです。残念ながら、これはiOS 6の自動レイアウトを使用するかどうかの関数です。ストーリーボードまたはNIBを開いて[ファイルインスペクター]に移動すると、自動レイアウトがオンになっているかどうかを確認できます(例: option+command+1 または、右側のパネルの最初のタブをクリックします):

enter image description here

オートレイアウトがオフになっていたと仮定しましょう。その場合、それは非常に単純で、adjustHeightOfTableviewはtableviewのframeを調整するだけです。

- (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
    }];
}

ただし、自動レイアウトがオンの場合、adjustHeightOfTableviewは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 height constraint accordingly

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

この後者の制約ベースのソリューションが自動レイアウトで機能するためには、最初にいくつかのことに注意する必要があります。

  1. ここでボタンのグループの中央のボタンをクリックして、tableviewに高さの制約があることを確認してから、高さの制約を追加することを選択します。

    add height constraint

  2. 次に、その制約にIBOutletを追加します。

    add IBOutlet

  3. テーブルビューのサイズをプログラムで調整する場合に競合しないように、他の制約を調整してください。私の例では、tableviewには画面の下部にロックする末尾スペース制約があったため、特定のサイズでロックされるのではなく、値以上になるようにその制約を調整する必要がありました。優先度を低くして、テーブルビューの高さと上部が日を支配するようにします。

    adjust other constraints

    ここで他の制約を使用して行うことは、テーブルビューの下の画面にある他のコントロールに完全に依存します。いつものように、制約に対処するのは少し厄介ですが、それは間違いなく機能しますが、あなたの状況の詳細は、あなたがシーンに持っている他のものに完全に依存しています。しかし、うまくいけば、あなたはアイデアを得ます。結論として、自動レイアウトでは、変化するTableViewの高さに対応するために、他の制約(もしあれば)を柔軟に調整してください。

ご覧のとおり、オートレイアウトを使用していない場合は、プログラムでテーブルビューの高さを調整する方がはるかに簡単ですが、使用する場合は、両方の選択肢を紹介します。

174
Rob

xibまたはストーリーボードでセルを作成します。アウトレットのコンテンツを提供します。 CellForRowAtIndexPathで呼び出します。例えば。コメントのラベルテキストに従ってセルの高さを設定する場合。 enter image description here

コメントを設定しますLbl.numberOfLine = 0;enter image description here

コメントを設定しますLbl.numberOfLine = 0;

その後、ViewDidLoadで

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

そしていま

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

ここでの回答の多くは、テーブルの変更を尊重していないか、あまりにも複雑です。 UITableViewを適切に設定するintrinsicContentSizeのサブクラスを使用することは、自動レイアウトを使用する場合のはるかに簡単なソリューションです。高さの制約などは必要ありません。

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

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

インターフェイスビルダーでTableViewのクラスをUIDynamicTableViewに設定し、reloadData()の呼び出し後にこのTableViewのサイズが変更されるのを見てください。

10
LimeRed

これは、viewDidAppearの1行のコードで大幅に簡素化できます。

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

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

ロブのソリューションは非常に素晴らしいです。彼の-(void)adjustHeightOfTableviewメソッドでは

[self.view needsUpdateConstraints]

何もせず、フラグを返すだけで、代わりに

[self.view setNeedsUpdateConstraints]

目的の効果が得られます。

5
Csaba

シンプルで簡単なコードを使用する

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

        return heightForCell;
    }
3

テーブルのサイズを変更するために、TableView Controllerでこのソリューションを使用しました。

[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);
                            }];

サイズ変更部分はメソッド内にありますが、ここではそれを確認できるようにしています。 TableViewのサイズ変更がいつ完了するかわからないので、もう1つの問題は、他のView Controllerでスクロールビューのサイズを変更することです。現時点では、performSelector:afterDelay:を使用していますが、これは実際には良い方法ではありません。何か案は?

2
alex

ストーリーボードよりもプログラムで制約を追加する方がはるかに簡単だと感じました。

    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