I'm trying to position a sheet within an NSTableView just below a certain row. I have the row number and have been successfully able to position the sheet at the right column but not the right row.
Apparently NSRect is drawing up from the bottom of the window containing tableView and I can't figure out how to have it identify the row... I know how to position the sheet at a button or text field NSRect cellRect = [myButton frame]; but not at a row...
Any suggestions or pointers would be very helpful, thanks!
- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect {
//the row number is stored as a user default - convoluted but it is what it is
int rowNumber = [[[NSUserDefaults standardUserDefaults] stringForKey:#"p"] intValue];
NSRect cellFrame = [tableView frameOfCellAtColumn:2 row:rowNumber];
cellFrame.size.height = 0;
return cellFrame;
}
This question already has answers here:
Can you animate a height change on a UITableViewCell when selected?
(21 answers)
ios - Expand table view cell like Twitter app
(3 answers)
Closed 9 years ago.
I have a custom cell and one of its labels can be larger enough to justify adding a "See more" button. So I'm cutting off the label's content to 5 lines and then adding this button that expands the content, if needed.
My question is: Can this be done without using reloadData of the tableView?
I have tried this code on the touch event of the "See more" button (inside the custom cell):
self.contentView.frame = self.backgroundView.frame = self.accessoryView.frame = CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height + 80);
Nothing happens! I think I need a way to expand the cell row height and so the table view's content height.
Thanks in advance,
Edition: I checked the solution in link ios - Expand table view cell like Twitter app, I have applied this code in the custom cell (on the touch event):
self.contentExpanded = YES;
UITableView *tableView = [self parentTableView];
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
I'm having 2 issues now:
1) The reloadRowsAtIndexPaths is performing a whole reloadData.
2) The custom cell is the one who knows the cell's height. When accesing this method, self.contentExpanded is always equal to NO.
***The method parentTableView was taken from Reference to the parent tableView of a cell
Edition 2: I dont think the issue is on the heightForRow. I can't avoid this method being called for all of the cells...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath
{
CellObject *object;
if(self.searchTableData)
object = [self.searchTableData objectAtIndex:indexPath.row];
else
object = [self.database.cellObjectsFetchedResultsController objectAtIndexPath:indexPath];
id cell = [TableViewCellFactory createFromCellObject:object fromPrototypeTable:self.tableView];
CGFloat height = [cell getHeightRowForCellObject:object];
return height;
}
And in the custom cell:
- (CGFloat)getHeightRowForCellObject:(CellObject *)cellObject
{
CGFloat messageHeight = 0;
if (![cellObject.content isEqualToString:#""])
{
UILabel *tempMessageLabel = [[UILabel alloc] init];
tempMessageLabel.font = [UIFont systemFontOfSize:14];
tempMessageLabel.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin );
tempMessageLabel.numberOfLines = 5;
tempMessageLabel.text = cellObject.content;
[tempMessageLabel sizeToFit];
CGFloat lineHeight = [tempMessageLabel.text sizeWithFont:tempMessageLabel.font].height;
CGSize size = [tempMessageLabel.text sizeWithFont:tempMessageLabel.font
constrainedToSize:CGSizeMake(280, lineHeight * tempMessageLabel.numberOfLines)
lineBreakMode:UILineBreakModeWordWrap];
messageHeight = size.height;
if(self.contentExpanded)
messageHeight += 100;
}
return messageHeight;
}
I have a UITableView where each row may have a label anywhere from no lines to any number of lines (realistically 3-4). I am wanting the row to be expanded based on the UILabelView contents.
I have this so far:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = 60.0;
UIFont *font = [UIFont fontWithName:#"Helvetica-BoldOblique" size:10.0];
NSString *text = reminder.notes; //the text that will be in the UiLabelView
CGFloat notesHeight = [text sizeWithFont:font
constrainedToSize:CGSizeMake(250.0, 4000.0)
lineBreakMode:UILineBreakModeTailTruncation].height;
height += notesHeight;
return height;
}
I still get screwy results. What can I do to accomplish my goal?
Thank you
you are using UILineBreakModeTailTruncation as lineBreakMode which will always result in a single line and sizeWithFont:constrainedToSize:lineBreakMode: will then return the needed size of that single line.
Try UILineBreakModeWordWrap instead.
edit: I hope you have set the numberOfLines-property of a UILabel to 0 (zero) so that your label is able to draw many lines.
I have a UIPicker I'm using to toggle layers on and off. I want to be able to either change the color of a row within the picker to indicate if that layer is on, or to change the font color of the text to indicate if that layer is on.
If neither are possible, I will append the nsstring to add an X at the end of it before I return it (so "streets" would become "streets X" if the layer is on). I'm not sure how to do this either. I know you can do this type of buffing with a number, but not sure with a NSString. I know the picker can display 27 characters, so maybe set the string length to 26 and then set the char at location 26 to X? But I don't know how to set the length of a string.
Any ideas for either path?
For custom rows in a UIPickerView you have to implement pickerView:viewForRow:forComponent:reusingView: instead of pickerView:titleForRow:forComponent:.
In your case you'd just use a UILabel as the view, and change the text colour and text string for each row.
Assuming you only have one component:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label;
if (!view) // No view to re-use, create a new one
label = [[UILabel alloc] initWithFrame://your frame here];
else
label = (UILabel*)view;
label.text = // Your row text here
if (//some flag to indicate that this row is selected)
label.textColor = [UIColor redColor];
else
label.textColor = [UIColor blackColor];
return label;
}
How would one modify the following snippet (in a tableView:cellForRowAtIndexPath: UITableViewController method) from the "09a - PrefsTable" recipe from Chapter 6 of The iPhone Developer's Cookbook:
if (row == 1) {
// Create a big word-wrapped UILabel
cell = [tableView dequeueReusableCellWithIdentifier:#"libertyCell"];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"libertyCell"] autorelease];
[cell addSubview:[[UILabel alloc] initWithFrame:CGRectMake(20.0f, 10.0f, 280.0f, 330.0f)]];
}
UILabel *sv = [[cell subviews] lastObject];
sv.text = #"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.";
sv.textAlignment = UITextAlignmentCenter;
sv.lineBreakMode = UILineBreakModeWordWrap;
sv.numberOfLines = 9999;
return cell;
}
...to size the "sv" UILabel subview and the "cell" UITableViewCell to be sized just big enough to fit the text (and work with more or less text, and other types of text alignment)? I looked at the UILabel textRectForBounds:limitedToNumberOfLines: method, but the documentation states that it should not be called directly (and should only be overridden). I experimented with the UIView sizeToFit method, without success.
Update: I asked a new question about my problem with the NSString -sizeWithFont:forWidth:lineBreakMode: method.
I had to do this enough that I extended UILabel to do it for me:
#interface UILabel (BPExtensions)
- (void)sizeToFitFixedWidth:(CGFloat)fixedWidth;
#end
#implementation UILabel (BPExtensions)
- (void)sizeToFitFixedWidth:(CGFloat)fixedWidth
{
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, fixedWidth, 0);
self.lineBreakMode = NSLineBreakByWordWrapping;
self.numberOfLines = 0;
[self sizeToFit];
}
#end
then to have a label to have a variable multiline height but a fixed width just:
[myLabel sizeToFitFixedWidth:kSomeFixedWidth];
You should use NSString's -sizeWithFont:forWidth:lineBreakMode: method to retrieve the associated sizing metrics for your label.
Also, change the numberOfLines property to 0 if you're going to use that code.
NSString's -sizeWithFont:forWidth:lineBreakMode: does not actually perform the word wrap. Instead, use -sizeWithFont:constrainedToSize:lineBreakMode: to get an accurate width AND height value for the string.
Try this:
sv.text = #"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.";
sv.textAlignment = UITextAlignmentCenter;
sv.lineBreakMode = UILineBreakModeWordWrap;
sv.numberOfLines = 0;
[sv sizeToFit];
Also, you will need to implement the UITableViewDelegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
And have it return a total cell height adjusted for the resized text field.
One other note - Size to Fit should actually work, if you have number of lines set to 0 as previously mentioned. It would give you back a size with the height increased to accomidate the word-wrapped text set in the label and the width set to whatever the original label width had.
That will not help you though as you need to get the size in heightForRow before the cell is obtained, so you are better off calculating the height needed (and very probably caching that calculation so as not to slow down table rendering)
Here's a bit of code i use:
CGSize textSize = [myLabel.text sizeWithFont:myLabel.font];
I had similar problem, I had a UITableViewCell that was designed in StoryBoards as a static cell. I used [super tableView:cellForRowAtIndexPath:] to get it. So I wanted to resize the UILabel "detailTextLabel" so it fits the text I set to it. The style was "Right Detail".
I just set the text in my tableView:cellForRowAtIndexPath:. And than in tableView:heightForRowAtIndexPath: I returned
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
return cell.detailTextLabel.frame.size.height
I had long string. And finally had a wide Cell with 4 lines of text in label.
I had similar problem.
I solved this.
In cellForRowAtIndexPath method set font size to whatever you want.
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
[cell.textLabel setFont:[UIFont systemFontOfSize:14.0]];
[cell.textLabel sizeToFit];
And in heightForRowAtIndexPath method increase font size.
CGFloat height;
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
NSString *text = cell.detailTextLabel.text;
CGSize constraint = CGSizeMake(320, 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:20.0] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat calHeight = MAX(size.height, 44.0f);
height = calHeight + (CELL_CONTENT_MARGIN * 2);
return height;