UIButton में छवि के तहत लेबल


158

मैं एक बटन बनाने की कोशिश कर रहा हूं जिसमें आइकन के नीचे कुछ टेक्स्ट हैं (ऐप के बटन की तरह ही) हालांकि इसे हासिल करना काफी मुश्किल लग रहा है। किसी भी विचार कैसे मैं के बारे में जाने के लिए पाठ के साथ छवि के नीचे प्रदर्शित कर सकते हैं UIButton?


यह UIImage और UILabel युक्त UIbutton के एक कस्टम उपवर्ग को बनाने के लिए काफी आसान और उल्लेखनीय है, जैसे आपको आवश्यकता होगी ...
NP Compete

7
या सिर्फ यूआईब्यूटन और यूआईबेल का उपयोग करें।
छापा मारा

आकार और ऑटो लेआउट के साथ सटीक नियंत्रण के लिए, आप यह कोशिश कर सकते हैं: https://github.com/albert-zhang/AZCenterLabelButton( लिंक )
अल्बर्ट झांग

इस समाधान के साथ ठीक काम करता है stackoverflow.com/a/59666154/1576134
श्रेयंक

जवाबों:


111

या आप इस श्रेणी का उपयोग कर सकते हैं:

ObjC

@interface UIButton (VerticalLayout)

- (void)centerVerticallyWithPadding:(float)padding;
- (void)centerVertically;

@end

@implementation UIButton (VerticalLayout)

- (void)centerVerticallyWithPadding:(float)padding {
    CGSize imageSize = self.imageView.frame.size;
    CGSize titleSize = self.titleLabel.frame.size;
    CGFloat totalHeight = (imageSize.height + titleSize.height + padding);
    
    self.imageEdgeInsets = UIEdgeInsetsMake(- (totalHeight - imageSize.height),
                                            0.0f,
                                            0.0f,
                                            - titleSize.width);
    
    self.titleEdgeInsets = UIEdgeInsetsMake(0.0f,
                                            - imageSize.width,
                                            - (totalHeight - titleSize.height),
                                            0.0f);
    
    self.contentEdgeInsets = UIEdgeInsetsMake(0.0f,
                                              0.0f,
                                              titleSize.height,
                                              0.0f);
}

- (void)centerVertically {
    const CGFloat kDefaultPadding = 6.0f;
    [self centerVerticallyWithPadding:kDefaultPadding];
}

@end

स्विफ्ट का विस्तार

extension UIButton {
    
    func centerVertically(padding: CGFloat = 6.0) {
        guard
            let imageViewSize = self.imageView?.frame.size,
            let titleLabelSize = self.titleLabel?.frame.size else {
            return
        }
        
        let totalHeight = imageViewSize.height + titleLabelSize.height + padding
        
        self.imageEdgeInsets = UIEdgeInsets(
            top: -(totalHeight - imageViewSize.height),
            left: 0.0,
            bottom: 0.0,
            right: -titleLabelSize.width
        )
        
        self.titleEdgeInsets = UIEdgeInsets(
            top: 0.0,
            left: -imageViewSize.width,
            bottom: -(totalHeight - titleLabelSize.height),
            right: 0.0
        )
        
        self.contentEdgeInsets = UIEdgeInsets(
            top: 0.0,
            left: 0.0,
            bottom: titleLabelSize.height,
            right: 0.0
        )
    }
    
}

सुझाव: यदि बटन की ऊंचाई से कम है totalHeight, तो छवि बाहर की सीमाओं को आकर्षित करेगी।

imageEdgeInset.top होना चाहिए:

max(0, -(totalHeight - imageViewSize.height))

5
मुझे लगता है कि यह सबसे अच्छा जवाब है क्योंकि यह फ्रेम को मैन्युअल रूप से समायोजित करने के बजाय किनारे का उपयोग करता है। यह ऑटो के लेआउट के साथ बहुत अच्छा काम करता है, जब बटन के सुपरवाइवे में लेआउटसुब्यू से बुलाया जाता है। केवल सुझाव का उपयोग करना है CGRectGetHeight()और CGRectGetWidth()जब imageView और titleLabel ऊंचाई और चौड़ाई प्राप्त कर रहा है।
जेसी

1
जब मैं इस चित्र का उपयोग बटन दृश्य के ऊपर करता हूं, तो मुझे इसे करना चाहिए CGFloat inset = (self.frame.size.height - totalHeight)/2; self.contentEdgeInsets = UIEdgeInsetsMake(inset, 0.0f, inset, 0.0f);
एलेक्स हडले

12
स्विफ्ट एक्सटेंशन ने मेरे लिए इसे सही ढंग से लेआउट नहीं किया।
पैट्रिक

यह काम करता है अगर छवि सेटआईमैज के रूप में सेट की गई थी, सेटबेकग्राउंडइमेज के रूप में नहीं।
आर्गस

1
इस समाधान के साथ ठीक काम करता है stackoverflow.com/a/59666154/1576134
श्रेयंक

87

Xcode में, आप केवल छवि की चौड़ाई को नकारात्मक करने के लिए एज टाइटल लेफ्ट इनसेट सेट कर सकते हैं। यह छवि के केंद्र में लेबल प्रदर्शित करेगा।

छवि के नीचे प्रदर्शित करने के लिए लेबल प्राप्त करने के लिए (ऐप बटन की तरह), आपको कुछ सकारात्मक संख्या के लिए एज टाइटल टॉप इनसेट सेट करने की आवश्यकता हो सकती है।


1
यह ऐसा करने का तरीका है ... जब तक आप कई बटन (विभिन्न आकारों के) के साथ बार-बार ऐसा नहीं कर रहे हैं ... तब तक मेरे पास एरिक डब्ल्यू के समाधान के एक साझा संस्करण के साथ अच्छे परिणाम थे
केनी विंकर

5
बस यह सुनिश्चित करने के लिए कि लोग इसे महसूस करें। मान छवि की नकारात्मक चौड़ाई होना चाहिए, भले ही बटन छवि की चौड़ाई से अधिक हो।
लिरोन

1
इसने मेरे लिए काम नहीं किया। मेरा पाठ अभी भी छवि के दाईं ओर दिखाई देता है, अर्थात इसके नीचे नहीं लपेटता है।
सिंधेलिया

1
@Cindeselia हैरानी की बात है। आपने टॉप इनसेट के लिए कितना बड़ा मूल्य इस्तेमाल किया? शायद इसे और भी बड़ा मान बढ़ाने की कोशिश करें?
क्रिस

3
IOS7 में, यह काम नहीं करता है। लेबल केवल छवि के निचले भाग में जाता है और छिपाया जाता है, अब और नहीं दिखाया जाता है।
बहादुर

50

यह एक सरल केंद्रित शीर्षक बटन है जिसे ओवरराइड करके titleRect(forContentRect:)और स्विफ्ट द्वारा कार्यान्वित किया गया है imageRect(forContentRect:)। यह intrinsicContentSizeAutoLayout के साथ उपयोग के लिए भी लागू होता है ।

import UIKit

class CenteredButton: UIButton
{
    override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
        let rect = super.titleRect(forContentRect: contentRect)

        return CGRect(x: 0, y: contentRect.height - rect.height + 5,
            width: contentRect.width, height: rect.height)
    }

    override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
        let rect = super.imageRect(forContentRect: contentRect)
        let titleRect = self.titleRect(forContentRect: contentRect)

        return CGRect(x: contentRect.width/2.0 - rect.width/2.0,
            y: (contentRect.height - titleRect.height)/2.0 - rect.height/2.0,
            width: rect.width, height: rect.height)
    }

    override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize

        if let image = imageView?.image {
            var labelHeight: CGFloat = 0.0

            if let size = titleLabel?.sizeThatFits(CGSize(width: self.contentRect(forBounds: self.bounds).width, height: CGFloat.greatestFiniteMagnitude)) {
                labelHeight = size.height
            }

            return CGSize(width: size.width, height: image.size.height + labelHeight + 5)
        }

        return size
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        centerTitleLabel()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        centerTitleLabel()
    }

    private func centerTitleLabel() {
        self.titleLabel?.textAlignment = .center
    }
}

5
वह सबसे सही समाधान है। लेकिन आंतरिक सामग्री के आकार के लिए कुछ संशोधन की आवश्यकता है। इसे छवि और लेबल के बीच अधिकतम चौड़ाई वापस आनी चाहिए: CGSizeMake (MAX (labelSize. उपलब्धता, self.imageView.image.size. उपलब्धता), self.imageView.image.size.height + labeleight)
लौटें

39

देखिए स्विफ्ट के इस शानदार जवाब को।

extension UIButton {

    func alignImageAndTitleVertically(padding: CGFloat = 6.0) {
        let imageSize = self.imageView!.frame.size
        let titleSize = self.titleLabel!.frame.size
        let totalHeight = imageSize.height + titleSize.height + padding

        self.imageEdgeInsets = UIEdgeInsets(
            top: -(totalHeight - imageSize.height),
            left: 0,
            bottom: 0,
            right: -titleSize.width
        )

        self.titleEdgeInsets = UIEdgeInsets(
            top: 0,
            left: -imageSize.width,
            bottom: -(totalHeight - titleSize.height),
            right: 0
        )
    }

}

4
यदि आप चाहते हैं कि चित्र लंबवत केंद्रित हो, तो leftइसके imageEdgeInsetsसाथ बदलें(self.frame.size.width - imageSize.width) / 2
elsurudo

यदि आप ऑटोलयूट का उपयोग कर रहे हैं, तो इस विधि layoutSubviews()को अपने पर्यवेक्षक को कॉल करें ।
एलेक्सवोगेल

33

उपवर्ग UIButton। ओवरराइड - layoutSubviewsबिल्ट-इन subviewsनए पदों को स्थानांतरित करने के लिए :

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGRect frame = self.imageView.frame;
    frame = CGRectMake(truncf((self.bounds.size.width - frame.size.width) / 2), 0.0f, frame.size.width, frame.size.height);
    self.imageView.frame = frame;

    frame = self.titleLabel.frame;
    frame = CGRectMake(truncf((self.bounds.size.width - frame.size.width) / 2), self.bounds.size.height - frame.size.height, frame.size.width, frame.size.height);
    self.titleLabel.frame = frame;
}

मुझे व्यक्तिगत रूप से टाइटलबेल y मान को 0 पर सेट करना था और छवि के साथ पाठ प्रदर्शित करने के लिए इसके लिए फ्रेम की ऊँचाई। यह मेरे लिए समझ में नहीं आता है, लेकिन यह काम करता है ... हालांकि मैं अभी भी नियंत्रण स्थापित करने का 'Apple' तरीका सीख रहा हूं।
रस

6
वास्तव में, बेहतर तरीका ओवरराइड titleRectForContentRectऔरimageRectForContentRect
Mazyod

28

Refactored icecrystal23`s जवाब।

स्विफ्ट 3, ऑटोलेयूट्स, एक्सिब, स्टोरीबोर्ड के साथ काम करता है, एनिमेटेड हो सकता है।

मूल icecrystal23 `के उत्तर में बटन एक बुरी तरह से गणना की गई फ्रेम था। मुझे लगता है कि मैंने तय कर लिया है।

संपादित करें: 5 स्विफ्ट के अपडेट किए गए और इंटरफ़ेस बिल्डर / स्टोरीबोर्ड के अंदर काम किया

import UIKit

@IBDesignable
class VerticalButton: UIButton {

    @IBInspectable public var padding: CGFloat = 20.0 {
        didSet {
            setNeedsLayout()
        }
    }

    override var intrinsicContentSize: CGSize {
        let maxSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)

        if let titleSize = titleLabel?.sizeThatFits(maxSize), let imageSize = imageView?.sizeThatFits(maxSize) {
            let width = ceil(max(imageSize.width, titleSize.width))
            let height = ceil(imageSize.height + titleSize.height + padding)

            return CGSize(width: width, height: height)
        }

        return super.intrinsicContentSize
    }

    override func layoutSubviews() {
        if let image = imageView?.image, let title = titleLabel?.attributedText {
            let imageSize = image.size
            let titleSize = title.size()

            titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + padding), right: 0.0)
            imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + padding), left: 0.0, bottom: 0.0, right: -titleSize.width)
        }

        super.layoutSubviews()
    }

}

2
इस के साथ एक समस्या है जब छवि को हटा दिया जाता है। मैं चयनित राज्य के लिए एक छवि का उपयोग कर रहा हूं और डिफ़ॉल्ट राज्य के लिए कोई छवि नहीं है। जब राज्य को चयनित से डिफ़ॉल्ट में बदल दिया जाता है तो लेबल गड़बड़ हो जाता है। तो कुछ सुधारों की आवश्यकता है: छवि दृश्य की जाँच न करें लेकिन 'छवि (के लिए: राज्य)' का उपयोग करें। लेआउट के अन्य विवरण में कोई छवि नहीं होने पर शून्य किनारे इनसेट सेट करें।
मैटिक ओब्लाक

केवल यहाँ समाधान है कि काम करता है। अन्य उत्तर काम करने लगते हैं, लेकिन वास्तव में बटन की सीमा लेबल और छवि के आकार के अनुसार नहीं होती है। इसे देखने के लिए एक पृष्ठभूमि रंग सेट करें।
मैनुएल

यह समाधान काम नहीं किया, मुझे लगता है कि यह एक अनंत लूप के कुछ प्रकार और अंततः Xcode दुर्घटना का कारण बना। मैंने आंतरिक भाग को हटा दिया और यह ठीक काम कर गया (Xcode 11.5)
mojuba

23

यहाँ एक उत्तर को सुधारा:

स्विफ्ट 3:

class CenteredButton: UIButton
{
    override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
        let rect = super.titleRect(forContentRect: contentRect)
        let imageRect = super.imageRect(forContentRect: contentRect)

        return CGRect(x: 0, y: imageRect.maxY + 10,
                      width: contentRect.width, height: rect.height)
    }

    override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
        let rect = super.imageRect(forContentRect: contentRect)
        let titleRect = self.titleRect(forContentRect: contentRect)

        return CGRect(x: contentRect.width/2.0 - rect.width/2.0,
                      y: (contentRect.height - titleRect.height)/2.0 - rect.height/2.0,
                      width: rect.width, height: rect.height)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        centerTitleLabel()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        centerTitleLabel()
    }

    private func centerTitleLabel() {
        self.titleLabel?.textAlignment = .center
    }
}

16

यह एरिक डब्ल्यू के उत्कृष्ट उत्तर का एक संशोधित संस्करण है। लेकिन दृश्य के शीर्ष पर केंद्रित छवि रखने के बजाय, यह छवि और लेबल को एक समूह के रूप में दृश्य में रखता है।

अंतर यह है:

+-----------+
|    ( )    |
|   Hello   |     // Erik W's code
|           |
|           |
+-----------+

बनाम

+-----------+
|           |
|    ( )    |     // My modified version
|   Hello   |
|           |
+-----------+

नीचे स्रोत:

-(void)layoutSubviews {
    [super layoutSubviews];

    CGRect titleLabelFrame = self.titleLabel.frame;
    CGSize labelSize = [self.titleLabel.text sizeWithFont:self.titleLabel.font constrainedToSize:CGSizeMake(self.frame.size.width, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];

    CGRect imageFrame = self.imageView.frame;

    CGSize fitBoxSize = (CGSize){.height = labelSize.height + kTextTopPadding +  imageFrame.size.height, .width = MAX(imageFrame.size.width, labelSize.width)};

    CGRect fitBoxRect = CGRectInset(self.bounds, (self.bounds.size.width - fitBoxSize.width)/2, (self.bounds.size.height - fitBoxSize.height)/2);

    imageFrame.origin.y = fitBoxRect.origin.y;
    imageFrame.origin.x = CGRectGetMidX(fitBoxRect) - (imageFrame.size.width/2);
    self.imageView.frame = imageFrame;

    // Adjust the label size to fit the text, and move it below the image

    titleLabelFrame.size.width = labelSize.width;
    titleLabelFrame.size.height = labelSize.height;
    titleLabelFrame.origin.x = (self.frame.size.width / 2) - (labelSize.width / 2);
    titleLabelFrame.origin.y = fitBoxRect.origin.y + imageFrame.size.height + kTextTopPadding;
    self.titleLabel.frame = titleLabelFrame;
}

FYI करें: यह तब टूट सकता है जब UIView एनिमेशन के साथ जोड़ दिया जाए, क्योंकि उनके दौरान लेआउटसुब्यू कहा जाता है।


क्या लेबल की गणना करने वाली रेखा को self.frame.size. उपलब्धता के बजाय self.bounds.size. उपलब्धता का उपयोग करना चाहिए?
जेरेमी विएबे

16

स्विफ्ट में डेव का समाधान:

override func layoutSubviews() {
    super.layoutSubviews()
    if let imageView = self.imageView {
        imageView.frame.origin.x = (self.bounds.size.width - imageView.frame.size.width) / 2.0
        imageView.frame.origin.y = 0.0
    }
    if let titleLabel = self.titleLabel {
        titleLabel.frame.origin.x = (self.bounds.size.width - titleLabel.frame.size.width) / 2.0
        titleLabel.frame.origin.y = self.bounds.size.height - titleLabel.frame.size.height
    }
}

अच्छा उत्तर। अपने उपवर्ग में @IBDesignable जोड़ें और इसे स्टोरीबोर्ड में देखें।
जोएल टेपली

16

यदि आप उपवर्ग UIButtonऔरoverride layoutSubviews , आप छवि को केंद्र में रखने के लिए नीचे का उपयोग कर सकते हैं और इसके नीचे शीर्षक शीर्षक रख सकते हैं:

kTextTopPadding एक स्थिरांक है जिसे आपको पेश करना होगा जो छवि और उसके नीचे पाठ के बीच की जगह को निर्धारित करता है।

-(void)layoutSubviews {
    [super layoutSubviews];

    // Move the image to the top and center it horizontally
    CGRect imageFrame = self.imageView.frame;
    imageFrame.origin.y = 0;
    imageFrame.origin.x = (self.frame.size.width / 2) - (imageFrame.size.width / 2);
    self.imageView.frame = imageFrame;

    // Adjust the label size to fit the text, and move it below the image
    CGRect titleLabelFrame = self.titleLabel.frame;
    CGSize labelSize = [self.titleLabel.text sizeWithFont:self.titleLabel.font
                                        constrainedToSize:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)
                                        lineBreakMode:NSLineBreakByWordWrapping];
    titleLabelFrame.size.width = labelSize.width;
    titleLabelFrame.size.height = labelSize.height;
    titleLabelFrame.origin.x = (self.frame.size.width / 2) - (labelSize.width / 2);
    titleLabelFrame.origin.y = self.imageView.frame.origin.y + self.imageView.frame.size.height + kTextTopPadding;
    self.titleLabel.frame = titleLabelFrame;

}

8

IOS7 में साइजविथोंट के बाद से केनी विंकर का अपडेट अपडेट किया गया था।

-(void)layoutSubviews {
[super layoutSubviews];

int kTextTopPadding = 3;

CGRect titleLabelFrame = self.titleLabel.frame;

CGRect labelSize = [self.titleLabel.text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGRectGetHeight(self.bounds)) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:self.titleLabel.font} context:nil];

CGRect imageFrame = self.imageView.frame;

CGSize fitBoxSize = (CGSize){.height = labelSize.size.height + kTextTopPadding +  imageFrame.size.height, .width = MAX(imageFrame.size.width, labelSize.size.width)};

CGRect fitBoxRect = CGRectInset(self.bounds, (self.bounds.size.width - fitBoxSize.width)/2, (self.bounds.size.height - fitBoxSize.height)/2);

imageFrame.origin.y = fitBoxRect.origin.y;
imageFrame.origin.x = CGRectGetMidX(fitBoxRect) - (imageFrame.size.width/2);
self.imageView.frame = imageFrame;

// Adjust the label size to fit the text, and move it below the image

titleLabelFrame.size.width = labelSize.size.width;
titleLabelFrame.size.height = labelSize.size.height;
titleLabelFrame.origin.x = (self.frame.size.width / 2) - (labelSize.size.width / 2);
titleLabelFrame.origin.y = fitBoxRect.origin.y + imageFrame.size.height + kTextTopPadding;
self.titleLabel.frame = titleLabelFrame;
}

चूंकि पूर्व iOS 7 अधिक से अधिक पुराना हो रहा है, यह नया स्वीकृत उत्तर होना चाहिए।
महालिफिकेशन

7

IOS 11 / स्विफ्ट 4 में उपरोक्त में से कोई भी उत्तर वास्तव में मेरे लिए काम नहीं करता है। मुझे कुछ उदाहरण मिले और मैंने उस पर अपनी बात रखी:

extension UIButton {

    func centerImageAndButton(_ gap: CGFloat, imageOnTop: Bool) {

      guard let imageView = self.currentImage,
      let titleLabel = self.titleLabel?.text else { return }

      let sign: CGFloat = imageOnTop ? 1 : -1
      self.titleEdgeInsets = UIEdgeInsetsMake((imageView.size.height + gap) * sign, -imageView.size.width, 0, 0);

      let titleSize = titleLabel.size(withAttributes:[NSAttributedStringKey.font: self.titleLabel!.font!])
      self.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + gap) * sign, 0, 0, -titleSize.width)
    }
}

आशा है कि यह किसी की मदद करता है।


उस रोमन का सुझाव देने के लिए धन्यवाद, हालांकि एक मुद्दा है जहां contentEdgeInsets शीर्षक और छवि को पूरी तरह से शामिल नहीं करता है।
पैट्रिक

6

केनी विन्कर के कोड और शिमोन का उपयोग करके मैं यह स्विफ्ट कोड बनाता हूं जो मेरे लिए काम करता है।

import UIKit

@IBDesignable
class TopIconButton: UIButton {
    override func layoutSubviews() {
        super.layoutSubviews()

        let kTextTopPadding:CGFloat = 3.0;

        var titleLabelFrame = self.titleLabel!.frame;


        let labelSize = titleLabel!.sizeThatFits(CGSizeMake(CGRectGetWidth(self.contentRectForBounds(self.bounds)), CGFloat.max))

        var imageFrame = self.imageView!.frame;

        let fitBoxSize = CGSizeMake(max(imageFrame.size.width, labelSize.width), labelSize.height + kTextTopPadding + imageFrame.size.    height)

        let fitBoxRect = CGRectInset(self.bounds, (self.bounds.size.width - fitBoxSize.width)/2, (self.bounds.size.height - fitBoxSize.    height)/2);

        imageFrame.origin.y = fitBoxRect.origin.y;
        imageFrame.origin.x = CGRectGetMidX(fitBoxRect) - (imageFrame.size.width/2);
        self.imageView!.frame = imageFrame;

        // Adjust the label size to fit the text, and move it below the image

        titleLabelFrame.size.width = labelSize.width;
        titleLabelFrame.size.height = labelSize.height;
        titleLabelFrame.origin.x = (self.frame.size.width / 2) - (labelSize.width / 2);
        titleLabelFrame.origin.y = fitBoxRect.origin.y + imageFrame.size.height + kTextTopPadding;
        self.titleLabel!.frame = titleLabelFrame;
        self.titleLabel!.textAlignment = .Center
    }

}

3

आपको बस अपनी छवि और शीर्षक लेबल के आकार के आधार पर सभी तीन एज इनसेट्स को समायोजित करना होगा:

button.contentEdgeInsets = UIEdgeInsetsMake(0, 0, titleLabelBounds.height + 4, 0)
button.titleEdgeInsets = UIEdgeInsetsMake(image.size.height + 8, -image.size.width, 0, 0)
button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -titleLabelBounds.width)

आप इसका पाठ सेट करने के बाद sizeToFit पर कॉल करके शीर्षक लेबल सीमा प्राप्त कर सकते हैं। क्षैतिज रिक्ति पाठ, फ़ॉन्ट और छवि के आकार की परवाह किए बिना काम करना चाहिए, लेकिन मुझे ऊर्ध्वाधर रिक्ति और नीचे सामग्री किनारे इनसेट के अनुरूप होने का एक भी समाधान नहीं पता है।


3

यहाँ एक उपवर्ग के रूप में "भालू विद मी" का जवाब है Swift 2.0। उपयोग करने के लिए यह सिर्फ अपने बटन को सक्रिय वर्ग बदलने Interface Builderके लिएVerticalButton और यह जादुई पूर्वावलोकन अद्यतन करेगा।

मैंने इसे स्वतः पूर्ण करने के लिए सही आंतरिक सामग्री आकार की गणना करने के लिए भी अपडेट किया।

import UIKit

@IBDesignable

class VerticalButton: UIButton {
    @IBInspectable var padding: CGFloat = 8

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        update()
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        update()
    }

    func update() {
        let imageBounds = self.imageView!.bounds
        let titleBounds = self.titleLabel!.bounds
        let totalHeight = CGRectGetHeight(imageBounds) + padding + CGRectGetHeight(titleBounds)

        self.imageEdgeInsets = UIEdgeInsets(
            top: -(totalHeight - CGRectGetHeight(imageBounds)),
            left: 0,
            bottom: 0,
            right: -CGRectGetWidth(titleBounds)
        )

        self.titleEdgeInsets = UIEdgeInsets(
            top: 0,
            left: -CGRectGetWidth(imageBounds),
            bottom: -(totalHeight - CGRectGetHeight(titleBounds)),
            right: 0
        )
    }

    override func intrinsicContentSize() -> CGSize {
        let imageBounds = self.imageView!.bounds
        let titleBounds = self.titleLabel!.bounds

        let width = CGRectGetWidth(imageBounds) > CGRectGetWidth(titleBounds) ? CGRectGetWidth(imageBounds) : CGRectGetWidth(titleBounds)
        let height = CGRectGetHeight(imageBounds) + padding + CGRectGetHeight(titleBounds)

        return CGSizeMake(width, height)
    }
}

2
एक अनंत लूप के रूप में समाप्त होता है जहां layoutSubviews()मेरे मामले में बार-बार कॉल किया जाता है: intrinsicContentSizeएक्सेस imageViewजिसे layoutSubviewsकॉल किया जाता है जो एक्सेस करता है imageViewआदि
ctietze

3

@ टियागो मैं इस तरह आपका जवाब बदलता हूं। यह सभी आकारों के साथ ठीक काम करता है

func alignImageAndTitleVertically(padding: CGFloat = 5.0) {
        self.sizeToFit()
        let imageSize = self.imageView!.frame.size
        let titleSize = self.titleLabel!.frame.size
        let totalHeight = imageSize.height + titleSize.height + padding

        self.imageEdgeInsets = UIEdgeInsets(
            top: -(totalHeight - imageSize.height),
            left: 0,
            bottom: 0,
            right: -titleSize.width
        )

        self.titleEdgeInsets = UIEdgeInsets(
            top: 0,
            left: 0,
            bottom: -(totalHeight - titleSize.height),
            right: titleSize.height
        )
    }

3

मैंने यहां उत्तरों का संयोजन लिया और एक के साथ आया जो मेरे लिए काम कर रहा था, स्विफ्ट में। मैं प्यार नहीं करता कि कैसे मैं सिर्फ इनसेट्स को ओवररोड करता हूं, लेकिन यह काम करता है। मैं टिप्पणियों में सुझाए गए सुधारों के लिए खुला रहूंगा। यह sizeToFit()ऑटो लेआउट के साथ और उसके साथ सही ढंग से काम करने लगता है ।

import UIKit

/// A button that displays an image centered above the title.  This implementation 
/// only works when both an image and title are set, and ignores
/// any changes you make to edge insets.
class CenteredButton: UIButton
{
    let padding: CGFloat = 0.0

    override func layoutSubviews() {
        if imageView?.image != nil && titleLabel?.text != nil {
            let imageSize: CGSize = imageView!.image!.size
            titleEdgeInsets = UIEdgeInsetsMake(0.0, -imageSize.width, -(imageSize.height + padding), 0.0)
            let labelString = NSString(string: titleLabel!.text!)
            let titleSize = labelString.sizeWithAttributes([NSFontAttributeName: titleLabel!.font])
            imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + padding), 0.0, 0.0, -titleSize.width)
            let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
            contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0)
        }
        super.layoutSubviews()
    }

    override func sizeThatFits(size: CGSize) -> CGSize {
        let defaultSize = super.sizeThatFits(size)
        if let titleSize = titleLabel?.sizeThatFits(size),
        let imageSize = imageView?.sizeThatFits(size) {
            return CGSize(width: ceil(max(imageSize.width, titleSize.width)), height: ceil(imageSize.height + titleSize.height + padding))
        }
        return defaultSize
    }

    override func intrinsicContentSize() -> CGSize {
        let size = sizeThatFits(CGSize(width: CGFloat.max, height: CGFloat.max))
        return size
    }
}

3

इस दो विधियों का उपयोग करें:

func titleRect(forContentRect contentRect: CGRect) -> CGRect
func imageRect(forContentRect contentRect: CGRect) -> CGRect

उदाहरण:

class VerticalButton: UIButton {

  override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
    let titleRect = super.titleRect(forContentRect: contentRect)
    let imageRect = super.imageRect(forContentRect: contentRect)

    return CGRect(x: 0,
                  y: contentRect.height - (contentRect.height - padding - imageRect.size.height - titleRect.size.height) / 2 - titleRect.size.height,
                  width: contentRect.width,
                  height: titleRect.height)
  }

  override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
    let imageRect = super.imageRect(forContentRect: contentRect)
    let titleRect = self.titleRect(forContentRect: contentRect)

    return CGRect(x: contentRect.width/2.0 - imageRect.width/2.0,
                  y: (contentRect.height - padding - imageRect.size.height - titleRect.size.height) / 2,
                  width: imageRect.width,
                  height: imageRect.height)
  }

  private let padding: CGFloat
  init(padding: CGFloat) {
    self.padding = padding

    super.init(frame: .zero)
    self.titleLabel?.textAlignment = .center
  }

  required init?(coder aDecoder: NSCoder) { fatalError() }
}

extension UIButton {

  static func vertical(padding: CGFloat) -> UIButton {
    return VerticalButton(padding: padding)
  }
}

और आप उपयोग कर सकते हैं:

let myButton = UIButton.vertical(padding: 6)

3

स्विफ्ट 5 - नीचे विधि मेरे लिए काम करती है

func centerVerticallyWithPadding(padding : CGFloat) {
        guard
            let imageViewSize = self.imageView?.frame.size,
            let titleLabelSize = self.titleLabel?.frame.size else {
            return
        }

        let totalHeight = imageViewSize.height + titleLabelSize.height + padding

        self.imageEdgeInsets = UIEdgeInsets(
            top: max(0, -(totalHeight - imageViewSize.height)),
            left: 0.0,
            bottom: 0.0,
            right: -titleLabelSize.width
        )

        self.titleEdgeInsets = UIEdgeInsets(
            top: (totalHeight - imageViewSize.height),
            left: -imageViewSize.width,
            bottom: -(totalHeight - titleLabelSize.height),
            right: 0.0
        )

        self.contentEdgeInsets = UIEdgeInsets(
            top: 0.0,
            left: 0.0,
            bottom: titleLabelSize.height,
            right: 0.0
        )
    }

सुनिश्चित करें कि आपका बटन शीर्षक स्टोरीबोर्ड में छोटा नहीं है / xib
समाधान 2 के लिए जाएं

class SVVerticalButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()
        let padding : CGFloat = 2.0
        if let imageView = self.imageView {
            imageView.frame.origin.x = (self.bounds.size.width - imageView.frame.size.width) / 2.0
            imageView.frame.origin.y = max(0,(self.bounds.size.height - (imageView.frame.size.height + (titleLabel?.frame.size.height ?? 0.0) + padding)) / 2.0)
        }
        if let titleLabel = self.titleLabel {
            titleLabel.frame.origin.x = 0
            titleLabel.frame.origin.y = self.bounds.size.height - titleLabel.frame.size.height
            titleLabel.frame.size.width = self.bounds.size.width
            titleLabel.textAlignment = .center
        }
    }

}

2

मैंने पाया कि शिमोन का उत्तर शायद सबसे अच्छा था, लेकिन यह मुझे कुछ बटन पर अजीब परिणाम दे रहा था और मैं सिर्फ इसलिए काम नहीं कर सकता था। इसलिए आधार के रूप में उनके जवाब का उपयोग करते हुए मैंने अपने बटन नीचे दिए अनुसार लागू किए:

#define PADDING 2.0f

@implementation OOButtonVerticalImageText

-(CGSize) intrinsicContentSize {
  CGSize size = [super intrinsicContentSize];
  CGFloat labelHeight = 0.0f;
  CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake([self contentRectForBounds:self.bounds].size.width, CGFLOAT_MAX)];
  labelHeight = titleSize.height;
  return CGSizeMake(MAX(titleSize.width, self.imageView.image.size.width), self.imageView.image.size.height + labelHeight + PADDING);
}

-(void) layoutSubviews {
  [super layoutSubviews];

  CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake([self contentRectForBounds:self.bounds].size.width, CGFLOAT_MAX)];
  self.titleLabel.frame = CGRectMake((self.bounds.size.width - titleSize.width)/2.0f,
                                     self.bounds.size.height - titleSize.height - PADDING,
                                     titleSize.width,
                                     titleSize.height);

  CGSize ivSize = self.imageView.frame.size;
  self.imageView.frame = CGRectMake((self.bounds.size.width - ivSize.width)/2.0f,
                                    self.titleLabel.frame.origin.y - ivSize.height - PADDING,
                                    ivSize.width,
                                    ivSize.height);
}

@end

1

यहाँ मेरा उपवर्ग है UIButtonजो इस समस्या को हल करता है:

@implementation MyVerticalButton

@synthesize titleAtBottom; // BOOL property

- (id)initWithFrame:(CGRect)frame
{
  self = [super initWithFrame:frame];
  if (self) {
    self.titleAtBottom = YES;
  }
  return self;
}

- (CGSize)sizeThatFits:(CGSize)size {
  self.titleLabel.text = [self titleForState: self.state];

  UIEdgeInsets imageInsets = self.imageEdgeInsets;
  UIEdgeInsets titleInsets = self.titleEdgeInsets;

  CGSize imageSize = [self imageForState: self.state].size;
  if (!CGSizeEqualToSize(imageSize, CGSizeZero)) {
    imageSize.width += imageInsets.left + imageInsets.right;
    imageSize.height += imageInsets.top + imageInsets.bottom;

  }

  CGSize textSize = [self.titleLabel sizeThatFits: CGSizeMake(size.width - titleInsets.left - titleInsets.right,
                                                              size.height -(imageSize.width +
                                                                            titleInsets.top+titleInsets.bottom))];
  if (!CGSizeEqualToSize(textSize, CGSizeZero)) {
    textSize.width += titleInsets.left + titleInsets.right;
    textSize.height += titleInsets.top + titleInsets.bottom;
  }

  CGSize result = CGSizeMake(MAX(textSize.width, imageSize.width),
                             textSize.height + imageSize.height);
  return result;
}

- (void)layoutSubviews {
  // needed to update all properities of child views:
  [super layoutSubviews];

  CGRect bounds = self.bounds;

  CGRect titleFrame = UIEdgeInsetsInsetRect(bounds, self.titleEdgeInsets);
  CGRect imageFrame = UIEdgeInsetsInsetRect(bounds, self.imageEdgeInsets);
  if (self.titleAtBottom) {
    CGFloat titleHeight = [self.titleLabel sizeThatFits: titleFrame.size].height;
    titleFrame.origin.y = CGRectGetMaxY(titleFrame)-titleHeight;
    titleFrame.size.height = titleHeight;
    titleFrame = CGRectStandardize(titleFrame);
    self.titleLabel.frame = titleFrame;

    CGFloat imageBottom = CGRectGetMinY(titleFrame)-(self.titleEdgeInsets.top+self.imageEdgeInsets.bottom);
    imageFrame.size.height = imageBottom - CGRectGetMinY(imageFrame);
    self.imageView.frame = CGRectStandardize(imageFrame);
  } else {
    CGFloat titleHeight = [self.titleLabel sizeThatFits: titleFrame.size].height;
    titleFrame.size.height = titleHeight;
    titleFrame = CGRectStandardize(titleFrame);
    self.titleLabel.frame = titleFrame;

    CGFloat imageTop = CGRectGetMaxY(titleFrame)+(self.titleEdgeInsets.bottom+self.imageEdgeInsets.top);
    imageFrame.size.height = CGRectGetMaxY(imageFrame) - imageTop;
    self.imageView.frame = CGRectStandardize(imageFrame);
  }
}

- (void)setTitleAtBottom:(BOOL)newTitleAtBottom {
  if (titleAtBottom!=newTitleAtBottom) {
    titleAtBottom=newTitleAtBottom;
    [self setNeedsLayout];
  }
}

@end

बस। आकर्षण की तरह काम करता है। समस्या दिखाई दे सकती है यदि शीर्षक और पाठ को फिट करने के लिए बटन छोटा होगा।


यह वास्तव में एक आकर्षण की तरह काम करता है! और ऑटो लेआउट के साथ भी। इस समाधान को साझा करने के लिए बहुत बहुत धन्यवाद। मैं इस के साथ पागल हो रहा था और अपने खुद के UIControl उपवर्ग बनाने के लिए सहारा ले रहा था।
valeCocoa

1

मुझे लगता है कि ऐसा करने का एक सबसे अच्छा तरीका है कि यूबूटन को उप-वर्ग करके और कुछ रेंडरिंग तरीकों को ओवरराइड करें:

- (void)awakeFromNib
{
    [super awakeFromNib];
    [self setupSubViews];
}

- (instancetype)init
{
    if (self = [super init])
    {
        [self setupSubViews];
    }
    return self;
}

- (void)setupSubViews
{
    [self.imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
    [self.titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[imageView][titleLabel]|" options:NSLayoutFormatAlignAllCenterX metrics:nil views:@{@"imageView": self.imageView, @"titleLabel": self.titleLabel}]];
}

- (CGSize)intrinsicContentSize
{
    CGSize imageSize = self.imageView.image.size;
    CGSize titleSize = [self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: self.titleLabel.font}];
    return CGSizeMake(MAX(imageSize.width, titleSize.width), imageSize.height + titleSize.height);
}

1

@ उद्देश्य-सी में शिमोन का समाधान

#import "CenteredButton.h"

@implementation CenteredButton

- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGRect rect = [super titleRectForContentRect: contentRect];
    return CGRectMake(0,
                      contentRect.size.height - rect.size.height - 5,
                      contentRect.size.width,
                      rect.size.height);
}

- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGRect rect = [super imageRectForContentRect: contentRect];
    CGRect titleRect = [self titleRectForContentRect: contentRect];

    return CGRectMake(contentRect.size.width / 2.0 - rect.size.width / 2.0,
                      (contentRect.size.height - titleRect.size.height)/2.0 - rect.size.height/2.0,
                      rect.size.width,
                      rect.size.height);
}

- (CGSize)intrinsicContentSize {
    CGSize imageSize = [super intrinsicContentSize];

    if (self.imageView.image) {
        UIImage* image = self.imageView.image;
        CGFloat labelHeight = 0.0;

        CGSize labelSize = [self.titleLabel sizeThatFits: CGSizeMake([self contentRectForBounds: self.bounds].size.width, CGFLOAT_MAX)];
        if (CGSizeEqualToSize(imageSize, labelSize)) {
            labelHeight = imageSize.height;
        }

        return CGSizeMake(MAX(labelSize.width, imageSize.width), image.size.height + labelHeight + 5);
    }

    return imageSize;
}

- (id) initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
     if (self) {
         [self centerTitleLabel];
     }
    return self;

}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self centerTitleLabel];
    }
    return self;
}

- (void)centerTitleLabel {
    self.titleLabel.textAlignment = NSTextAlignmentCenter;
}

@end

मुझे लगता है कि यहां आंतरिक घुसपैठ सही नहीं है। मुझे समझ नहीं आ रहा है कि CGSizeEqualToSize वाला हिस्सा क्या है, लेकिन आपके पास केवल लेबल आकार> 0 है यदि लेबल का आकार UILabel के आंतरिक नियंत्रण से मेल खाता है। यह केवल CGSizeMake(MAX(labelSize.width, image.size.width), image.size.height + labelSize.height + 5.0)मामले में लौटने के लिए पर्याप्त होना चाहिए
ओलिवर

1

यदि आप कस्टम फोंट का उपयोग कर रहे हैं तो टाइटललैब के आकार की गणना ठीक से काम नहीं करेगी, आपको इसे बदल देना चाहिए

let titleLabelSize = self.titleLabel?.text?.size(withAttributes: [NSAttributedStringKey.font: self.titleLabel!.font!])


1

एज और एज इनसेट के साथ आइकन और टेक्स्ट को पोजिशन देने की कोशिश करने के बजाय, आप एक अटैचमेंट के रूप में अपनी छवि के साथ एक NSAttributedString बना सकते हैं और इसके बजाय अपने बटन के शीर्षक वाले शीर्षक पर सेट कर सकते हैं:

let titleText = NSAttributedString(string: yourTitle, attributes: attributes)
let imageAttachment = NSTextAttachment()
imageAttachment.image = yourImage

let title = NSMutableAttributedString(string: "")
title.append(NSAttributedString(attachment: imageAttachment))
title.append(titleText)

button.setAttributedTitle(title, for: .normal)

ओप्स प्रश्न के लिए काम नहीं करता है जहां पाठ को छवि के नीचे केंद्रित किया जाना चाहिए । एक UIButtonपाठ क्षेत्र लेआउट केवल 1 पंक्ति प्रदर्शित करने के लिए है, इसलिए यह तब भी काम नहीं करता है जब किसी स्ट्रिंग में पंक्ति विराम का उपयोग किया जाता है। अन्यथा एक अच्छा समाधान होगा।
मैनुएल

यह button.titleLabel?.numberOfLinesआवश्यक है कि लाइनों की आवश्यक संख्या प्राप्त करने के लिए सेट करें
swearwolf

1

स्थानीयकरण के अनुकूल समाधान:

इतने सारे महान समाधान दोस्तों, लेकिन मैं स्थानीयकरण का उपयोग करने वालों के लिए यहां एक नोट जोड़ना चाहूंगा।

LtR से RtL तक भाषा की दिशा में बदलाव के मामले में बटन को सही ढंग से लगाने के लिए आपको बाएँ और दाएँ EdgeInstets मानों को उल्टा करने की आवश्यकता है।

इसी तरह के समाधान का उपयोग करके मैं इसे इस प्रकार लागू करूंगा:

extension UIButton {

    func alignVertical(spacing: CGFloat, lang: String) {
        guard let imageSize = self.imageView?.image?.size,
            let text = self.titleLabel?.text,
            let font = self.titleLabel?.font
        else { return }

        let labelString = NSString(string: text)
        let titleSize = labelString.size(
            withAttributes: [NSAttributedString.Key.font: font]
        )

        var titleLeftInset: CGFloat = -imageSize.width
        var titleRigtInset: CGFloat = 0.0

        var imageLeftInset: CGFloat = 0.0
        var imageRightInset: CGFloat = -titleSize.width

        if Locale.current.languageCode! != "en" { // If not Left to Right language
            titleLeftInset = 0.0
            titleRigtInset = -imageSize.width

            imageLeftInset = -titleSize.width
            imageRightInset = 0.0
        }

        self.titleEdgeInsets = UIEdgeInsets(
            top: 0.0,
            left: titleLeftInset,
            bottom: -(imageSize.height + spacing),
            right: titleRigtInset
        )
        self.imageEdgeInsets = UIEdgeInsets(
            top: -(titleSize.height + spacing),
            left: imageLeftInset,
            bottom: 0.0,
            right: imageRightInset
        )
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsets(
            top: edgeOffset,
            left: 0.0,
            bottom: edgeOffset,
            right: 0.0
        )
    }
}

1
कई गैर-अंग्रेजी एलटीआर भाषाएं हैं। आप बटन पर प्रभावीUserInterfaceLayoutDirection की जाँच करना बेहतर समझते हैं।
एलेक्स जेंडर

1

UIButton को उपवर्ग के साथ शीर्ष छवि और नीचे शीर्षक बटन

class VerticalButton: UIButton {
  override func layoutSubviews() {
    super.layoutSubviews()
    let padding: CGFloat = 8
    let iH = imageView?.frame.height ?? 0
    let tH = titleLabel?.frame.height ?? 0
    let v: CGFloat = (frame.height - iH - tH - padding) / 2
    if let iv = imageView {
      let x = (frame.width - iv.frame.width) / 2
      iv.frame.origin.y = v
      iv.frame.origin.x = x
    }

    if let tl = titleLabel {
      let x = (frame.width - tl.frame.width) / 2
      tl.frame.origin.y = frame.height - tl.frame.height - v
      tl.frame.origin.x = x
    }
  }
}

1

यह निश्चित रूप से इस सवाल के लिए एक ओवरकिल है, हालांकि ... मेरी एक परियोजना में मुझे पहली बार बाईं ओर स्थित आइकन के साथ एक बटन लागू करना पड़ा। तब हमें छवि के तहत शीर्षक के साथ एक और बटन मिला। मैंने एक मौजूदा समाधान के लिए खोज की लेकिन कोई भाग्य नहीं है, इसलिए यहां संरेखण बटन जाता है:

@IBDesignable
class AlignableButton: UIButton {

override class var requiresConstraintBasedLayout: Bool {
    return true
}

@objc enum IconAlignment: Int {
    case top, left, right, bottom
}

// MARK: - Designables
@IBInspectable var iconAlignmentValue: Int {
    set {
        iconAlignment = IconAlignment(rawValue: newValue) ?? .left
    }
    get {
        return iconAlignment.rawValue
    }
}

var iconAlignment: IconAlignment = .left

@IBInspectable var titleAlignmentValue: Int {
    set {
        titleAlignment = NSTextAlignment(rawValue: newValue) ?? .left
    }
    get {
        return titleAlignment.rawValue
    }
}

var titleAlignment: NSTextAlignment = .left

// MARK: - Corner Radius
@IBInspectable
var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set {
        layer.masksToBounds = (newValue != 0)
        layer.cornerRadius = newValue
    }
}

// MARK: - Content size
override var intrinsicContentSize: CGSize {
    
    switch iconAlignment {
    case .top, .bottom:
        return verticalAlignedIntrinsicContentSize
    
    default:
        return super.intrinsicContentSize
    }
}

private var verticalAlignedIntrinsicContentSize: CGSize {
    
    if let imageSize = imageView?.intrinsicContentSize,
        let labelSize = titleLabel?.intrinsicContentSize {
        
        let width = max(imageSize.width, labelSize.width) + contentEdgeInsets.left + contentEdgeInsets.right
        let height = imageSize.height + labelSize.height + contentEdgeInsets.top + contentEdgeInsets.bottom
        
        return CGSize(
            width: ceil(width),
            height: ceil(height)
        )
    }
    
    return super.intrinsicContentSize
}

// MARK: - Image Rect
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
    
    switch iconAlignment {
    case .top:
        return topAlignedImageRect(forContentRect: contentRect)
    case .bottom:
        return bottomAlignedImageRect(forContentRect: contentRect)
    case .left:
        return leftAlignedImageRect(forContentRect: contentRect)
    case .right:
        return rightAlignedImageRect(forContentRect: contentRect)
    }
}

func topAlignedImageRect(forContentRect contentRect: CGRect) -> CGRect {
    let rect = super.imageRect(forContentRect: contentRect)
    
    let x = (contentRect.width - rect.width) / 2.0 + contentRect.minX
    let y = contentRect.minY
    let w = rect.width
    let h = rect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: imageEdgeInsets)
}

func bottomAlignedImageRect(forContentRect contentRect: CGRect) -> CGRect {
    let rect = super.imageRect(forContentRect: contentRect)
    
    let x = (contentRect.width - rect.width) / 2.0 + contentRect.minX
    let y = contentRect.height - rect.height + contentRect.minY
    let w = rect.width
    let h = rect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: imageEdgeInsets)
}

func leftAlignedImageRect(forContentRect contentRect: CGRect) -> CGRect {
    let rect = super.imageRect(forContentRect: contentRect)
    
    let x = contentRect.minX
    let y = (contentRect.height - rect.height) / 2 + contentRect.minY
    let w = rect.width
    let h = rect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: imageEdgeInsets)
}

func rightAlignedImageRect(forContentRect contentRect: CGRect) -> CGRect {
    let rect = super.imageRect(forContentRect: contentRect)
    
    let x = (contentRect.width - rect.width) + contentRect.minX
    let y = (contentRect.height - rect.height) / 2 + contentRect.minY
    let w = rect.width
    let h = rect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: imageEdgeInsets)
}

// MARK: - Title Rect
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
    
    switch iconAlignment {
    case .top:
        return topAlignedTitleRect(forContentRect: contentRect)
    case .bottom:
        return bottomAlignedTitleRect(forContentRect: contentRect)
    case .left:
        return leftAlignedTitleRect(forContentRect: contentRect)
    case .right:
        return rightAlignedTitleRect(forContentRect: contentRect)
    }
}

func topAlignedTitleRect(forContentRect contentRect: CGRect) -> CGRect {
    
    let rect = super.titleRect(forContentRect: contentRect)

    let x = contentRect.minX
    let y = contentRect.height - rect.height + contentRect.minY
    let w = contentRect.width
    let h = rect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: titleEdgeInsets)
}

func bottomAlignedTitleRect(forContentRect contentRect: CGRect) -> CGRect {
    
    let rect = super.titleRect(forContentRect: contentRect)
    
    let x = contentRect.minX
    let y = contentRect.minY
    let w = contentRect.width
    let h = rect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: titleEdgeInsets)
}

func leftAlignedTitleRect(forContentRect contentRect: CGRect) -> CGRect {
    
    let titleRect = super.titleRect(forContentRect: contentRect)
    let imageRect = self.imageRect(forContentRect: contentRect)
    
    let x = imageRect.width + imageRect.minX
    let y = (contentRect.height - titleRect.height) / 2.0 + contentRect.minY
    let w = contentRect.width - imageRect.width * 2.0
    let h = titleRect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: titleEdgeInsets)
}

func rightAlignedTitleRect(forContentRect contentRect: CGRect) -> CGRect {
    
    let titleRect = super.titleRect(forContentRect: contentRect)
    let imageRect = self.imageRect(forContentRect: contentRect)

    let x = contentRect.minX + imageRect.width
    let y = (contentRect.height - titleRect.height) / 2.0 + contentRect.minY
    let w = contentRect.width - imageRect.width * 2.0
    let h = titleRect.height
    
    return CGRect(
        x: x,
        y: y,
        width: w,
        height: h
    ).inset(by: titleEdgeInsets)
}

// MARK: - Lifecycle
override func awakeFromNib() {
    super.awakeFromNib()
    
    titleLabel?.textAlignment = titleAlignment
}

override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()
    
    titleLabel?.textAlignment = titleAlignment
}
}

उम्मीद है यह आपको उपयोगी होगा।


0

UIButtonउपवर्ग के अंदर कुछ इस तरह

public override func layoutSubviews() {
    super.layoutSubviews()

    imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 0, 0)
    titleEdgeInsets = UIEdgeInsetsMake(0, -bounds.size.width/2 - 10, -30, 0)
}

0

यह बहुत आसान है।

इसके अलावा:

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

इसे इस्तेमाल करो:

   button.setBackgroundImage(UIImage(named: "image", forState: .Normal)

तब आप आसानी से उपयोग कर बटन पर पाठ जोड़ सकते हैं:

// button.titleLabel! .font = UIFont (नाम: "FontName", आकार: 30)

 button.setTitle("TitleText", forState: UIControlState.Normal)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.