Tuesday 29 April 2014

Update view frame with text size. Increase UIView width and height to fit the content of text.

There are several times we need to update our view, label, button, etc size to fit the text in them. We can either update view frame width or height and resize our view. So below I wrote two function to update view frame with as NSString as parameter.


Add new files to your project   i.e. UIView+Additions.h and  UIView+Additions.m

//
//  UIView+Additions.h
//

#import <UIKit/UIKit.h>

@interface UIView (Additions)

-(void)updateViewHorizontalFrameWithTitle:(NSString*)titleString withFont:(UIFont*)titleFont;
-(void) updateViewVerticalFrameWithTitle:(NSString*)titleString withFont:(UIFont*)titleFont;

@end

//
//  UIView+Additions.m
//

#import "UIView+Additions.h"

#define kMaxWidth 300
#define kMaxHeight 100000


@implementation UIView (Additions)

-(void)updateViewHorizontalFrameWithTitle:(NSString*)titleString withFont:(UIFont*)titleFont;
{
    NSLog(@"Initial Frame x:%f y:%f w:%f h:%f",self.frame.origin.x, self.frame.origin.y , self.frame.size.width,self.frame.size.height);
    
    //Constrain max size for text
    CGSize constrainedSize = CGSizeMake(kMaxWidth, self.frame.size.height);
    // Get the font
    UIFont *textFont = titleFont;
    //Calculate the size that fits the text with given font in constrained size
    CGSize textSize = [titleString sizeWithFont:textFont constrainedToSize: constrainedSize lineBreakMode:NSLineBreakByWordWrapping];

    // Update view frame according to the size calculated
    self.frame = CGRectMake(self.frame.origin.x , self.frame.origin.y,textSize.width+5, self.frame.size.height);
    
    
  NSLog(@"Updated Frame x:%f y:%f w:%f h:%f",self.frame.origin.xself.frame.origin.y , self.frame.size.width,self.frame.size.height);

}

-(void) updateViewVerticalFrameWithTitle:(NSString*)titleString withFont:(UIFont*)titleFont;
{
    NSLog(@"Initial Frame x:%f y:%f w:%f h:%f",self.frame.origin.xself.frame.origin.y , self.frame.size.width,self.frame.size.height);
    
    //Constrain max size for text
     CGSize constrainedSize = CGSizeMake(self.frame.size.width, kMaxHeight);
    // Get the font
    UIFont *textFont = titleFont;
    //Calculate the size that fits the text with given font in constrained size
     CGSize textSize = [titleString sizeWithFont:textFont constrainedToSize: constrainedSize lineBreakMode:NSLineBreakByWordWrapping];

    // Update view frame according to the size calculated
     self.frame = CGRectMake(self.frame.origin.x , self.frame.origin.y,textSize.width+5self.frame.size.height);
    
    NSLog(@"Updated Frame x:%f y:%f w:%f h:%f",self.frame.origin.xself.frame.origin.y , self.frame.size.width,self.frame.size.height);

}

@end



UPDATE:--------
To calculate the text size replace deprecated method
sizeWithFontconstrainedToSize: lineBreakMode
with new
 boundingRectWithSize: options:  attributes: context:


CGRect textSize = [text boundingRectWithSize:size
                                 options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName: textFont}
                                 context:nil];

CGSize size = textRect.size;

UPDATE:--------



Eg:
Lets create a horizontal scrollview menu with different titles.


/*!
 This function takes array of titleString and create menu slider
Create a scrollview and initialize viewDidLoad that "menuScrollView" 
 */
- (void)viewsInScrollViewForArray:(NSArray*)titleArray
{
    NSLog(@"Array: %@", titleArray); // Array of titles as NSString
    
    /*!
     Remove the views added previously to scrollview if any then remove this line of code
     */
    for (UIView *tempViews in menuScrollView.subviews) {
        if ([tempViews isKindOfClass:[UIButton class]] || [tempViews isKindOfClass:[UILabel class]]) {
            [tempViews removeFromSuperview];
        }
    }
    
    int xOffset = 0;
    int yOffset = 0;
    int width   = 10;
    int height  = 40;
    int spacing = 5;
  

    for (int i = 0; i< titleArray.count; i++) {
        /*!
         Create a view for every menu item
         @param xOffset <#xOffset description#>
         @param yOffset <#yOffset description#>
         @param width   <#width description#>
         @param height  <#height description#>
         @return <#return value description#>
         */
        UIView *view = [[UIView alloc]initWithFrame: CGRectMake(xOffset, yOffset, width, height)];
        /*!
         Update the width of menu item
         */
        [view updateViewHorizontalFrameWithTitle:[titleArray objectAtIndex:i] withFont: kFontTextBoxTitle];
        
        xOffset = view. frame.origin.x + view. frame.size.width + spacing;
        
        UILabel* titleLabel = [[UILabel alloc]init];
        [titleLabel setFrameCGRectMake(0, 0, view. frame.size.width, view. frame.size.height)];
        [titleLabel setText:[titleArray objectAtIndex:i]];
[titleLabel setTextAlignment: NSTextAlignmentCenter];
[titleLabel setFont: kFontTextBoxTitle];
        
        UIButton* button = [UIButton buttonWithType: UIButtonTypeCustom];
        [button setFrameCGRectMake(0, 0, view. frame.size.width, view. frame.size.height)];
        [button addTarget:self action:@selector(menuButtonClicked:) forControlEvents: UIControlEventTouchUpInside];
        
        [view addSubview: titleLabel];
        [view addSubview: button];
        [view setBackgroundColor:[UIColor whiteColor]];
        [button setBackgroundColor:[UIColor clearColor]];
        [titleLabel setTextColor: [UIColor redColor]];
        
        view.tag = i;
        button.tag = i;
        titleLabel.tag = i;

        [menuScrollView addSubview: view];
    }
    
[menuScrollView setContentSize: CGSizeMake(xOffset, menuScrollView. frame.size.height)];
    
}