ios 动态更改 UITableView 高度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14223931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change UITableView height dynamically
提问by alex
I want to change the height of my tableview from another viewcontroller based on the sum of its cells' heights, as they are dynamic. Is it at all possible? Thanks
我想根据其单元格高度的总和从另一个视图控制器更改我的 tableview 的高度,因为它们是动态的。有可能吗?谢谢
Add-on:
添加在:
What I basically have is a UserProfileViewController that has a containerview on half of the screen. There I add different other viewcontrollers:
我基本上拥有的是一个 UserProfileViewController,它在屏幕的一半上有一个容器视图。在那里我添加了不同的其他视图控制器:
In the case of the wall button this is how I add the viewcontroller and it's subsequent tableview:
在墙壁按钮的情况下,这就是我添加视图控制器及其后续 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;
}
and in that viewcontroller this is where I initialize my tableview:
在那个视图控制器中,这是我初始化 tableview 的地方:
-(UITableView *)activityFeedTableView
{
if (!_activityFeedTableView) {
_activityFeedTableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 850.0) style:UITableViewStylePlain];
}
return _activityFeedTableView;
}
I am calculating he total sum of the cell's height, the problem is that the cell's height method is called way after the getter of te tableview is called. So I would need some sort of way to know when the cells' height method is done for all cells and then I can resize my tableview. Thanks
我正在计算单元格高度的总和,问题是在调用 te tableview 的 getter 之后调用单元格的高度方法。所以我需要某种方法来知道何时为所有单元格完成单元格的高度方法,然后我可以调整我的表格视图的大小。谢谢
回答by Rob
There isn't a system feature to change the height of the table based upon the contents of the tableview. Having said that, it is possible to programmatically change the height of the tableview based upon the contents, specifically based upon the contentSize
of the tableview (which is easier than manually calculating the height yourself). A few of the particulars vary depending upon whether you're using the new autolayout that's part of iOS 6, or not.
没有系统功能可以根据 tableview 的内容更改 table 的高度。话虽如此,可以根据内容以编程方式更改 tableview 的高度,特别是基于contentSize
tableview 的高度(这比自己手动计算高度更容易)。一些细节会有所不同,具体取决于您是否使用 iOS 6 中的新自动布局。
But assuming you're configuring your table view's underlying model in viewDidLoad
, if you want to then adjust the height of the tableview, you can do this in viewDidAppear
:
但是假设你在 中配置你的表视图的底层模型viewDidLoad
,如果你想调整表视图的高度,你可以在viewDidAppear
:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self adjustHeightOfTableview];
}
Likewise, if you ever perform a reloadData
(or otherwise add or remove rows) for a tableview, you'd want to make sure that you also manually call adjustHeightOfTableView
there, too, e.g.:
同样,如果您曾经reloadData
为 tableview执行(或以其他方式添加或删除行),您需要确保您也手动调用adjustHeightOfTableView
那里,例如:
- (IBAction)onPressButton:(id)sender
{
[self buildModel];
[self.tableView reloadData];
[self adjustHeightOfTableview];
}
So the question is what should our adjustHeightOfTableview
do. Unfortunately, this is a function of whether you use the iOS 6 autolayout or not. You can determine if you have autolayout turned on by opening your storyboard or NIB and go to the "File Inspector" (e.g. press option+command+1or click on that first tab on the panel on the right):
所以问题是我们应该adjustHeightOfTableview
怎么做。不幸的是,这取决于您是否使用 iOS 6 自动布局。您可以通过打开情节提要或 NIB 并转到“文件检查器”(例如,按option+ command+1或单击右侧面板上的第一个选项卡)来确定是否打开了自动布局:
Let's assume for a second that autolayout was off. In that case, it's quite simple and adjustHeightOfTableview
would just adjust the frame
of the tableview:
让我们假设自动布局已关闭。在这种情况下,它非常简单,adjustHeightOfTableview
只需调整frame
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
}];
}
If your autolayout was on, though, adjustHeightOfTableview
would adjust a height constraint for your tableview:
但是,如果您的自动布局处于开启状态,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];
}];
}
For this latter constraint-based solution to work with autolayout, we must take care of a few things first:
对于后一种基于约束的解决方案与自动布局一起使用,我们必须首先处理一些事情:
Make sure your tableview has a height constraint by clicking on the center button in the group of buttons here and then choose to add the height constraint:
Then add an
IBOutlet
for that constraint:Make sure you adjust other constraints so they don't conflict if you adjust the size tableview programmatically. In my example, the tableview had a trailing space constraint that locked it to the bottom of the screen, so I had to adjust that constraint so that rather than being locked at a particular size, it could be greater or equal to a value, and with a lower priority, so that the height and top of the tableview would rule the day:
What you do here with other constraints will depend entirely upon what other controls you have on your screen below the tableview. As always, dealing with constraints is a little awkward, but it definitely works, though the specifics in your situation depend entirely upon what else you have on the scene. But hopefully you get the idea. Bottom line, with autolayout, make sure to adjust your other constraints (if any) to be flexible to account for the changing tableview height.
单击此处按钮组中的中心按钮,确保您的 tableview 具有高度约束,然后选择添加高度约束:
然后
IBOutlet
为该约束添加一个:如果您以编程方式调整大小 tableview,请确保调整其他约束,以便它们不会发生冲突。在我的示例中,tableview 有一个尾随空间约束,将其锁定到屏幕底部,因此我必须调整该约束,以便它不会被锁定在特定大小,而是可以大于或等于一个值,并且具有较低的优先级,以便 tableview 的高度和顶部将统治这一天:
你在这里用其他约束做什么将完全取决于你在 tableview 下方的屏幕上有哪些其他控件。与往常一样,处理约束有点尴尬,但它绝对有效,尽管您所处的具体情况完全取决于您在现场的其他情况。但希望你能明白。底线,使用自动布局,确保调整您的其他约束(如果有)以灵活考虑不断变化的 tableview 高度。
As you can see, it's much easier to programmatically adjust the height of a tableview if you're not using autolayout, but in case you are, I present both alternatives.
如您所见,如果您不使用自动布局,以编程方式调整 tableview 的高度要容易得多,但如果您使用了,我会提供两种选择。
回答by Mohit Tomar
create your cell by xib or storyboard. give it's outlet's contents.
now call it in CellForRowAtIndexPath.
eg. if you want to set cell height according to Comment's label text.
通过 xib 或故事板创建您的单元格。给它的插座的内容。现在在 CellForRowAtIndexPath 中调用它。例如。如果要根据注释的标签文本设置单元格高度。
so set you commentsLbl.numberOfLine=0;
所以设置你commentsLbl.numberOfLine=0;
so set you commentsLbl.numberOfLine=0;
所以设置你commentsLbl.numberOfLine=0;
then in ViewDidLoad
然后在 ViewDidLoad
self.table.estimatedRowHeight = 44.0 ;
self.table.rowHeight = UITableViewAutomaticDimension;
and now
现在
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;}
回答by LimeRed
Lots of the answers here don't honor changes of the table or are way too complicated. Using a subclass of UITableView
that will properly set intrinsicContentSize
is a far easier solution when using autolayout. No height constraints etc. needed.
这里的很多答案都不尊重表格的变化或者太复杂了。使用自动布局时,使用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()
}
}
Set the class of your TableView to UIDynamicTableView
in the interface builder and watch the magic as this TableView will change it's size after a call to reloadData()
.
UIDynamicTableView
在界面构建器中将TableView 的类设置为并观看魔术,因为此 TableView 将在调用后更改其大小reloadData()
。
回答by Justin Vallely
This can be massively simplified with just 1 line of code in viewDidAppear:
这可以通过 viewDidAppear 中的 1 行代码大大简化:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
tableViewHeightConstraint.constant = tableView.contentSize.height
}
回答by Csaba
Rob's solution is very nice, only thing that in his -(void)adjustHeightOfTableview
method the calling of
Rob 的解决方案非常好,只有在他的-(void)adjustHeightOfTableview
方法中调用
[self.view needsUpdateConstraints]
does nothing, it just returns a flag, instead calling
什么都不做,它只是返回一个标志,而不是调用
[self.view setNeedsUpdateConstraints]
will make the desired effect.
会产生想要的效果。
回答by alex
for resizing my table I went with this solution in my tableview controller witch is perfectly fine:
为了调整我的桌子大小,我在我的 tableview 控制器中使用了这个解决方案,非常好:
[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);
}];
The resizing part is in a method but here is just so you can see it. Now the only problem I haveis resizing the scroll view in the other view controller as I have no idea when the tableview has finished resizing. At the moment I'm doing it with performSelector: afterDelay: but this is really not a good way to do it. Any ideas?
调整大小部分在一个方法中,但在这里只是为了你可以看到它。现在我唯一的问题是在另一个视图控制器中调整滚动视图的大小,因为我不知道 tableview 何时完成调整大小。目前我正在使用 performSelector: afterDelay: 做这件事,但这真的不是一个好方法。有任何想法吗?
回答by Maninderjit Singh
Use simple and easy code
使用简单易行的代码
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let myCell = tableView.dequeueReusableCellWithIdentifier("mannaCustumCell") as! CustomCell
let heightForCell = myCell.bounds.size.height;
return heightForCell;
}
回答by Prajyot
I found adding constraint programmatically much easier than in 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)