Development Tip

UIButton의 이미지 및 중앙 텍스트 왼쪽 정렬

yourdevel 2021. 1. 5. 19:43
반응형

UIButton의 이미지 및 중앙 텍스트 왼쪽 정렬


오른쪽 정렬에 관한 게시물을 보았지만 왼쪽 정렬이 작동하지 않습니다. 버튼이 화면 너비를 차지하고 왼쪽에 이미지가 있고 제목 / 텍스트가 중앙에 있기를 원합니다.

이것은 작동하지 않습니다 (적어도 안정적으로).

    button.titleLabel.textAlignment = UITextAlignmentCenter;
    [button setImageEdgeInsets:UIEdgeInsetsMake(0, -60.0, 0, 0)];
    button.frame = CGRectMake((self.view.frame.size.width - w ) / 2, self.view.frame.size.height - 140.0,  self.view.frame.size.width - 10.0, 40.0);

이 솔루션은 Swift 3에서 작동하며 원본 콘텐츠 및 이미지 가장자리 삽입을 존중하면서 제목 레이블을 항상 사용 가능한 공간의 중앙에 유지하므로 여백을 훨씬 쉽게 조정할 수 있습니다.

titleRect(forContentRect:)메서드를 재정의 하고 올바른 프레임을 반환합니다.

@IBDesignable
class LeftAlignedIconButton: UIButton {
    override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
        let titleRect = super.titleRect(forContentRect: contentRect)
        let imageSize = currentImage?.size ?? .zero
        let availableWidth = contentRect.width - imageEdgeInsets.right - imageSize.width - titleRect.width
        return titleRect.offsetBy(dx: round(availableWidth / 2), dy: 0)
    }
}

다음 삽입물 :

여기에 이미지 설명 입력

결과는 다음과 같습니다.

여기에 이미지 설명 입력


더 이상 사용되지 않는 이전 답변

이것은 대부분의 시나리오에서 작동하지만 일부 레이아웃 layoutSubviews은 무한 루프에서 재귀 적으로 자신을 호출하므로 주의해서 사용하십시오 .

@IBDesignable
class LeftAlignedIconButton: UIButton {
    override func layoutSubviews() {
        super.layoutSubviews()
        contentHorizontalAlignment = .left
        let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
        let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
    }
}

이 코드는 동일하지만 아이콘을 오른쪽 가장자리에 정렬합니다.

@IBDesignable
class RightAlignedIconButton: UIButton {
    override func layoutSubviews() {
        super.layoutSubviews()
        semanticContentAttribute = .forceRightToLeft
        contentHorizontalAlignment = .right
        let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
        let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
    }
}

여기에 이미지 설명 입력

올바른 할당 버전을 사용 semanticContentAttribute하므로 iOS 9 이상이 필요합니다.


결국에는 UIEdgeInsetsMake를 사용하여이 작업을 수행했습니다.이 작업은 왼쪽 모서리가 중앙에 있도록 계산됩니다. 텍스트를 중앙에 정렬 할 수있는 것이 있는지 확실하지 않지만 이것은 저에게 효과적입니다. 너비를 계산하여 왼쪽 모서리를 원하는 위치로 설정했는지 확인하십시오. 예 :UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f)

UIButton *scanBarCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
scanBarCodeButton.frame = CGRectMake(center, 10.0f, fieldWidth, 40.0f);
[scanBarCodeButton setImage:[UIImage imageNamed:@"BarCodeIcon.png"] forState:UIControlStateNormal];
[scanBarCodeButton setTitle:@"Scan the Barcode" forState:UIControlStateNormal];
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f);
[scanBarCodeButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[scanBarCodeButton addTarget:self action:@selector(scanBarCode:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:scanBarCodeButton];

출력은 다음과 같습니다.

이미지가있는 가운데 맞춤 텍스트

에서 스위프트 :

var scanBarCodeButton: UIButton = UIButton(type: .roundedRect)
scanBarCodeButton.frame = CGRectMake(center, 10.0, fieldWidth, 40.0)
scanBarCodeButton.setImage(UIImage(named: "BarCodeIcon.png"), for: UIControlStateNormal)
scanBarCodeButton.setTitle("Scan the Barcode", for: UIControlStateNormal)
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0, 42.0, 0.0, 0.0)
scanBarCodeButton.contentHorizontalAlignment = .left
scanBarCodeButton.addTarget(self, action: "scanBarCode:", for: UIControlEventTouchUpInside)
self.view.addSubview(scanBarCodeButton)

Swift 4.0의 경우 작동하는 확장 기능이 있습니다.

extension UIButton {
    func leftImage(image: UIImage, renderMode: UIImageRenderingMode) {
        self.setImage(image.withRenderingMode(renderMode), for: .normal)
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
        self.contentHorizontalAlignment = .left
        self.imageView?.contentMode = .scaleAspectFit
    }

    func rightImage(image: UIImage, renderMode: UIImageRenderingMode){
        self.setImage(image.withRenderingMode(renderMode), for: .normal)
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
        self.contentHorizontalAlignment = .right
        self.imageView?.contentMode = .scaleAspectFit
    }
}

용법:

myButton.rightImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
myButton.leftImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)

renderMode.alwaysTemplate또는 일 수 있습니다 .alwaysOriginal. 또한 유형 myButton이어야합니다 .customUIButton

이 확장의 leftImagerightImage도 사용할 수 있습니다 UIButtonUIBarButtonItem대한 UINavigationBar(참고 :에 너비 / 높이 제약 조건을 추가해야합니다, 그래서 아이폰 OS (11)로, 탐색 바는 자동 레이아웃 다음 UIBarButtonItem). 내비게이션 바에서 사용하려면 Apple에서 권장하는 @ 2x 및 @ 3x 이미지 크기 (예 : 50x50, 75x75)를 따르고 iPhone 6, 7, 8, 6s, 7s, 8s, Plus 변형 및 iPhone에서 더 나은 접근성을 제공하는지 확인하십시오. x의 너비와 높이는 높이 UIBarButton-25 및 너비-55 일 수 있습니다.


업데이트 : Swift 4.2에서 UIImageRenderingMode이름이 다음과 같이 변경되었습니다.UIImage.RenderingMode

extension UIButton {
    func leftImage(image: UIImage, renderMode: UIImage.RenderingMode) {
        self.setImage(image.withRenderingMode(renderMode), for: .normal)
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
        self.contentHorizontalAlignment = .left
        self.imageView?.contentMode = .scaleAspectFit
    }

    func rightImage(image: UIImage, renderMode: UIImage.RenderingMode){
        self.setImage(image.withRenderingMode(renderMode), for: .normal)
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
        self.contentHorizontalAlignment = .right
        self.imageView?.contentMode = .scaleAspectFit
    }
}

버튼을 만들고 텍스트 정렬을 가운데로 설정 한 후 다음을 추가합니다.

UIImage *image = [UIImage imageNamed:@"..."];
CGSize imageSize = image.size;
CGFloat offsetY = floor((self.layer.bounds.size.height - imageSize.height) / 2.0);

CALayer *imageLayer = [CALayer layer];
imageLayer.contents = (__bridge id) image.CGImage;
imageLayer.contentsGravity = kCAGravityBottom;
imageLayer.contentsScale = [UIScreen mainScreen].scale;
imageLayer.frame = CGRectMake(offsetY, offsetY, imageSize.width, imageSize.height);
[self.layer addSublayer:imageLayer];

내가 생각하기에 좋은 솔루션은 삽입에 대한 하드 코딩 된 값없이 모든 텍스트에 유용해야합니다 (toytoy에서 제공하는 솔루션에 관한 것입니다). 다음과 유사한 코드를 사용합니다.

NSString *sometitle = @"blabla button title";
NSString *someimage = @"blablaimage";
UIImage *image = [[UIImage imageNamed:someimage];
int buttonWidth = A;
int buttonHeight = B;
int imageWidth =image.size.width;
int imageHeight = image.size.height;
int titleWidth = buttonWidth - imageWidth;

// create button and set image and title
buttonView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, buttonWidth, buttonHeight)];
[buttonView setImage:image forState:UIControlStateNormal];
[buttonView setTitle:sometitle forState:UIControlStateNormal];

// make button all content to be left aligned
[buttonView setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];

// set title font 
[buttonView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:14]];

// calculate font text width with selected font
CGSize stringBoundingBox = [number sizeWithFont:[buttonView.titleLabel font]];

// make title inset with some value from left 
// it place the title right on the center of space for the title
int titleLeft = (titleWidth - stringBoundingBox.width) / 2;
[buttonView setTitleEdgeInsets:UIEdgeInsetsMake(0, titleLeft, 0, 0)];

stringBoundingBox init 문자열 뒤에 다음과 같은 문자열도 추가합니다.

if (stringBoundingBox.width > titleWidth)
{
    [_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:13]];
    stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
if (stringBoundingBox.width > titleWidth)
{
    [_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:12]];
    stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}

더 작은 글꼴을 선택하여 사용 가능한 공간보다 긴 제목을 설정할 수 있습니다. 나는 이것을위한 다른 방법 때문에 이것을 만든다 :

[buttonView.titleLabel setAdjustsFontSizeToFitWidth:YES];

잘 작동하지 않고 한 단계에서 3-4 포인트 더 작은 글꼴 크기를 사용하는 것처럼 보이므로 너무 길지 않은 일부 줄은 필요한 것보다 너무 작아집니다.

이 코드를 사용하면 버튼 제목 공간에 텍스트를 정확히 가운데에 배치 할 수 있습니다.


[self.button setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];

[self.button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, self.button.center.x/2 , 0.0, 0.0)];

[self.button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];

작동하지 않는 경우 알려주십시오.

내 출력 여기에 이미지 설명 입력


UIButton 확장을 작성했습니다.

extension UIButton {

  /// Add image on left view
  func leftImage(image: UIImage) {
    self.setImage(image, for: .normal)
    self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width)
  }
}

그리고 다음과 같이 사용할 수 있습니다.

yourButton.leftImage(image: yourImage)

짜잔!


이것은 이미지 너비와 제목 길이가 다른 여러 버튼에 대해 잘 작동합니다.

하위 클래스를 열고 UIButton다음 메서드를 추가합니다.

override func layoutSubviews() {
    super.layoutSubviews()

    if let image = imageView?.image {

        let margin = 30 - image.size.width / 2
        let titleRect = titleRectForContentRect(bounds)
        let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2


        contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
            imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
            titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width -  image.size.width - margin) / 2, 0, 0)
    }

}

나는 위의 거의 모든 솔루션을 시도했지만 예상대로 작동하지 않았습니다 (각기 다른 제목과 다른 이미지 너비를 가진 두 개의 버튼이 있습니다). 그래서 UIButton에 대한 내 자신의 확장 프로그램을 작성했습니다. UIButton은 다른 제목뿐만 아니라 다른 이미지 너비에서도 완벽하게 작동합니다.

extension UIButton {
    func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
        guard let imageViewWidth = self.imageView?.frame.width else{return}
        guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
        self.contentHorizontalAlignment = .left
        imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
        titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
    }
}

용법: myButton.moveImageLeftTextCenter()


운없이 대부분의 답변을 시도했습니다. 나는 대부분의 시간 동안 파란색 이미지를 얻었거나 제목이 중앙에 있지 않았습니다. 몇 가지 답변의 코드를 사용 하고이 확장을 작성하면 매력처럼 작동합니다.

Swift 4.2 :

import UIKit

extension UIButton {
    func moveImageLeftTextCenter(image : UIImage, imagePadding: CGFloat, renderingMode: UIImage.RenderingMode){
        self.setImage(image.withRenderingMode(renderingMode), for: .normal)
        guard let imageViewWidth = self.imageView?.frame.width else{return}
        guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
        self.contentHorizontalAlignment = .left
        let imageLeft = imagePadding - imageViewWidth / 2
        let titleLeft = (bounds.width - titleLabelWidth) / 2 - imageViewWidth
        imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imageLeft, bottom: 0.0, right: 0.0)
        titleEdgeInsets = UIEdgeInsets(top: 0.0, left: titleLeft , bottom: 0.0, right: 0.0)
    }
}

도움이되기를 바랍니다!


1) button.frame = self.view.bounds;

2) setImageEdgeInsets음수 값으로 버튼이 화면을 채울 때 광기입니다. 여기서 뭘 하려는지 재고 해?

3) UITextAlignmentCenter지금NSTextAlignmentCenter

4) button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;


여기에 아이콘을 왼쪽으로 설정하는 데 초점을 맞춘 많은 솔루션이 있습니다. UIImageView를 추가하고 버튼과 이미지의 왼쪽을 정렬하고 중앙에 맞추는 것이 더 쉽다고 생각합니다. 그런 다음 오프셋으로 약간 재생하여 멋지게 만들 수 있습니다.

인터페이스 빌더에 코드가 없습니다.


신속하게 UIButton 확장을 작성했습니다.

extension UIButton {

func setLeftImage(imageName:String, padding:CGFloat) {
        //Set left image
        let image = UIImage(named: imageName)
        self.setImage(image, forState: .Normal)

        //Calculate and set image inset to keep it left aligned
        let imageWidth = image?.size.width
        let textWidth = self.titleLabel?.intrinsicContentSize().width
        let buttonWidth = CGRectGetWidth(self.bounds)

        let padding:CGFloat = 30.0
        let rightInset = buttonWidth - imageWidth!  - textWidth! - padding

        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: rightInset)
    }
}

원하는 방식으로 버튼 텍스트의 스타일을 지정하고 중앙 정렬 상태로 유지합니다. 그런 다음 버튼에서이 메서드를 다음과 같이 호출합니다.

myButton.setLeftImage("image_name", 30.0)

이로 인해 내 이미지가 왼쪽 테두리의 패딩과 함께 왼쪽 정렬됩니다.


이 답변이 다소 늦었다는 것을 알고 있습니다. 그러나 중앙 텍스트가있는 UIButton의 왼쪽에 UIImageView를 사용하여 이미지를 추가하려는 사람들을위한 매우 간단한 솔루션이 있습니다. 모두 프로그래밍 방식

class RandomVC: UIViewController{

    var imageDemo: UIImageView = {
    let img = UIImageView()
    img.translatesAutoresizingMaskIntoConstraints = false
    img.image = UIImage(named: "someImgFromAssets")
    return img
    }()

    lazy var someButton: UIButton = { //lazy var: so button can have access to self class
    let button = UIButton(type: .system)
    button.setTitle("This is your title", for: UIControlState.normal)
    button.translatesAutoresizingMaskIntoConstraints = false 
    button.setTitleColor(UIColor.white, for: UIControlState.normal)
    button.addTarget(self, action: #selector(handleButtonClick), for: .touchUpInside) //make sure you write function "handleButtonClick" inside your class
    button.titleLabel?.textAlignment = .center
    return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubView(someButton)
        someButton.addSubview(imageDemo)
        imageDemo.centerYAnchor.constraint(equalTo: someButton.centerYAnchor).isActive = true
        imageDemo.leftAnchor.constraint(equalTo: someButton.leftAnchor, constant: 10).isActive = true
        imageDemo.heightAnchor.constraint(equalToConstant: 25).isActive = true
        imageDemo.widthAnchor.constraint(equalToConstant: 25).isActive = true
    }

}

한 가지 트릭은 다음과 같습니다.

  1. 오버라이드 titleRectForContentRect버튼의 만드는 titleLabel의이 frame버튼의 경계에 동일
  2. 설정 titleLabeltextAlignment.Center
  3. 우선 imageRectForContentRect지정하는 origin.x버튼의의를imageView

    import UIKit
    
    class ButtonWithLeftAlignedImageAndCenteredText: UIButton {
    
        override init(frame: CGRect) {
            super.init(frame: frame)
    
            titleLabel?.textAlignment = .Center
        }
    
        override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
            var imageFrame = super.imageRectForContentRect(contentRect)
            imageFrame.origin.x = 20 //offset from left edge
            return imageFrame
        }
    
        override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
            var titleFrame = super.titleRectForContentRect(contentRect)
            titleFrame = self.bounds
            return titleFrame
        }
    
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

아래 코드를 사용하여 UIButton에서 이미지를 왼쪽 정렬 할 수 있습니다.

1 단계:

//create your UIButton
UIButton *post_bNeeds_BTN= [UIButton buttonWithType:UIButtonTypeRoundedRect];
post_bNeeds_BTN.frame= CGRectMake(160 ,5 ,150 ,40);
[post_bNeeds_BTN addTarget:self action:@selector(post_Buying_Needs_BTN_Pressed:) forControlEvents:UIControlEventTouchUpInside];
[post_bNeeds_BTN setBackgroundColor:[UIColor colorWithRed:243/255.0 green:131/255.0 blue:26/255.0 alpha:1.0f]];//230
[self.view addSubview:post_bNeeds_BTN];
post_bNeeds_BTN.autoresizingMask= UIViewAutoresizingFlexibleWidth;

2 단계:

//Add UIImageView on right side the button
UIImageView *bNeedsIVw= [[UIImageView alloc] initWithFrame:CGRectMake(5,5,30,30)];
bNeedsIVw.image= [UIImage imageNamed:@"postRequir_30.png"];
bNeedsIVw.image= [bNeedsIVw.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
bNeedsIVw.tintColor= [UIColor whiteColor];
[post_bNeeds_BTN addSubview:bNeedsIVw];

3 단계 :

//also set UILable on UIButton
UILabel *bNeedsLbl= [[UILabel alloc] initWithFrame:CGRectMake(40 ,0 ,post_Prod_BTN.frame.size.width-40 ,post_Prod_BTN.frame.size.height)];
bNeedsLbl.text= @"Requirements";
bNeedsLbl.font= [UIFont systemFontOfSize:16];
bNeedsLbl.textColor= [UIColor whiteColor];
bNeedsLbl.textAlignment= NSTextAlignmentLeft;
[post_bNeeds_BTN addSubview:bNeedsLbl];

4 단계 :

-(void)post_Buying_Needs_BTN_Pressed:(id)sender{
    //write your code action here,,
}

감사,


이 코드는 버튼 이미지를 왼쪽에 맞추고 제목 레이블은 버튼의 중앙으로 이동합니다. b는 버튼입니다 :)

            b.contentHorizontalAlignment = .Left
        let left = (b.frameWidth() - b.titleLabel!.frameWidth()) / 2 - CGRectGetMaxX(b.imageView!.frame)
        b.titleEdgeInsets = UIEdgeInsetsMake(0, left, 0, 0)

이 솔루션은 확장을 사용하여 적용 할 수 있습니다. 하위 분류가 필요 없습니다.

경고 : 텍스트 / 이미지가 업데이트 될 때마다 호출해야합니다.

let width = frame.width
guard let imageWidth = imageView?.frame.width, let labelWidth = titleLabel?.frame.width else {
      return
}
titleEdgeInsets = UIEdgeInsets(top: 0, left: (width - labelWidth)/2.0 - imageWidth, bottom: 0, right: 0)

다음 확장은 Swift 4.2에서 나를 위해 작동합니다.

func leftImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode) {
    self.setImage(image.withRenderingMode(renderMode), for: .normal)
    contentHorizontalAlignment = .left
    let availableSpace = bounds.inset(by: contentEdgeInsets)
    let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
    titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
    imageEdgeInsets = UIEdgeInsets(top: 0, left: padding, bottom: 0, right: 0)
}

func rightImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode){
    self.setImage(image.withRenderingMode(renderMode), for: .normal)
    semanticContentAttribute = .forceRightToLeft
    contentHorizontalAlignment = .right
    let availableSpace = bounds.inset(by: contentEdgeInsets)
    let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
    titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
    imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: padding)
}

이 문제를 더 나은 방식으로 해결하려면 사용자 지정 UIButton 하위 클래스를 만드는 것이 가장 좋습니다. Apple이 설정을 '재설정'하고있을 수 있습니다.

참조 URL : https://stackoverflow.com/questions/10954880/left-align-image-and-center-text-on-uibutton

반응형