UIButton এ চিত্রের নিচে লেবেল


158

আমি একটি বোতাম তৈরি করার চেষ্টা করছি যা আইকনের নীচে কিছু পাঠ্য রয়েছে (অ্যাপ্লিকেশন বোতামগুলির মতো সাজানো) তবে এটি অর্জন করা বেশ কঠিন বলে মনে হচ্ছে। কোনও ধারণা কীভাবে আমি এটির সাথে চিত্রের নীচে প্রদর্শিত পাঠ্য পেতে পারি UIButton?


আপনার যেমন প্রয়োজন এমন একটি ইউআইআইজেজ এবং ইউআইএলবেলযুক্ত UIbutton এর একটি কাস্টম সাবক্লাস তৈরি করা মোটামুটি সহজ এবং করণীয় ...
এনপি প্রতিযোগিতা

7
অথবা কেবল একটি ইউআইবাটন এবং ইউআইএলবেল ব্যবহার করুন।
রেডিফাইভ

আকার এবং স্বয়ংক্রিয় বিন্যাসের সাথে সঠিকভাবে নিয়ন্ত্রণ করতে, আপনি এটি চেষ্টা করতে পারেন: https://github.com/albert-zhang/AZCenterLabelButton( লিঙ্ক )
অ্যালবার্ট জাং

এই সমাধান সঙ্গে কাজ করে জরিমানা stackoverflow.com/a/59666154/1576134
Shreyank

উত্তর:


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
Shreyank

87

এক্সকোডে, আপনি কেবলমাত্র চিত্রের প্রস্থকে ঘৃণিত করতে এজ শিরোনাম বাম ইনসেটটি সেট করতে পারেন। এটি চিত্রের কেন্দ্রে লেবেলটি প্রদর্শন করবে।

চিত্রটির নীচে প্রদর্শিত লেবেলটি পেতে (অ্যাপ্লিকেশন বোতামগুলির মতো বাছাই), আপনাকে কিছু ধনাত্মক সংখ্যায় এজ শিরোনাম শীর্ষের ইনসেট সেট করতে হতে পারে।


1
এটি করার উপায় এটি ... আপনি যদি বার বার কয়েকটি বোতাম (বিভিন্ন আকারের) দিয়ে না করে থাকেন ... তবে এরিক
ডাব্লু'র

5
লোকেরা এটি উপলব্ধি করতে পারে তা নিশ্চিত করার জন্য। বোতামটি চিত্রের প্রস্থের চেয়ে প্রশস্ত হলেও, মানটি চিত্রের নেতিবাচক প্রস্থ হওয়া উচিত।
লিরন

1
এটি আমার পক্ষে কার্যকর হয়নি। আমার পাঠ্যটি এখনও চিত্রের ডানদিকে প্রদর্শিত হয়, এর নিচে মোড়ানো হয় না।
সিন্ডেসেলিয়া

1
@ সিন্ডেসেলিয়া আশ্চর্যজনক। টপ ইনসেটের জন্য আপনি কত বড় মানের ব্যবহার করেছেন? এটি আরও বৃহত্তর মান বাড়ানোর চেষ্টা করতে পারেন?
ক্রিস

3
আইওএস 7-তে, এটি কার্যকর হয়নি বলে মনে হচ্ছে। লেবেল কেবল চিত্রের নীচে চলে যায় এবং লুকানো থাকে, আর প্রদর্শিত হয় না।
সাহসী

50

এটি একটি সাধারণ কেন্দ্রিক শিরোনাম বোতাম যা সুইফারে ওভাররাইড করে titleRect(forContentRect:)এবং দ্বারা প্রয়োগ করা হয় imageRect(forContentRect:)। এটি intrinsicContentSizeঅটোলআউট সহ ব্যবহারের জন্য প্রয়োগ করে ।

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
এটিই সর্বাধিক সঠিক সমাধান। তবে অভ্যন্তরীণ সামগ্রীর আকারের জন্য কিছু সংশোধন প্রয়োজন। এটি চিত্র এবং লেবেলের মধ্যে MAX প্রস্থকে ফিরে আসতে হবে: CGSizeMake (MAX (labelSize.width, self.imageView.image.size.width), self.imageView.image.size.height + লেবেল হাইট)
কিরান্ডার

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

চিত্রের সাথে টেক্সটটি প্রদর্শনের জন্য আমাকে ব্যক্তিগতভাবে শিরোনাম লেবেল ওয়াই মানটি 0 এবং ফ্রেমের উচ্চতায় উচ্চতা নির্ধারণ করতে হয়েছিল। এটি আমার কাছে বোধগম্য নয় তবে এটি কাজ করে ... যদিও আমি এখনও নিয়ন্ত্রণ স্থাপনের 'অ্যাপল' পদ্ধতি শিখছি।
রুশ

6
আসলে, আরও ভাল উপায় ওভাররাইড করা titleRectForContentRectএবংimageRectForContentRect
মজইড

28

রিফ্যাক্টর আইসক্রিস্টাল 23 এর উত্তর।

সুইফট 3, অটোলেআউটস, এক্সিব, স্টোরিবোর্ডগুলির সাথে কাজ করে অ্যানিমেটেড করা যায়।

অরজিনাল আইসক্রিস্টাল 23 এর উত্তরের বোতামটি খুব খারাপভাবে গণনা করা ফ্রেম পেয়েছিল। আমি মনে করি আমি এটি স্থির করেছি।

সম্পাদনা করুন: সুইফ্ট 5 এ আপডেট হয়েছে এবং ইন্টারফেস বিল্ডার / স্টোরিবোর্ডের ভিতরে কাজ করেছে made

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
চিত্রটি সরানো হলে এ নিয়ে একটি সমস্যা রয়েছে। আমি নির্বাচিত রাজ্যের জন্য একটি চিত্র ব্যবহার করছি এবং ডিফল্ট রাজ্যের জন্য কোনও চিত্র নেই। যখন রাষ্ট্রটি নির্বাচিত থেকে ডিফল্ট হয়ে যায় তখন লেবেলটি গণ্ডগোল হয়। সুতরাং কয়েকটি সংশোধন করা দরকার: চিত্রের ভিউ চেক করবেন না তবে 'চিত্র (এর জন্য: রাষ্ট্র)' ব্যবহার করুন। লেআউটসুউভিউগুলির বিবৃতিতে কোনও চিত্র না থাকলে শূন্য প্রান্তের ইনসেটগুলি সেট করুন Set
ম্যাটিক ওব্লাক

শুধুমাত্র সমাধান এখানে কাজ করে। অন্যান্য উত্তরগুলি কাজ করে বলে মনে হচ্ছে তবে লেবেল এবং চিত্রের আকার অনুযায়ী বোতামের সীমানা পুনরায় আকার দেয় না। এটি দেখতে একটি পটভূমি রঙ সেট করুন।
ম্যানুয়েল

এই সমাধানটি কাজ করে না, আমি মনে করি এটি একরকম এক অসীম লুপ এবং শেষ পর্যন্ত এক্সকোড ক্রাশের কারণ হয়েছিল। আমি অন্তর্নিহিত অংশটি সরিয়েছি এবং এটি দুর্দান্ত কাজ করেছে (এক্সকোড ১১.৫)
ইন্টারসিনিকট্যান্টসাইজ এক্সকোড মোজুবা

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

এফওয়াইআই: ইউআইভিউ অ্যানিমেশনগুলির সাথে একত্রিত হয়ে এটি ভেঙে যেতে পারে, কারণ লেআউটসুভ্যুভিউগুলি তাদের সময় বলা হয়।


লাইনের আকার নির্ধারণকারী লাইনটি সেলফ.ফ্রেম.সাইজ.উইথের পরিবর্তে স্ব.বাউন্ডস.সাইজ.উইথ ব্যবহার করা উচিত নয়?
জেরেমি ওয়েইব

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

সাইজ উইথফন্টের আইওএস in-তে অবমূল্যায়ন করা হওয়ার পর থেকে কেনি উইঙ্কারের উত্তর আপডেট হয়েছে।

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

প্রাক আইওএস 7 যেহেতু আরও বেশি পুরানো হয়ে আসছে, এটি নতুন গ্রহণযোগ্য উত্তর হওয়া উচিত।
মেহলিফিকেশন

7

আইওএস 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)
    }
}

আশা করি এটি কাউকে সাহায্য করবে।


রোমানকে পরামর্শ দেওয়ার জন্য ধন্যবাদ, যদিও এমন একটি সমস্যা রয়েছে যেখানে বিষয়বস্তু এজজেন্সগুলি শিরোনাম এবং চিত্র পুরোপুরি অন্তর্ভুক্ত করে না।
প্যাট্রিক

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)

আপনি এর পাঠ্য নির্ধারণের পরে সাইজটিফিট কল করে শিরোনাম লেবেল সীমানা পেতে পারেন। অনুভূমিক ব্যবধানটি পাঠ্য, ফন্ট এবং চিত্রের আকার নির্বিশেষে কাজ করা উচিত তবে আমি উল্লম্ব ফাঁক এবং নীচের বিষয়বস্তু প্রান্তটি ইনসেট সুসংগতভাবে পেতে একটি একক সমাধানের বিষয়ে জানি না।


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

আপনার বোতামের শিরোনামটি স্টোরিবোর্ডে / ছাঁটাই না করে অন্যথায় সমাধান 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

এটাই. মোহন মত কাজ করে। শিরোনাম এবং পাঠ্য মাপসই করতে বোতামটি ছোট হয়ে গেলে সমস্যাটি উপস্থিত হতে পারে।


এটি সত্যই একটি মোহন মত কাজ করে! এবং অটো লেআউট সহও। এই সমাধান ভাগ করে নেওয়ার জন্য অনেক ধন্যবাদ। আমি এটি দিয়ে বাদাম যাচ্ছিলাম এবং আমার নিজের ইউআইসিএন্ট্রোল সাবক্লাস তৈরি করতে অবলম্বন করছি।
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 রয়েছে যদি লেবেল আকারটি ইউআইএবেলের অন্তর্নিহিত কনসেন্টসাইজের সাথে মেলে। এটি যদি কেবলমাত্র ক্ষেত্রে ফিরে 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

আইকনটি এবং প্রান্তের ইনসেটগুলি সহ পাঠ্যকে অবস্থান দেওয়ার চেষ্টা করার পরিবর্তে আপনি একটি চিত্র সংযুক্তি হিসাবে একটি এনএসএট্রিবিউটেড স্ট্রিং তৈরি করতে পারেন এবং পরিবর্তে এটি আপনার বোতামের বিশিষ্ট শিরোনামে সেট করতে পারেন:

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

স্থানীয়করণ বন্ধুত্বপূর্ণ সমাধান:

অনেক দুর্দান্ত সমাধান ছেলেগুলি, তবে আমি এখানে স্থানীয়করণ ব্যবহারকারীদের জন্য একটি নোট যুক্ত করতে চাই।

এলটিআরটি থেকে আরটিএল ভাষার ভাষার পরিবর্তনের ক্ষেত্রে বাটনটি সঠিকভাবে আউট করার জন্য আপনার বাম এবং ডান এজ এজেন্টস মানগুলি বিপরীত করতে হবে।

অনুরূপ সমাধান ব্যবহার করে আমি এটি নিম্নলিখিত হিসাবে প্রয়োগ করব:

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
অনেকগুলি অ-ইংরাজী এলটিআর ভাষা রয়েছে। আপনি বোতামের কার্যকর ইউজার ইন্টারফেসলয়েআউটডাইরেকশনটি পরীক্ষা করা ভাল।
অ্যালেক্সান্ডার আকার্স

1

উপক্লাসিং ইউআইবাটন সহ শীর্ষ চিত্র এবং নীচের শিরোনাম বোতাম

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)

তারপরে আপনি সহজেই ব্যবহার করে বোতামটিতে পাঠ্য যোগ করতে পারেন:

// বাটন.টাইটেল লেবেল! .ফন্ট = ইউআইফন্ট (নাম: "ফন্টনাম", আকার: 30)

 button.setTitle("TitleText", forState: UIControlState.Normal)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.