I'm coding a custom UITableViewCell object and I've implemented layoutSubviews to resize the cell when its contents is updated.
To implement heightForRowAtIndexPath, I'm calculating the height of the cell within the custom UITableViewCell object. I'm using NSString sizeWithFont to calculate the size of the cell based on the text within a UILabel and the width of a cell in the UITableView.
But how do I get the width of a cell in the UITableView?
Right now, I'm passing in the table view to the object and using the frame. But the width is of the whole table not the individual cells. Is there something I'm missing here?
Thanks in advance.
EDIT3
I was thinking, if it's really not possible, just test portrait or landscape orientation then set the width manually (ipad just has 2 different orientations)..
EDIT2
There have been some questions about 'why are you doing it this way xxxx'. I understand maybe there's a better way to achieve what I'm doing, creating a custom cell that can calculate its own height with varying text length. If there's a better way of doing it I'm all ears :)
EDIT
http://img845.imageshack.us/img845/7792/screenshot20121129at193.png
+ (CGFloat)getHeightForCellWithText:(NSString *)text isExpanded:(BOOL)expanded tableView:(UITableViewController *)tv {
ProposalViewCell *cell = [[ProposalViewCell alloc] initWithStyle:UITableViewCellSelectionStyleNone reuseIdentifier:#"NormalCell" tableView:tv];
[cell setLabelText:text];
[cell setExpanded:expanded];
[cell layoutSubviews];
return cell.primaryLabel.frame.size.height + cell.readmoreButton.frame.size.height + cell.sendmessageButton.frame.size.height +30;
}
- (void)layoutSubviews {
[super layoutSubviews];
_primaryLabel.numberOfLines = 0; // multiple lines
// size of expanded text label
// sizeWithFont: if text doesn't fit, it is truncated
CGSize expandedSize = [_primaryLabel.text sizeWithFont:myFont constrainedToSize:CGSizeMake(tableView.view.frame.size.width, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
// size as expanded by default
_primaryLabel.frame = CGRectMake(10, 10, expandedSize.width, expandedSize.height);
if (expanded==NO) {
// size of summary text label
_primaryLabel.numberOfLines = 10;
CGSize summarySize = [_primaryLabel sizeThatFits:_primaryLabel.frame.size];
_primaryLabel.frame = CGRectMake(10, 10, summarySize.width, summarySize.height);
}
_readmoreButton.frame = CGRectMake(10, _primaryLabel.frame.size.height+10, 225, 25);
_sendmessageButton.frame = CGRectMake(10, _primaryLabel.frame.size.height+10+_readmoreButton.frame.size.height+10, 225, 25);
}
To get the width of the cell just do this...
cell.contentview.frame.size.width
Related
This is what i have tried,
UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = #"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;//Here i am adjusting the textview
[self.view addSubview:_textView];
Basically after fitting the text into textview,scrolling is enable,but i cannot view the content inside the textview without scrolling the textview.I do want to initialize the UITextView frame size based on the text size,font name etc.
Any solution is appreciated.Thanks.
NSString *str = #"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
UIFont * myFont = [UIFont fontWithName:#"your font Name"size:12];//specify your font details here
//then calculate the required height for the above text.
CGSize textviewSize = [str sizeWithFont:myFont constrainedToSize:CGSizeMake(300, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
//initialize your textview based on the height you got from the above
UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, textviewSize.width, textviewSize.height)];
_textView.text = str;
[self.view addSubview:_textView];
And also you want to disable the scrolling in textview then refer this.
As William Jockusch states in his answer here:
You can disable almost all scrolling by putting the following method
into your UITextView subclass:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
// do nothing
}
The reason I say "almost" all scrolling is that even with the above,
it still accepts user scrolls. Though you could disable those by
setting self.scrollEnabled to NO.
If you want to only disable some scrolls, then make an ivar, lets call
it acceptScrolls, to determine whether you want to allow scrolling or
not. Then your scrollRectToVisible method can look like this:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
if (self.acceptScrolls)
[super scrollRectToVisible: rect animated: animated];
}
I have a UILabel inside a UITableViewCell and I was trying to adjust the height, however when the height is greater than the cell height it overflows to the next cell below it. How can I avoid this? I am adding this into my contentView:
[self.contentView addSubview:self.commentsText_];
if you want to hide the overflows.
self.contentView.clipsToBounds = YES;
or you may want to layout by overwriting at
- (void)setNeedsLayout
{
[super setNeedsLayout];
self.commentsText_.frame = .... // layout your label
}
Using following code you can calculate height of label and also change the height of cell
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UILabel *yourlabel;// use your memober class UILabel. I am declare here temporary.
CGSize s = [yourlabel.text sizeWithFont:[UIFont systemFontOfSize:15] // enter your text font size and cell-width
constrainedToSize:CGSizeMake(yourcellwidth, MAXFLOAT) // - 40 For cell padding
lineBreakMode:UILineBreakModeWordWrap];
return s.height; //this will give you height of UILabel view you can change using addition according your requirements
}
Hope, this will help you..
I'm loading my UITextView from an XML feed so the text is constantly changing. I'm trying the following to resize the cell and text, and it resizes the cell but not the text view, it's just not displaying the text view, or sometimes just part of it.
Any tips along the right way will be really appreciated;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
AssessObject *newObj1;
newObj1=[totalArray objectAtIndex:indexPath.row];
NSString *cellText = newObj1.routeText;
UIFont *cellFont = [UIFont fontWithName:#"Helvetica" size:16.0];
CGSize constraintSize = CGSizeMake(188.0, CGFLOAT_MAX);
CGSize textViewSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
return textViewSize.height + 200;
}
Check the AutoresizingMask of the UITextView you have added to your cell.
Make sure it is set so that it resizes with the cell (you can do this either in IB, or via code using the UIViewAutoresizingMaskFlexibleWidth|UIViewAutoresizingMaskFlexibleWidth value)
Set the textView size equal to textView's contentSize.
Something like this:
CGRectMake(textView.frame.origin.x, textView.frame.origin.y, textView.frame.size.width, textView.contentSize.height);
I'm making the height of the textView equal to the height of it's contentView.
setup the font size, text content and frame rect of the UITextView, then [UITextView sizeToFit] to calculate the contentSize of UITextView, then calculate the row height with the size of contentSize.
Don't forget to resize the frame rect of UITextView;
I have used Bruno's idea to resize my TextView according to the amount of text, when I put it to the ScrollView. This is how I do this. A bunch of constants there, that you may not use. It is important to resize textView after adding it to the ScrollView.
// Programmatic creation of scroll view layout
NSString *text = #"Your text";
CGFloat textOffSetInColumn = 10;
CGFloat infoTextWidth = 196;
CGFloat infoOffsetVertical = 36;
CGFloat initialTextHeight = 50;
// Create textView with initial height
CGRect infoTextFrame = CGRectMake(textOffSetInColumn, infoOffsetVertical, infoTextWidth, initialTextHeight);
infoTextView = [[UITextView alloc] initWithFrame:infoTextFrame];
infoTextView.text = text;
[scrollView addSubview:infoTextView];
// Resize textView
CGFloat infoTextHeight = infoTextView.contentSize.height;
infoTextFrame = CGRectMake(textOffSetInColumn, infoOffsetVertical, infoTextWidth, infoTextHeight);
infoTextView.frame = infoTextFrame;
If you want to change the size of TextView and center it to the previous center, you can use this code:
// Changing size of TextView and centering
CGPoint center = self.categoryTextView.center;
self.categoryTextView.frame = CGRectMake(_categoryTextView.frame.origin.x, _categoryTextView.frame.origin.y, _categoryTextView.frame.size.width, _categoryTextView.contentSize.height);
self.categoryTextView.center = center;
Instead of categoryTextView use your own Outlet name.
I have scroll view with label and a table view and a button . I just want to scroll the scrollview and the table view must display all the contents but tableview must not scroll. Below the tableview i have a button. How to set the frame of the button so it comes exactly below the table?
Thanks
Maybe you would like to set the YourTableView.userInteractionEnabled = NO?
Yes we can disable the scrolling the tableview.
Goto->xib->select table->Goto 1st tab->unselect the scrolling Enabled.
The answer for your Second Question.
Put the UiView in footer of your table and then place the button in that UIView you want to show in bottom.
It will always show at the bottom.
If you want to place button programmatically use following code in viewDidload method.
///--------Table Footer is Set here
UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 260, 44)];
UIButton *adddays = [[UIButton alloc] initWithFrame:CGRectMake(10, 0, 260, 44)];
[adddays setBackgroundImage:[UIImage imageNamed:#"abcd.png"] forState:UIControlStateNormal];
[adddays addTarget:self action:#selector(buttonaction) forControlEvents:UIControlEventTouchDown];
UILabel *text = [[UILabel alloc] initWithFrame:CGRectMake(75, 12, 250, 20)];
[text setBackgroundColor:CLEAR_COLOR];
[text setText:#"Title for your button"];
[text setTextColor:XDARK_BLUE];
text.font=[UIFont fontWithName:#"Arial-BoldMT" size:18.0f];
[footer addSubview:adddays];
[footer addSubview:text];
[table setTableFooterView:footer];
This is assuming you have created IBOutlets for your scrollView, tableView and button, and hooked them up appropriately.
I find it useful to remember that we're only messing with the y-values of a CGRect (origin.y & size.height) - The x-values should be set up in the xib.
I've commented this profusely to illustrate my point better, usually I would only comment where appropriate
-(void)viewDidLoad {
[self.tableView setScrollEnabled:NO];
// Get the number of rows in your table, I use the method
// 'tableView:numberOfRowsInSection:' because I only have one section.
int numOfRows = [self.tableView numberOfRowsInSection:0];
// Get the height of your rows. You can use the magic
// number 46 (44 without including the separator
// between rows) for the height of your rows, but because
// I was using a custom cell, I had to declare an instance
// of that cell and exctract the height from
// cell.frame.size.height (adding +2 to compensate for
// the separator). But for the purpose of this demonstration
// I'm going to stick with a magic number
int rowHeight = 46; //Eww, Magic numbers! :/
// Get a reference to the tableViews frame, and set the height
// of this frame to be the sum of all your rows
CGRect frame = self.tableView.frame;
frame.size.height = numOfRows * rowHeight;
// Now we have a frame with the exact size of our table,
// so set the 'tableView.frame' AND the 'tableView.contentSize'
// to that. (Because we want ALL rows visible as you
// disabled scrolling for the 'tableView')
self.tableView.frame = frame;
self.tableView.contentSize = frame.size;
// Now we want to set up the button beneath the table.
// We still have the 'frame' variable, which gives us
// the tableView's Y-origin and height. We just add these
// two together (with +20 for padding) to get the origin of the button
CGRect buttonFrame = self.button.frame;
buttonFrame.origin.y = frame.origin.y + frame.size.height + 20;
self.button.frame = buttonFrame;
// Finally, we want the `scrollView`'s `contentSize` to
// encompass this entire setup (+20 for padding again)
CGRect scrollFrame = self.scrollView.frame;
scrollFrame.size.height = buttonFrame.origin.y + buttonFrame.size.height = 20;
self.scrollView.contentSize = scrollFrame.size;
}
You could stop the scrolling the table view. But you shouldn't be adding a tableview inside a scrollview. UITableView is subclass of UIScrollView and adding one scrollView on another will create problem. I suggest you to remove the scrollview and use the tableview alone ( as the tableview itself is a scrollview).
An address cell needs a variable height.
In viewWillAppear I draw a test cell to capture the label height in an ivar.
In the delegate method, tableView:heightForRowAtIndexPath, I use the ivar to set the height for the actual address cell.
The code:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UITableViewCell *testCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:#"addressCell"] autorelease];
testCell.textLabel.text = #"Address";
testCell.detailTextLabel.text = [selectedPatient valueForKey:#"address"];
testCell.selectionStyle = UITableViewCellSelectionStyleNone;
testCell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
testCell.frame = CGRectMake(0,0,100,30);
[testCell addSubview:testCell.detailTextLabel];
[testCell sizeToFit];
CGSize maxSize;
// HERE is where the problem occurs
// maxSize.width is 35 when it should be 200
maxSize.width = testCell.detailTextLabel.frame.size.width;
//
maxSize.height = 500;
UIFont *font = testCell.detailTextLabel.font;
CGSize testSize = [[selectedPatient valueForKey:#"address"] sizeWithFont:font constrainedToSize:maxSize lineBreakMode:UILineBreakModeWordWrap];
addressLabelHeight = testSize.height;
[testCell removeFromSuperview];
}
Getting the width of the test cell is the problem. When NSLog'ing cellForRowAtIndexPath: it shows the width to be 200, but my testCell's width is only 35. This causes the height to be too big, showing a cell with way too much white space.
I fixed the problem by just setting maxSize.width = 200 but I was curious what I was doing wrong to get the detailLabel's width dynamically?
maxSize.width is going to be the width of the text. What's the text you get from #"address"? I'm betting it's about 35 points wide.
BTW, why are you doing this:
// This is legal, but a strange size
testCell.frame = CGRectMake(0,0,100,30);
// This is redundant I believe
[testCell addSubview:testCell.detailTextLabel];
// Does this help you at all?
[testCell sizeToFit];
You can't really trust the width of the cell until tableView:willDisplayCell:atIndexPath:. That's where you want to do any final layout. For your purposes, you should probably choose how wide you want the address to be (200 points if you like), and then force it to be that width rather than asking it how big it is.