1

I use this method for recalculate frame for my labels:

- (void)fitElements {    
    CGFloat currentX = 0.0;
    CGFloat currentY = 0.0;    
    for (UIView *view in elements) {    
        CGRect rect = view.frame;
        rect.origin.x = currentX;
        rect.origin.y = currentY;        
        currentX = rect.origin.x + rect.size.width + 5;        
        view.frame = rect;      
        if (currentX >= 420) {
            currentX = 0.0;
            currentY += rect.size.height + 5;
        }
    }
}

If my label crosses the border that more than 420 I move my object to next line.

- (void)createElements {
    NSInteger tag = 0;
    for (NSString *str in words) {
        UILabel *label = [[UILabel alloc] init];
        [self addGesture:label];
        [label setTextColor:[UIColor blueColor]];
        label.text = str;
        [label setAlpha:0.8];
        [label sizeToFit];
        [elements addObject:label];
    }
}

This is how it looks if I create object as above (using [label sizeToFit];)

enter image description here

as we can see all my label went out of border

but if I use label with hardcode frame I get this:

enter image description here

and this is what I want, but in this case I have static width of object.

This is my method with a hardcode frame.

- (void)createElements {
    NSInteger tag = 0;
    for (NSString *str in words) {
        UILabel *label = [[UILabel alloc] init];
        [self addGesture:label];
        [label setTextColor:[UIColor blueColor]];
        label.text = str;
        [label setAlpha:0.8];
        [label setFrame:CGRectMake(0, 0, 100, 20)];
        [elements addObject:label];
        tag++;
    }
}

How can I make object with relative width and that it also can recalculates correctly?

Tetsujin no Oni
  • 7,300
  • 2
  • 29
  • 46
Matrosov Oleksandr
  • 25,505
  • 44
  • 151
  • 277

1 Answers1

2

You could achieve something like left-justify with small modification of your code:

- (void)fitElements {
CGFloat currentX = 0.0;
CGFloat currentY = 0.0;
for (UILabel *view in elements) { //UIView changed to UILabel
    CGRect rect = view.frame;
    rect.origin.x = currentX;
    rect.origin.y = currentY;
    rect.size.width = [self widthOfString: view.text withFont:view.font];
    currentX = rect.origin.x + rect.size.width + 5;
    view.frame = rect;
    if (currentX + rect.size.width >= 420) {   //EDIT done here
        currentX = 0.0;
        currentY += rect.size.height + 5;
        rect.origin.x = currentX;
        rect.origin.y = currentY;
        view.frame = rect;
        currentX = rect.origin.x + rect.size.width + 5;
    }
}}

- (CGFloat)widthOfString:(NSString *)string withFont:(NSFont *)font {
     NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
     return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
 }

widthOfString method is copied from Stephen's answer

EDIT:

You can also find a lot of useful methods dealing with size of graphical representation of a string in NSString UIKit Additions.

Community
  • 1
  • 1
Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • sorry I have copy paste and it does not work as well :( I don't need grouped or table style, I'm wanna the same variant as on first image, but that all words contain in frame. – Matrosov Oleksandr Oct 31 '12 at 23:35
  • of course, sorry for that. i edited the code. have a xp machine here, so i couldn't test it. now it should work. – Rok Jarc Nov 01 '12 at 02:14
  • 1
    thanks, but I have corrected your code, cause if we don't increase values of currentX in if block in the next iteration we get the same value and labels add on each other. – Matrosov Oleksandr Nov 01 '12 at 13:09
  • i don't what the problem but it is don't work, but it work if I don't use [label sizeToFit]; how come :( – Matrosov Oleksandr Nov 01 '12 at 13:16
  • don't use `sizeToFit` - it's `UIView`'s method - it changes it's bounds to fit all the subviews. It has nothing to do with fitting the string to a `UILabel` since characters (string) are not considered as subviews. – Rok Jarc Nov 01 '12 at 13:18
  • i edited the answer some more but can't test it at the moment - if there are some subviews that are not of UILabel type this will crash - but it's easy to adapt for that situation – Rok Jarc Nov 01 '12 at 13:26
  • so wich method i should to use for get dynamic width of UILabel – Matrosov Oleksandr Nov 01 '12 at 13:26
  • no problem. you should uncheck the answer if it still doesn't work – Rok Jarc Nov 01 '12 at 13:36