uitableviewcell textlabel too long and push detailtextlabel out of view
Asked Answered
C

12

31

When i'm using UITableViewCellStyleValue1, i got a long string of textLabel, and somehow the detailTextLabel got push out from the view.

When i shorted my textLabel text, then i can see the detailTextLabel's text.

Is there anyway to limit the width of textLabel in the above style so that it will truncate the textLabel with it's too long?

My code is:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];

}

cell.textLabel.lineBreakMode = UILineBreakModeTailTruncation;

//---get the letter in each section; e.g., A, B, C, etc.---
NSString *alphabet = [self.currencyNameIndex objectAtIndex:[indexPath section]];

//---get all states beginning with the letter---
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF beginswith[c] %@", alphabet];
self.currencyList = [self.keyCurrencyName filteredArrayUsingPredicate:predicate];

if ([self.currencyList count] > 0) 
{
    NSString *currencyName = [self.keyCurrencyName objectAtIndex:indexPath.row];
    cell.textLabel.text = currencyName;

    NSString *currencyCode = [self.valueCurrencyCode objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = currencyCode;

}   

return cell;
}

so my currency name will be a long one on some entry.

Cleistogamy answered 21/4, 2011 at 15:2 Comment(5)
Does it look like Figure 1-8 in the Table View Programming Guide for iOS?Rackety
yes. correct Nick. except that my detailTextLabel is fixed 3 character but the textLabel will be long so i need to truncate textLabel like in Figure 1-8Cleistogamy
Strange, it should truncate by default. Have you set the linebreakmode of the textLabel?Rackety
pasted the code. yea, tried to set the linebreakmode too but no luckCleistogamy
Even more strange. Can you post a screenshot? And please dump the frame of the textLabel of a cell in which the text does not look right.Rackety
M
-7

Use the UILabel lineBreakMode property to restrict your text within the width of your UILabel

@property(nonatomic) UILineBreakMode lineBreakMode

Use it as below.

myLabel.lineBreakMode = UILineBreakModeTailTruncation;

Here is the list of values which could be used with lineBreakMode.

http://developer.apple.com/library/ios/#documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html#//apple_ref/doc/c_ref/UILineBreakMode

EDITED:

Set the width of your UILabel as per your requirment

eg.

myLabel.frame.size.width = 320;
Manfred answered 21/4, 2011 at 15:17 Comment(3)
UILabel works. But when i apply the same to textLabel: cell.textLabel.lineBreakMode = UILineBreakModeTailTruncation; then this will not truncate my textLabelCleistogamy
If you try to use cell.textLabel.frame.size.width = 320; you will get a compiler error indicating that the 'Expression is not assignable' -- so I don't believe this works for the scenario described.Bought
I'm not sure why this is the accepted answer because it does not fix the posted problem. The cell's textLabel already uses NSLineBreakByTruncatingTail by default. And there is no way to change the label's width without subclassing UITableViewCell.Inerney
M
16

Simplest for me was to subclass UITableViewCell and override the layoutSubviews.

Couldn't find a reliable way to calculate the positions from just the label frames so just hardcoded the accessory width for in this case a UITableViewCellStyleValue1 cell with a UITableViewCellAccessoryDisclosureIndicator accessory type.

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGFloat detailTextLabelWidth = [self.detailTextLabel.text sizeWithFont:self.detailTextLabel.font].width;
    CGRect detailTextLabelFrame = self.detailTextLabel.frame;

    if (detailTextLabelFrame.size.width <= detailTextLabelWidth && detailTextLabelWidth > 0) {
        detailTextLabelFrame.size.width = detailTextLabelWidth;
        CGFloat accessoryWidth = (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) ? 28.0f : 35.0f;
        detailTextLabelFrame.origin.x = self.frame.size.width - accessoryWidth - detailTextLabelWidth;
        self.detailTextLabel.frame = detailTextLabelFrame;

        CGRect textLabelFrame = self.textLabel.frame;
        textLabelFrame.size.width = detailTextLabelFrame.origin.x - textLabelFrame.origin.x;
        self.textLabel.frame = textLabelFrame;
    }
}
Marcellamarcelle answered 9/9, 2013 at 20:43 Comment(1)
Better calculate accessory width directly const CGFloat accessoryWidth = CGRectGetWidth(self.bounds) - CGRectGetMaxX(detailTextLabelFrame)Habile
B
8

@Jhaliya @lucas

cell.textLabel.numberOfLines = 3; // set the numberOfLines
cell.textLabel.lineBreakMode = UILineBreakModeTailTruncation;

see here: Custom UITableViewCell. Failed to apply UILineBreakModeTailTruncation

Baskin answered 25/5, 2011 at 9:35 Comment(1)
It works like a charm. Just replace UILineBreakModeTailTruncation by NSLineBreakByTruncatingTail (deprecated since iOS6).Luddite
D
4

I ran into a similar problem when trying to use "Right Detail" in UITableView; the right detail's built in title label was clobbering my subtitle label.

Eventually I gave up on the "Right Detail" in favor of my own custom one (using swift and autolayout):

  1. I created my own simple class that inherited from the UITableViewCell:

    class TransactionCell: UITableViewCell
    {
    
    }
    
  2. I set my prototype cell use that custom class by setting the "Style" field to "Custom" on the "Table View Cell" Menu and by adding "TransactionCell" to the "Class" field of the "Custom Class" menu. These menus are available when you select the prototype cell in the storyboard. enter image description hereenter image description here

  3. I added two labels to my prototype cell and connected them to my custom class by right click dragging from my labels to my class (Oddly, I had to clean my build before it would let me do this):

    class TransactionCell: UITableViewCell{
    
        @IBOutlet weak var detailsLabel: UILabel!
    
        @IBOutlet weak var amountLabel: UILabel!
    
    }
    
  4. I added new constraints to my labels, taking advantage of swift's autolayout features (You will need to set these to match your own requirements; see a tutorial on autolayout if you are stuck)

How to add new constraints: click on the thing to add constraints to then click on this symbol

  1. ...and set the "Lines" and "Line Breaks" fields in the respective "Label" menus so that the spacing between labels would be even and so that my details label could flex to multiple lines. enter image description here

It worked for me, allowing me to have the flexibility of different amounts of multiple lines in a UITableView in swift per cell, while formatting the word wrapping so that it looked nice and even, like I would have expected the "Right Detail" to do automatically.

Deputy answered 31/12, 2015 at 18:57 Comment(1)
This should be the accepted answer. If you're a serious developer and know you'll need a lot of tableViews, you should subclass your cells right off the bat as a habit.Harless
D
3

I had the same problem and had to create a UITableViewCell subclass. It's easier to do that than I thought:

Basically, just make a new file, that is a subclass of UITableViewCell

Add the labels and synthesize them:

// in the .h file
@property (nonatomic, weak) IBOutlet UILabel *textLabel;
@property (nonatomic, weak) IBOutlet UILabel *detailTextLabel;
// in the .m file
@synthesize textLabel, detailTextLabel;

In the StoryBoard, set your class as the cell's class, make the Style "Custom" and add two labels in the cell to look exactly as you want (I made them look the same as the default: http://cl.ly/J7z3)

The most important part is to make sure you connect the labels to the cell

You need to control-click from the Cell to the label in the Document outline. Here's a picture of what it looks like: http://cl.ly/J7BP

What helped me to understand how to create custom cell, dynamic cells, and static cells is this youtube video: http://www.youtube.com/watch?v=fnzkcV_XUw8

Once you do that, you should be all set. Good luck!

Denticle answered 30/8, 2012 at 15:0 Comment(0)
G
2

Swift version supporting the latest iOS (12):

override func layoutSubviews() {
    super.layoutSubviews()
    guard let detailWidth = detailTextLabel?.intrinsicContentSize.width, var detailFrame = detailTextLabel?.frame else {
        return
    }

    let padding = layoutMargins.right
    if (detailFrame.size.width <= detailWidth) && (detailWidth > 0) {
        detailFrame.size.width = detailWidth
        detailFrame.origin.x = frame.size.width - detailWidth - padding
        detailTextLabel?.frame = detailFrame

        var textLabelFrame = textLabel!.frame
        textLabelFrame.size.width = detailFrame.origin.x - textLabelFrame.origin.x - padding
        textLabel?.frame = textLabelFrame
    }
}
Goodspeed answered 27/3, 2019 at 10:35 Comment(0)
V
1

Adjust the frame of the view: textLabel

 CGRect aFrame = cell.textLabel.frame;
 aFrame.size.width = 100;  // for example
 cell.textLabel.frame = aFrame;
Verbalize answered 21/4, 2011 at 15:20 Comment(2)
no luck on this still. the width seems like not getting adjustedCleistogamy
I believe you can't really configure the frame of the default textLabel and detailTextLabel inside a UITableViewCell. If you want to be able to configure the frame of the textLabels you should create your own UITableViewCell subclass. The frame isn't configurable for the default cells because it's related to the size of other components, like the imageView and accessoryView, if those components resize, they will force the labels to resize.Debris
E
1

Updated Gosoftworks Development`s answer.

Swift 3

class BaseTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()

        guard let tl = textLabel, let dl = detailTextLabel else { return }
        if (tl.frame.maxX > dl.frame.minX) {
             tl.frame.size.width = dl.frame.minX - tl.frame.minX - 5        
        }
    }
}
Eleph answered 14/6, 2017 at 7:16 Comment(0)
B
0

Create a custom UITableViewCell with a UILabel in it that you can control however you want, or truncate the text that you assign to the base-class textLabel to fit the space that you have.

It's not perfect, but I have used the text-truncation technique in places where a custom cell is overkill (ex. when the only issue was fitting the text in) using an NSString category with a method similar to the following:

- (NSString *)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font
{
    NSString *result = [NSString stringWithString:self];

    while ([result sizeWithFont:font].width > width)
    {
        result = [result stringByReplacingOccurrencesOfString:@"..." withString:[NSString string]];

        result = [[result substringToIndex:([result length] - 1)] stringByAppendingString:@"..."];
    }

    return result;
}

Probably not 'optimized' but it works for simple scenarios.

Bought answered 30/1, 2013 at 16:47 Comment(0)
C
0

1st: set line break mode

textLabel.lineBreakMode = NSLineBreakByTruncatingTail;

2nd: set texLabel frame width you want (e.g. 200)

CGRect textFrame = self.textLabel.frame;
CGRect newTextFrame = CGRectMake(textFrame.origin.x, textFrame.origin.y, 200, textFrame.size.height);
self.textLabel.frame = newTextFrame;
Cowslip answered 14/3, 2014 at 5:53 Comment(0)
M
0

It works!! But i just changed Christopher King`s code:

- (NSString *)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font :(NSString*) result
{

    while ([result sizeWithFont:font].width > width)
    {
        result = [result stringByReplacingOccurrencesOfString:@"..." withString:[NSString string]];

        result = [[result substringToIndex:([result length] - 1)] stringByAppendingString:@"..."];
    }

    return result;
}

and usage:

NSString* text = @"bla bla bla some long text bla bla";
text = [self stringByTruncatingToWidth:cell.frame.size.width-70.0 withFont:[UIFont systemFontOfSize:17] :text];
cell.textLabel.text = text;
Muumuu answered 11/11, 2014 at 13:7 Comment(0)
S
0

I've struggled with this a bunch and found a pretty simple answer. My textLabel was on the left and would push out the detailText on the right to the point you couldn't see it at all sometimes.

My solution, change the Table View Cell style to Subtitle from Left Detail or Right Detail. This solution works if you don't mind your detailText being below instead of on the right or left.

If you are having issues with the height of the row, you can adjust that using the code below in viewDidLoad.

    self.tableView.estimatedRowHeight = 500 // set this as high as you might need, although I haven't tested alternatives
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.reloadData()
Snorter answered 22/12, 2015 at 3:10 Comment(0)
M
-7

Use the UILabel lineBreakMode property to restrict your text within the width of your UILabel

@property(nonatomic) UILineBreakMode lineBreakMode

Use it as below.

myLabel.lineBreakMode = UILineBreakModeTailTruncation;

Here is the list of values which could be used with lineBreakMode.

http://developer.apple.com/library/ios/#documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html#//apple_ref/doc/c_ref/UILineBreakMode

EDITED:

Set the width of your UILabel as per your requirment

eg.

myLabel.frame.size.width = 320;
Manfred answered 21/4, 2011 at 15:17 Comment(3)
UILabel works. But when i apply the same to textLabel: cell.textLabel.lineBreakMode = UILineBreakModeTailTruncation; then this will not truncate my textLabelCleistogamy
If you try to use cell.textLabel.frame.size.width = 320; you will get a compiler error indicating that the 'Expression is not assignable' -- so I don't believe this works for the scenario described.Bought
I'm not sure why this is the accepted answer because it does not fix the posted problem. The cell's textLabel already uses NSLineBreakByTruncatingTail by default. And there is no way to change the label's width without subclassing UITableViewCell.Inerney

© 2022 - 2024 — McMap. All rights reserved.