user1007522
user1007522

Reputation: 8118

Button with right image aligned x points from the right

I'm trying to create a button that looks like this:

enter image description here

So it has a border and a right imageview.

I subclassed UIButton like this:

class ButtonWithRightImage: UIButton {

    override func imageRectForContentRect(contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRectForContentRect(contentRect)
        imageFrame.origin.x = CGRectGetMaxX(super.titleRectForContentRect(contentRect)) - CGRectGetWidth(imageFrame)
        return imageFrame
    }

    override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRectForContentRect(contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = CGRectGetMinX(super.imageRectForContentRect(contentRect))
        }
        return titleFrame
    }
}

And I created my button as follows:

lazy var testButton: ButtonWithRightImage = {
   let button = ButtonWithRightImage(forAutoLayout: ())

    button.setTitle("Privacy", forState: .Normal)
    button.setTitleColor(UIColor.DarkBlue(), forState: .Normal)

    button.layer.borderWidth = 1
    button.layer.borderColor = UIColor.grey().CGColor

    button.setImage(UIImage(named: "arrow"), forState: .Normal)

    button.contentHorizontalAlignment = .Left
    button.contentEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0)

    return button
}()

Now my button looks like this:

enter image description here

As you can see the image is not aligned with 20 points from the right. I can't figure out how to do this. I'm using autolayout to display the button so I can't just modify the frames I guess.

Upvotes: 2

Views: 362

Answers (3)

Maverick
Maverick

Reputation: 3259

Swift 3 and above solution based on MinuMaster's answer.

Furthermore, provision is added to set right padding for image and left padding for text from storyboard.

Also, have handled the text length so it should not overlap image.

class ButtonWithRightImage: UIButton {

    @IBInspectable var imagePaddingRight: CGFloat = 0.0
    @IBInspectable var textPaddingLeft: CGFloat = 0.0

    override func imageRect(forContentRect contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRect(forContentRect: contentRect)
        imageFrame.origin.x = contentRect.width - imageFrame.width - imagePaddingRight
        return imageFrame
    }

    override func titleRect(forContentRect contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRect(forContentRect: contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = super.imageRect(forContentRect: contentRect).minX + textPaddingLeft
            if titleFrame.size.width > frame.size.width - (imageView?.frame.size.width)! - imagePaddingRight {
                titleFrame.size.width = titleFrame.size.width - (imageView?.frame.size.width)! - imagePaddingRight
            }
        }
        return titleFrame
    }
}

Upvotes: 0

MinuMaster
MinuMaster

Reputation: 1457

As your ButtonWithRightImage class need modification to achieve output as per your requirement.

class ButtonWithRightImage: UIButton {

    override func imageRectForContentRect(contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRectForContentRect(contentRect)
        imageFrame.origin.x = CGRectGetWidth(contentRect) - CGRectGetWidth(imageFrame)
        return imageFrame
    }

    override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRectForContentRect(contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = CGRectGetMinX(super.imageRectForContentRect(contentRect))
        }
        return titleFrame
    }
}

Issue is you need to minus image width from container width. Instead of container maxX value.

Let me know if you have any comment on the same.

Thanks

Upvotes: 4

SBK
SBK

Reputation: 101

Set imageEdgeInsets for button Like Below code:-

lazy var testButton: ButtonWithRightImage = 
{
   let button = ButtonWithRightImage(forAutoLayout: ())

    button.setTitle("Privacy", forState: .Normal)
    button.setTitleColor(UIColor.DarkBlue(), forState: .Normal)

    button.layer.borderWidth = 1
    button.layer.borderColor = UIColor.grey().CGColor

    button.setImage(UIImage(named: "arrow"), forState: .Normal)

    button.contentHorizontalAlignment = .Left
    button.imageEdgeInsets = UIEdgeInsetsMake(0, 280, 0, 0)

    return button
}()

Upvotes: 0

Related Questions