In my iphone app, I have a UITableView with customized cell. The text for one of the label on the cell could be quite long, and I would like it to wrap and clip to bound. I have tried couple of things, however the label still extend all way underneath the accessory icon.
If you have a custom UITableViewCell then you can implement the - (void) layoutSubviews method and resize the UILabel in the cell.
Something like:
CGRect titleFrame = _title.frame;
NSString *currentText = [_title text];
CGSize size = [currentText sizeWithFont:_title.font constrainedToSize:CGSizeMake(titleFrame.size.width, 50.0f) lineBreakMode:_title.lineBreakMode];
titleFrame.size.height = size.height;
_title.frame = titleFrame;
Where _title is the UILabel.
I would add to elpri's answer that you don't need to go through all the trouble of creating a custom subclass of UITableViewCell. Instead you can use tag's but the general approach is correct.
Calculate the size of the frame constraining it to a max size using sizeWithFont:constrainedToSize:lineBreakMode:
Set width/height of your UILabel frame using the calculatedSize.width and calculatedSize.height
Using tags this would look like:
#define NAMELABEL_TAG 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ACellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:NAMELABEL_TAG];
// the rest of your code to resize the frame can go here...
}
Also make sure to set the struts and springs correctly in interface builder so that it autoexpands when the device is rotated (assuming that is what you want).
Related
I am curious as to the behavior of the reuse identifier system.
I am working with a uitableviewcell that has two different uilabels on them.
Label one is always there and is updating correctly,
Label two starts with .alpha=0 and appears on a certain condition within the specific cell.
Label one is acting as suspected,
Label two acts strangely, when I first load the scene(viewdidload) it appears as it should.
When I scroll down and find a uitableviewcell has the labeltwo with .alpha=1 because it satisfied the conditional.
Up to this point everything is working, but now if I scroll back up, all label two's have an .alpha=1.
After doing some research, I have come to the conclusion that this has to do with me redefining what the reuse identifier cell template actually looks like programatically.
My question is , is there a way to reset the "buffer" to the uitableview cell i have created in storyboard that DOESNT have the changes I have made programatically.
Also since these are my own deductions, I may be incorrect in my assumptions,
Thanks for your time.
Your cells begins .alpha = 1, because of reuseIdentifier, that already see .alpha = 1, and set another sell to this parameter. As a first decision, you can control .alpha parameter for the each cell individually.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"FeedbackCell";
VZDetailFeedbackTableViewCell *cell = (VZDetailFeedbackTableViewCell *)[self.p_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[VZDetailFeedbackTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// There can be more cells with Identifier
CGFloat alpha = 1.0f;
//if (something)
{
alpha = 0.0f;
}
[cell setSellAlpha:alpha];
}
// In your custom cell class you make method setAlpha and there control visibility
I am having trouble getting consistent results from UITextViews in a UITableViewCell using NSAttributedStrings.
Inside - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
headerText = [[UITextView alloc]initWithFrame:CGRectZero];
[headerText setUserInteractionEnabled:NO];
headerText.tag = HEADER_TEXT;
[cell.contentView addSubview:headerText];
} else {
headerText = (UITextView*)[cell.contentView viewWithTag:HEADER_TEXT];
}
//...setting up attributed strings
[headerText setAttributedText:headerString];
CGSize headerSize = [headerText sizeThatFits:CGSizeMake(246, CGFLOAT_MAX)];
headerText.frame = CGRectMake(45, 8, headerSize.width, headerSize.height);
Results:
As you can see, the first two appear to draw the text in a way that I would expect/want. In the last two the UITextView sizeThatFits method returns a much larger size then is required to draw the text and the text becomes centered in the frame rather then tight to the top of the frame. This is an issue because I want to be able to layout other views based on the uitextview frame height.
After Scrolling out of frame and back in:
Now it gets even stranger, when the cells are reused, and the attributed string is set again. the uitextview draws the text in an inconsistent way.
Even Setting the contentInsets to
headerText.contentInset = UIEdgeInsetsMake(-8, -8, -8, -8);
Does not provide any sort of consistent results:
And After Scrolling with contentinset set:
Are there other attributes on UITextView that would allow me to get the behavior that I need?
When setting the attributed string of a UITextView that previously had a different attributed string, you must always set all of the UITextView's string-related properties to nil first, e.g.:
self.tv.text = nil;
self.tv.font = nil;
self.tv.textColor = nil;
self.tv.textAlignment = NSTextAlignmentLeft;
self.tv.attributedText = s2;
Otherwise, as you have discovered, old features of the previous attributed string still hang around and affect the new attributed string.
In general, though, I have to say I don't see why you're using UITextView at all. If you don't need the user to be able to edit these attributed strings, use UILabel or else just draw the attributed string directly for the most accurate possible rendering. NSAttributedString gives you all the power you need to measure the size and draw within that size.
I have a UITableView with 3 sections. Each of them have a footer that I've added using viewForFooterInSection. The problem I'm having is that when I scroll the tableview down, the footer sticks to the bottom of the screen, and doesn't scroll like the rest of the cells. Does anyone know how to make it so the footer almost acts like a cell, and scrolls along with the rest of the table? Thanks!
I actually figured it out. Probably isn't the smartest way to do it, but I changed my UITableView style to grouped, and that fixed it. I had to tweak the TableView a bit so the cells would look the same as they did non-grouped (clear background, no separators), but it worked fine. The footer no longer sticks to the bottom of the TableView.
Footers are supposed to stick. The trick is to add an extra cell to each section and render the footer there. If you need more help, add a comment, but it should be pretty straightforward.
EDITS:
Q: Alright. I'm using Core Data and NSFetchedResultsController, to populate the TableView. Would that make it more tricky to accomplish this?
A: Not at all. Override
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
To add an extra cell in each section, and in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
test if the indexPath.row > than your fetchedResultsController's rows for that section. If true, add in your cell that shows the footer information.
One way around this is if you set the footer as one of the cells as the last cell in the scroll view (could be done but setting it as the last item in the array that you set the uitable from)
Adding an extra cell, making it invisible, and rendering your view there is not an advisable way of adding a footer. Doing it properly is pretty straight-forward:
- (UIView*)tableView:(UITableView*)tableView viewForFooterInSection:(NSInteger)section {
NSString* sectionFooter = [self tableView:tableView titleForFooterInSection:section];
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourWidth, yourHeight)]; //create a view- the width should usually be the width of the screen
UILabel* label = [[UILabel alloc] initWithFrame:someFrame];
label.backgroundColor = [UIColor blueColor];
label.textColor = [UIColor whiteColor];
label.text = sectionFooter;
[view addSubview:label];
return view;
}
You will also have to implement tableView: titleForFooterInSection: if you want to add text like I have here.
I did had similar problem when I found out that my code did not work with Landscape mode, and only worked in Portrait mode. In my old code, when in Landscape the tableview can not scroll lower than visible view and it bounced back to top row when scroll (not letting me see the lower rows). All I have to change is to make sure that the height set to 44 as default cell height. So my footer is basically another cell with clearColor. Note my app uses 'AutoLayout'
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
CGRect screenBounds = [UIScreen mainScreen].bounds;
CGFloat width = screenBounds.size.width;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)];
view.backgroundColor = [UIColor clearColor];
UILabel *label = [[UILabel alloc] initWithFrame:view.frame];
label.text = #"Your Text";
[view addSubview:label];
return view;
}
I have a custom view for displaying application status messages that I slide over my table view as needed. This worked fine until I started customizing my table view cells.
When I manually assign a row height to my table view cells in initWithSTyle...
self.TableView.rowHeight = 64.0;
...the custom view doesn't show up anymore.
I replaced the code above with a delegate method...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 64.0;
}
...and now the custom view works as before.
Set rowHeight in the view controller.
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.rowHeight = 64.0f;
}
I think initWithStyle is too early to set the height. Eitherway, since your height is constant, it's still more efficient to set the height once (in viewDidLoad) than set it every time for each cell created (in initWithStyle or heightForRowAtIndexPath).
Did you create a custom cell class inheriting UITableVIewCell , if yes , then the height of customcell is different than the height of default cell.So you need to change the height of row to match your customcell;s in order for it to desplay correctly,Else cellswill overlap.
To Dynamically set height accoring to your customcell:-
YourCustomCell *cell = (YourCustomCell *)[tableView cellForRowAtIndexPath:indexPath];
return [cell.frame.size.height];
maintableView = [[UITableView alloc] init];
maintableView.frame = CGRectMake(0, 0, 320, 480);
maintableView.rowHeight = 100.0;
maintableView.delegate=self;
maintableView.dataSource=self;
It is working in my Xcode. Try like it. I think it will work.
I have a different size of image to be input as a thumbnail of a tableview, is there a way to make all the image align despite their different in size? since in my case, the location of the text will follow the image, so it won't be neat.
Here's the code that I use to input the image
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = title;
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.imageView.image = thumb;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
You can always set the frame of the imageView and textLabel objects as you want them to be.
Cell.imageView is a UIImageView, which is a subclass of UIView. Look at documentation of UIView - exactly "Configuring the Resizing Behavior". Maybe something of that helps.
But beware - resizing on the fly can reduce scrolling behaviour of the tableview. Maybe better way is to resize images to fit the size of the uiimageview before actually using them in tableview.