BergP
BergP

Reputation: 3545

UIButton: place image next to the title

I need to place an image view next to the title label (on the right side), so I've created a category with following method:

- (void)updateInsetsToMoveImageRightToText:(NSString *)text {
    CGFloat textWidth = [text sizeWithAttributes:[self.titleLabel.attributedText attributesAtIndex:0 effectiveRange:NULL]].width;
    CGFloat newXPosition = (self.frame.size.width - (self.frame.size.width - textWidth) / 2);
    self.imageEdgeInsets = UIEdgeInsetsMake(0., newXPosition, 0., 0.);
    self.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., self.imageView.image.size.width);
}

I'm using it like this:

- (void)quizzesFilterView:(QuizzesFilterView *)filterView didSelectFilter:(QuizFilterType)type {
    self.filterType = type;
    NSString *newTitle = [QuizzesFilterView filterNameByType:type];
    [self.filterButton setTitle:newTitle forState:UIControlStateNormal];
    [self.filterButton updateInsetsToMoveImageRightToText:newTitle];
    [self removeFilterView];
    [self updateSearchedQuizzesWithSearchText:nil quizFilterType:type];
    [self updateTableUi];
}

But it doesn't work for smaller titles:

enter image description here enter image description here enter image description here enter image description here

What am I doing wrong?

Upvotes: 2

Views: 817

Answers (4)

Glenn Posadas
Glenn Posadas

Reputation: 13300

I know this might be an old question and tagged with Objective-C, but for those guys (like me) who search on Google without specifying the language of the iOS, here's the Swift 3.0 version.

func setupButton(button: UIButton) {
    if let title: NSString = button.currentTitle as NSString?,
        let attribute = button.titleLabel?.attributedText?.attributes(at: 0, effectiveRange: nil) {
        let textWidth = title.size(attributes: attribute).width
        // place here the remaining configurations
    }
}

Upvotes: 0

namanhams
namanhams

Reputation: 526

I have written a custom UIButton that supports flexible alignment in just few lines of code.
It's available here : https://github.com/namanhams/FlexibleAlignButton

Example :
self.btn.alignment = kButtonAlignmentLabelLeft self.btn.gap = 5; // horizontal gap between image and text

Upvotes: 1

rdelmar
rdelmar

Reputation: 104092

The following code worked for me. I put some code in didMoveToSuperview to get the layout correct when the view first appears (I didn't make any changes to the button in the storyboard, other than to set the title and the image).

@implementation RDButton

-(void)didMoveToSuperview {
    CGFloat textWidth = [self.currentTitle sizeWithAttributes:[self.titleLabel.attributedText attributesAtIndex:0 effectiveRange:NULL]].width;
    self.titleEdgeInsets = UIEdgeInsetsMake(0, - (self.imageView.frame.size.width + textWidth), 0, 0);
    self.imageEdgeInsets = UIEdgeInsetsMake(0, textWidth, 0, 0);
    self.contentEdgeInsets = UIEdgeInsetsMake(0, 5, 0, 0);
}



- (void)updateInsetsToMoveImageRightToText:(NSString *)text {
    CGFloat textWidth = [text sizeWithAttributes:[self.titleLabel.attributedText attributesAtIndex:0 effectiveRange:NULL]].width;
    self.imageEdgeInsets = UIEdgeInsetsMake(0, textWidth, 0, 0);
}

After Edit:

Another way that doesn't require any adjustment when you change the title, is to flip the button's layer 180 degrees around the y axis, and do the same to the title label's layer to flip it back to reading correctly. This can be done in the button's code, or you can do it in viewDidLoad of the controller with no need to subclass the button.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.filterButton.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
    self.filterButton.titleLabel.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
}

Upvotes: 1

Michael
Michael

Reputation: 6899

Seems your calculation may be wrong, give this a try.

- (void)updateInsetsToMoveImageRightToText:(NSString *)text {
    CGFloat textWidth = [text sizeWithAttributes:[self.titleLabel.attributedText attributesAtIndex:0 effectiveRange:NULL]].width;
    CGFloat newXPosition = (self.frame.size.width / 2) + (width / 2); //left offset
    self.imageEdgeInsets = UIEdgeInsetsMake(0.0, newXPosition, 0.0, 0.0); 
    self.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., self.imageView.image.size.width);
}

If that doesn't solve the problem, you can add the image as a subview of the button and position it easier according to the width of the text.

Add an image inside UIButton as an accesory

Upvotes: 1

Related Questions