ios 如何以编程方式增加 iPhone 中 UITableView 单元格的高度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21396907/
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
How to programmatically increase UITableView cell's height in iPhone?
提问by Kalai
I having the separate custom UITableViewCell
for displaying the data(these data come from server JSON response).In each UITableViewCell
i am having button as read more.If the user clicks read more button i want to programmatically add UILabel
for displaying additional information from server.But initially i set UITableViewCell
height so after clicking read more button i cant able to see the additional inforamtion UILabel
..
我有UITableViewCell
用于显示数据的单独自定义(这些数据来自服务器 JSON 响应)。在每个UITableViewCell
我都有按钮作为阅读更多。如果用户点击阅读更多按钮,我想以编程方式添加UILabel
以显示来自服务器的附加信息。但最初我设置了UITableViewCell
高度,所以点击阅读更多按钮后,我无法看到附加信息UILabel
..
This is the screen shot:
这是屏幕截图:
This is my required screen:
这是我需要的屏幕:
This is the following coding i used:
这是我使用的以下编码:
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
int height1;
if(readMore){
height1=200;
NSLog(@"Clicked");
}
else{
height1=100;
NSLog(@"Not clicked");
}
return height1; // Normal height
}
-(NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return [TitleArr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
static NSString *simpleTableIdentifier = @"SimpleTableCell_iPad";
cell = (TableCell_Leads *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
}
else{
static NSString *simpleTableIdentifier = @"TableCell_Leads";
cell = (TableCell_Leads *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
}
if (cell == nil)
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"SimpleTableCell_iPad" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
else{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"TableCell_Leads" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
}
cell.labTitle.text = [TitleArr objectAtIndex:indexPath.row];
cell.labCategory.text=[CategoryArr objectAtIndex:indexPath.row];
[cell.btnReadmore addTarget:self
action:@selector(funReadmore:)
forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (IBAction)funReadmore:(id)sender
{
[self.tableView beginUpdates];
readMore=TRUE;
NSLog(@"READ MORE");
[self.tableView endUpdates];
}
回答by Tapas Pal
First of all take a bool
& int
variable.
首先取一个bool
&int
变量。
BOOL isReadMoreButtonTouched = NO;
int indexOfReadMoreButton = -1;
Then Implement below with your code
然后用你的代码在下面实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[[cell btnReadmore] setTag:[indexPath row]];
if(isReadMoreButtonTouched && [indexPath row]== indexOfReadMoreButton)
{
// design your read more label here
}
}
Now implement IBAction
现在实现 IBAction
-(IBAction) funReadmore:(id)sender
{
UIButton *readMoreButton = (UIButton *)sender;
indexOfReadMoreButton=[readMoreButton tag];
isReadMoreButtonTouched=YES;
[[self tableView] beginUpdates];
[[self tableView] reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForItem: indexOfReadMoreButton inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
[[self tableView] endUpdates];
}
Now Come to heightForRowAtIndexPath
现在来 heightForRowAtIndexPath
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(isReadMoreButtonTouched && [indexPath row]== indexOfReadMoreButton) return 200.0f;
else return 100.0f;
}
Hope it'll work for you.
希望它对你有用。
回答by Salman Zaidi
Take a int readMoreAtIndex;
as your class variable. Initialize it with a negative value like -1 in init method
and/or viewDidLoad/viewWillAppear
. Some basic logic would be like this:
将 aint readMoreAtIndex;
作为您的类变量。使用负值(如 -1 ininit method
和/or )对其进行初始化viewDidLoad/viewWillAppear
。一些基本逻辑是这样的:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(readMoreAtIndex == indexPath.row) {
return 400; //return as per your requirement
}
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//same lines as currently you are doing to setup cell.
//important line
[cell.btnReadmore setTag:indexPath.row];
[cell.btnReadmore addTarget:self
action:@selector(funReadmore:)
forControlEvents:UIControlEventTouchUpInside];
if(indexPath.row == readMoreAtIndex) {
//setup your cell according to your logic to show expanded view
}
else {
//you are reusing cells, so provide logic to disappear shown expanded view if you want
}
return cell;
}
- (IBAction)funReadmore:(id)sender
{
UIButton *button = (UIButton *)sender;
readMoreAtIndex = button.tag;
[yourTableView reloadData];
NSLog(@"READ MORE");
}
EDIT:Links for tutorials to implement expandable/collapsable tableview.
编辑:实现可展开/可折叠 tableview 的教程链接。
回答by Martin Deandreis
I found another solution based on self-sizingtable view cells. Instead of updating cell's height (hardcoded) we can update the constraints priority.
我找到了另一种基于自调整表格视图单元格的解决方案。我们可以更新约束优先级,而不是更新单元格的高度(硬编码)。
fileprivate extension Int {
static let rowHeight = 175
}
class CellArticleData {
var article: Article
var isExpanded: Bool
init(article: Article, isExpanded: Bool) {
self.article = article
self.isExpanded = isExpanded
}
}
enum Article: String {
case medicine, sport
static let allArticles: [Article] = [.medicine, .sport]
var title: String { return self.rawValue.capitalized }
var description: String {
switch self {
case .medicine:
return "Lorem Ipsum is simply dummy text of the printing and
typesetting industry"
case .sport:
return "Contrary to popular belief, Lorem Ipsum is not simply
random text. It has roots in a piece of classical Latin
literature from 45 BC, making it over 2000 years old. Richard
McClintock, a Latin professor at Hampden-Sydney College in
Virginia."
}
}
}
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var articles: [CellArticleData] = Article.allArticles.map { CellArticleData(article: protocol MyCellDelegate {
func handleReadMore()
}
class MyCell: UITableViewCell {
@IBOutlet weak var topConstraint: NSLayoutConstraint!
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
func setup(articleData: CellArticleData) {
self.articleData = articleData
titleLabel.text = articleData.article.title
descriptionLabel.text = articleData.article.description
readMoreLabel.isUserInteractionEnabled = true
let readMoreTap = UITapGestureRecognizer(target: self, action: #selector(handleReadMore))
readMoreTap.cancelsTouchesInView = false
readMoreLabel.addGestureRecognizer(readMoreTap)
updateCellConstraints()
}
fileprivate func updateCellConstraints() {
if let articleData = self.articleData {
if !articleData.isExpanded {
heightConstraint.priority = 999
topConstraint.priority = 250
bottomConstraint.priority = 250
}else {
heightConstraint.priority = 250
topConstraint.priority = 999
bottomConstraint.priority = 999
}
}
}
func handleReadMore() {
if let articleData = self.articleData {
articleData.isExpanded = !articleData.isExpanded
delegate?.handleReadMore(articleData: articleData)
}
}
}
, isExpanded: false) }
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = CGFloat(.rowHeight)
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
let articleData = articles[indexPath.row]
cell.setup(articleData: articleData)
cell.delegate = self
return cell
}
}
extension ViewController: MyCellDelegate {
func handleReadMore() {
tableView.reloadData()
}
}
I have a custom class that represent a cell "MyCell" which handles the protocol and constraints updates:
我有一个自定义类,代表一个单元格“MyCell”,它处理协议和约束更新:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
Here is an example showing how it looks like: My custom cell MyCell
这是一个显示其外观的示例: 我的自定义单元 MyCell
回答by Jay Gajjar
You need to put some kind of flag mechanism and manage the height in
您需要放置某种标志机制并管理高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(readMore){
return 500;
}else{
return 100;
}
}
The best and ideal way is to calculate the height according to the text and then return the height
最好和理想的方法是根据文本计算高度,然后返回高度
in customCell.h
#import <UIKit/UIKit.h>
@class CustomCell;
@protocol ButtonClickDelegate <NSObject> //custom delegate
- (void)whenReadMoreButtonClicked:(CustomCell *)cell;//i am passing the cell itself
@end
@interface CustomCell : UITableViewCell
@property (nonatomic,assign)id<ButtonClickDelegate>delegate;
@property (nonatomic,retain)UILabel *mesageLabel;
@property (nonatomic,retain)NSString *message;
@property (nonatomic,assign)BOOL expand;
@end
If you are using autolayout then you can calculate the size of each labels manually according to content by using sizeToFit
method
如果您使用的是自动布局,那么您可以使用sizeToFit
方法根据内容手动计算每个标签的大小
回答by Shankar BS
I am posting the sample code that will expand cell based on button click and the text size works for both iOS6 and iOS 7, this is just the sample code, just go through this this may helps u ... :)
我正在发布将基于按钮单击扩展单元格的示例代码,文本大小适用于 iOS6 和 iOS 7,这只是示例代码,只需通过这可能会帮助你... :)
this is just a sample project that u can try
这只是一个您可以尝试的示例项目
#import "CustomCell.h"
@implementation CustomCell
@synthesize delegate;//synthesize it
@synthesize mesageLabel;
@synthesize message;
@synthesize expand;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(5,2, 100, 35)];
[button addTarget:self action:@selector(whenButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Read More" forState:UIControlStateNormal];
button.backgroundColor = [UIColor greenColor];
self.mesageLabel = [[UILabel alloc]initWithFrame:CGRectMake(0 , 40,0 ,0)];
self.mesageLabel.backgroundColor = [UIColor redColor];
self.mesageLabel.numberOfLines = 100;
[self addSubview:self.mesageLabel];
[self addSubview:button];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)whenButtonClicked:(id)sender
{
if([self.delegate respondsToSelector:@selector(whenReadMoreButtonClicked:)])
{
[self.delegate whenReadMoreButtonClicked:self];//delegate to controller
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.mesageLabel.text = self.message;
if(self.expand)
{
CGSize size = [self findMessgeStringHeight];
self.mesageLabel.frame = CGRectMake(0, 40, size.width, size.height);
}
else
{
self.mesageLabel.frame = CGRectMake(0, 40, self.bounds.size.width, 100);
}
}
//helper method to find height
- (CGSize)findMessgeStringHeight
{
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:self.message attributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:17.0f] }];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){225, MAXFLOAT}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize requiredSize = rect.size;
return requiredSize; //finally u return your height
}
@end
in customCell.m
在 customCell.m 中
#import "ViewController.h"
#import "CustomCell.h"
@interface ViewController ( <UITableViewDataSource,UITableViewDelegate,ButtonClickDelegate>//confirm's to delegate
{
BOOL ButtonClickedForExpand;
NSMutableArray *array;
}
@property (nonatomic,retain)NSIndexPath *previousIndexPath;
@property (nonatomic,retain)NSIndexPath *currentIndexPath;
@end
@implementation ViewController
@synthesize previousIndexPath;
@synthesize currentIndexPath;
- (void)viewDidLoad
{
[super viewDidLoad];
ButtonClickedForExpand = NO;
// Do any additional setup after loading the view, typically from a nib.
array = [[NSMutableArray alloc]initWithObjects:@"hello happy coding some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext",@"some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext",@"ello happy coding some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext ello happy coding some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext ello happy coding some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext ello happy coding some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext ello happy coding some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtext some longtextsome longtext some longtext", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return array.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"];
if(cell == nil)
{
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CELL"];
}
if(ButtonClickedForExpand)
{
if(indexPath.row == currentIndexPath.row)
{
cell.expand = YES;
}
else
{
cell.expand = NO;
}
}
else
{
cell.expand = NO;
}
cell.message = [array objectAtIndex:indexPath.row];
cell.delegate = self;//u need to set delegate to self
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize size = [self findMessgeStringHeight:[array objectAtIndex:indexPath.row]];
if(ButtonClickedForExpand)
{
if(indexPath.row == currentIndexPath.row)
{
return size.height + 30;
}
else
{
return 100;//by default
}
}
else
{
return 100;
}
}
//helper function to return the correct height for your label
- (CGSize)findMessgeStringHeight:(NSString *)str
{
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:str attributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:17.0f] }];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){225, MAXFLOAT}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize requiredSize = rect.size;
return requiredSize; //finally u return your height
}
- (void)whenReadMoreButtonClicked:(CustomCell *)cell
{
ButtonClickedForExpand = YES;
self.previousIndexPath = self.currentIndexPath;
self.currentIndexPath = [self.tableView indexPathForCell:cell];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:self.currentIndexPath] withRowAnimation:UITableViewRowAnimationFade];
if(self.previousIndexPath.row == nil)
{
return;
}
else
{
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:self.previousIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
@end
in viewController
在视图控制器中
[yourTableViewInstance reloadData];
EDIT:ADDED ButtonClickedForExpand
to for first click
编辑:添加ButtonClickedForExpand
到第一次点击
EDIT:2 changed if(self.previousIndexPath.row == nil)
in "whenReadMoreButtonClicked" method of view controller
编辑:2if(self.previousIndexPath.row == nil)
在视图控制器的“whenReadMoreButtonClicked”方法中更改
Comment if u don't get
如果你没有得到评论
回答by NeverHopeless
I would suggest you to follow these steps:
我建议您按照以下步骤操作:
In custom cell the contents that will be available to you, put it inside a hidden UIView container. So it is not visible by default.
在自定义单元格中,您可以使用的内容,将其放入隐藏的 UIView 容器中。所以默认是不可见的。
When read more button presses, handle its event trigger inside the class that draws tableView as you are doing it
funReadmore
handler.Take the index of cell and manage/add it in
NSMutableArray
object.Reload TableView data using:
当阅读更多按钮按下时,在绘制 tableView 的类中处理它的事件触发器,因为你正在做它的
funReadmore
处理程序。获取单元格的索引并将其管理/添加到
NSMutableArray
对象中。使用以下命令重新加载 TableView 数据:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if(arrayOfExpandedCellIndexes.contains(indexPath.row)) return EXTENDED_CELL_HEIGHT; // Macro : #define EXTENDED_CELL_HEIGHT 230.0f else return NORMAL_CELL_HEIGHT; // Macro : #define NORMAL_CELL_HEIGHT 100.0f }
- In
heightForRowAtIndexPath
delegate function, write it like this:
- 在
heightForRowAtIndexPath
委托函数中,这样写:
[arrayOfExpandedCellIndexes removeAllObjects];
Using this way you can handle more than one cell with Read More button pressed. If in your requirement only one cell can be expand clear your arrayOfExpandedCellIndexes
using:
使用这种方式,您可以在按下“阅读更多”按钮的情况下处理多个单元格。如果在您的要求中只能扩展一个单元格,请清除您的arrayOfExpandedCellIndexes
使用:
NOTE:Once height is adjusted for a cell don't forget to make the hidden view visible.
注意:一旦为单元格调整了高度,不要忘记使隐藏视图可见。
Hope it helps!
希望能帮助到你!