简体   繁体   中英

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:

在此处输入图片说明在此处输入图片说明在此处输入图片说明在此处输入图片说明

What am I doing wrong?

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

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);
}

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

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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM