iPhone UIButton - छवि स्थिति


116

मेरे पास एक UIButtonपाठ है "एप्लिकेशन का अन्वेषण करें" और UIImage(>) इसमें Interface Builderऐसा दिखता है:

[ (>) Explore the app ]

लेकिन मुझे इस UIImageपाठ को जगह देने की आवश्यकता है :

[ Explore the app (>) ]

मैं UIImageदाईं ओर कैसे जा सकता हूं ?


आप इंटरफ़ेस बिल्डर का भी उपयोग कर सकते हैं। मेरा जवाब यहां देखें: stackoverflow.com/questions/2765024/…
n8tr

1
कोड की कुछ पंक्तियों के साथ बस इस उपवर्ग का उपयोग करें: github.com/k06a/RTLButton
k06a

जवाबों:


161

मेरा यह समाधान काफी सरल है

[button sizeToFit];
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);

4
यह महान काम करता है! एज इनसेट कॉन्सेप्ट को समझना मुश्किल है। किसी भी विचार क्यों हम दोनों बाएँ और दाएँ किनारे इनसेट सेट करने की आवश्यकता है? सैद्धांतिक रूप से, अगर मैं शीर्षक को बाईं ओर और छवि को दाईं ओर ले जाता हूं, तो यह पर्याप्त होगा। मुझे बाएं और दाएं दोनों को सेट करने की आवश्यकता क्यों है?
PokerIncome.com

3
सबसे अच्छा समाधान मैं हूँ
बिमवा

2
यह जवाब पूरी तरह से काम करता है। स्वीकृत उत्तर सही है, और सही एपीआई डॉक्स को इंगित करता है, लेकिन यह ओपी द्वारा अनुरोध किए जाने के लिए प्रतिलिपि और पेस्ट समाधान है।
मैकलॉघलिनज

जब आप बटन पाठ बदलना शुरू करते हैं तो थोड़ा जटिल हो जाता है। इस मामले में उपवर्ग समाधान ने मेरे लिए बेहतर काम किया।
ब्रैड गॉस

मुझे दिखाने के लिए धन्यवाद कि आपको बाईं और दाईं ओर समान चौड़ाई लागू करना है, मुझे 100% समझ में नहीं आता कि यह कैसे काम करता है (क्योंकि कभी-कभी यह आकार के साथ-साथ उत्पत्ति को भी प्रभावित करेगा) लेकिन मैं इसी तरह के मुद्दों को हल करने में सक्षम रहा हूं इस विधि का उपयोग कर।
टॉबी

128

पर आईओएस 9 के बाद से, लगता है कि इस लक्ष्य को हासिल करने के लिए एक आसान तरीका देखने के अर्थ के लिए मजबूर किया जा सके।

यहां छवि विवरण दर्ज करें

या प्रोग्रामेटिक रूप से, उपयोग करके:

button.semanticContentAttribute = .ForceRightToLeft

4
जितना मुझे आपका उत्तर (+1) पसंद आया, मुझे यह कहने से नफरत है कि ऐसा करने का यह "उचित" तरीका नहीं हो सकता है, लेकिन यह सबसे आसान में से एक है।
farzadshbfn

@farzadshbfn आप सही हैं। मैंने उस शब्द को "सरल" के लिए बदल दिया, अधिक सुसंगत लगता है।
अलविवि

@farzadshbfn ऐसा करने का "उचित" तरीका क्यों नहीं होगा?
सम्मन बिक्रम थापा

3
@SmanmanBikramThapa IMHO को यूबीटटन को उप-समूहित करना और semanticContentAttributeलेआउट को ओवरराइड करना होगा और हमारे लेआउट लॉजिक में सम्मान को बदलने के बजाय semanticContentAttributeस्वयं को बदलना होगा । (बदलते अर्थपूर्ण दृष्टिकोण, अंतर्राष्ट्रीयकरण के साथ अच्छी तरह से काम नहीं करेगा)
farzadshbfn

@farzadshbfn पूरी तरह से सही है। कोई बात नहीं यह जवाब स्कोर सबसे अधिक अंक सही नहीं है - यह दाईं ओर से बाएं इंटरफ़ेस के लिए UX को तोड़ सकता है।
पावेल याकिमेंको

86

सेट करें imageEdgeInsetऔर titleEdgeInsetअपनी छवि के भीतर घटकों को स्थानांतरित करने के लिए। आप उन ग्राफिक्स का उपयोग करके एक बटन भी बना सकते हैं जो पूर्ण आकार का है, और बटन के लिए पृष्ठभूमि छवि के रूप में उपयोग करें (फिर titleEdgeInsetsशीर्षक को स्थानांतरित करने के लिए उपयोग करें)।


8
उपवर्ग लागू करने की तुलना में इनसेट्स को सेट करना बहुत कम कोड है। यह इनसेट्स का पूरा बिंदु है। सब व्यू (जो आपने नहीं बनाया है) के लिए फ्रेम में हेरफेर करना एक हैक की तरह लगता है।
किम आंद्रे सैंड

6
@kimsnarf, सच में? जब भी आप छवि के आकार या शीर्षक की लंबाई में मामूली बदलाव करते हैं तो इनसेट्स को ट्वीक करना बहुत कम काम (और हैक का कम ) है?
कर्क वॉक

54

रेमंड डब्ल्यू का जवाब यहां सबसे अच्छा है। Subclass UIButton कस्टम लेआउट के साथ साक्षात्कार। करने के लिए बेहद सरल है, यहाँ एक लेआउट है जो मेरे लिए काम करता है कार्यान्वयन:

- (void)layoutSubviews
{
    // Allow default layout, then adjust image and label positions
    [super layoutSubviews];

    UIImageView *imageView = [self imageView];
    UILabel *label = [self titleLabel];

    CGRect imageFrame = imageView.frame;
    CGRect labelFrame = label.frame;

    labelFrame.origin.x = imageFrame.origin.x;
    imageFrame.origin.x = labelFrame.origin.x + CGRectGetWidth(labelFrame);

    imageView.frame = imageFrame;
    label.frame = labelFrame;
}

2
यह तरीका उस मामले में बेहतर है जब आपको कई बटन प्रबंधित करने की आवश्यकता होती है, लेकिन मुझे केवल एक बटन बदलने की आवश्यकता है :)
Pavel Yakimenko

2
यदि बटन छवि गलत है, तो लेबल परिणाम गलत है, क्योंकि शायद UIImageView डाला नहीं गया है (iOS2.0 पर परीक्षण किया गया)। आपको केवल संपादन फ्रेम पर विचार करना चाहिए, अगर imageView.image शून्य नहीं है।
स्कैको

2
मैं इस उत्तर के लिए निम्नलिखित सुधार का सुझाव दूंगा ताकि दोनों विचार केन्द्रित रहें: 'CGFloat cumactoryWidth = CGRectGetWidth (imageFrame) + CGRectGetWidth (labelFrame + 10); CGFloat अत्यधिक मात्रा = CGRectGetWidth (self.bounds) - संचयीWidth; labelFrame.origin.x = अत्यधिक मात्रा / 2; imageFrame.origin.x = CGRectGetMaxX (labelFrame) + 10; '
i-konov

यह मेरे लिए iOS 7 पर ब्रेक करता है। कोई और? 8. iOS पर ठीक काम करता है
Rounak

1
IOS7 का बिल्कुल भी समर्थन न करें और आपकी समस्या दूर हो जाएगी। आप इसे वैसे भी नहीं करना चाहिए।
गिल सैंड

30

उपवर्ग UIButtonऔर ओवरराइडिंग के बारे में क्या layoutSubviews?

तब के स्थानों को बाद के प्रसंस्करण self.imageViewऔरself.titleLabel


4
यह सभी अन्य सलाह की तुलना में बहुत आसान है (जैसे ऊपर वाला) हाथ से तैयार किए गए इनसेट का उपयोग करके सब कुछ सही तरीके से करने की कोशिश कर रहा है।
स्टीवन क्रेमर

13

एक और सरल तरीका (जो केवल iOS 9 नहीं है) इन दो तरीकों को ओवरराइड करने के लिए UIButton को उप-वर्ग करना है

override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.titleRectForContentRect(contentRect)
    rect.origin.x = 0
    return rect
}

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

contentEdgeInsets सुपर का उपयोग करके पहले से ही ध्यान में रखा जाता है।


धन्यवाद! मुझे यह पसंद है कि उपवर्ग और ओवरराइड
लेआउट

1
मेरी विनम्र राय में इस बारे में जाने का सबसे अच्छा तरीका :)
DrPatience

9

बटन के लिए is राइट-टू-लेफ्ट ’को मजबूर करना एक विकल्प नहीं है यदि आपका ऐप right लेफ्ट-टू-राइट’ और left राइट-टू-लेफ्ट ’दोनों का समर्थन करता है।

मेरे लिए काम किया समाधान एक उपवर्ग है जिसे स्टोरीबोर्ड में बटन में जोड़ा जा सकता है और बाधाओं के साथ अच्छी तरह से काम करता है (iOS 11 में परीक्षण किया गया):

class ButtonWithImageAtEnd: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let imageView = imageView, let titleLabel = titleLabel {
            let padding: CGFloat = 15
            imageEdgeInsets = UIEdgeInsets(top: 5, left: titleLabel.frame.size.width+padding, bottom: 5, right: -titleLabel.frame.size.width-padding)
            titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageView.frame.width, bottom: 0, right: imageView.frame.width)
        }

    }

}

जहां 'पैडिंग' शीर्षक और छवि के बीच का स्थान होगा।


बेशक .forceRightToLeftएक विकल्प है! बस विपरीत मूल्य ( .forceLeftToRight) का उपयोग करें UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft
मणिमाल

5

स्विफ्ट में:

override func layoutSubviews(){
    super.layoutSubviews()

    let inset: CGFloat = 5

    if var imageFrame = self.imageView?.frame,
       var labelFrame = self.titleLabel?.frame {

       let cumulativeWidth = imageFrame.width + labelFrame.width + inset
       let excessiveWidth = self.bounds.width - cumulativeWidth
       labelFrame.origin.x = excessiveWidth / 2
       imageFrame.origin.x = labelFrame.origin.x + labelFrame.width + inset

       self.imageView?.frame = imageFrame
       self.titleLabel?.frame = labelFrame  
    }
}

4

@Split द्वारा उत्तर का निर्माण ...

जवाब शानदार है, लेकिन यह इस तथ्य को नजरअंदाज करता है कि बटन में कस्टम इमेज और टाइटल एज इनसेट हो सकते हैं जो पहले से सेट हैं (जैसे स्टोरीबोर्ड में)।

उदाहरण के लिए, आप चाह सकते हैं कि छवि में कंटेनर के ऊपर और नीचे से कुछ पैडिंग हो, लेकिन फिर भी छवि को बटन के दाईं ओर ले जाएं।

मैंने इस विधि के साथ अवधारणा को आगे बढ़ाया: -

- (void) moveImageToRightSide {
    [self sizeToFit];

    CGFloat titleWidth = self.titleLabel.frame.size.width;
    CGFloat imageWidth = self.imageView.frame.size.width;
    CGFloat gapWidth = self.frame.size.width - titleWidth - imageWidth;
    self.titleEdgeInsets = UIEdgeInsetsMake(self.titleEdgeInsets.top,
                                            -imageWidth + self.titleEdgeInsets.left,
                                            self.titleEdgeInsets.bottom,
                                            imageWidth - self.titleEdgeInsets.right);

    self.imageEdgeInsets = UIEdgeInsetsMake(self.imageEdgeInsets.top,
                                            titleWidth + self.imageEdgeInsets.left + gapWidth,
                                            self.imageEdgeInsets.bottom,
                                            -titleWidth + self.imageEdgeInsets.right - gapWidth);
}

2
// Get the size of the text and image
CGSize buttonLabelSize = [[self.button titleForState:UIControlStateNormal] sizeWithFont:self.button.titleLabel.font];
CGSize buttonImageSize = [[self.button imageForState:UIControlStateNormal] size];

// You can do this line in the xib too:
self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

// Adjust Edge Insets according to the above measurement. The +2 adds a little space 
self.button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -(buttonLabelSize.width+2));
self.button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, buttonImageSize.width+2);

यह दाएं-संरेखित बटन बनाता है, जैसे:

[           button label (>)]

बटन संदर्भ के अनुसार इसकी चौड़ाई को समायोजित नहीं करता है, इसलिए अंतरिक्ष लेबल के बाईं ओर दिखाई देगा। आप बटन के फ्रेम की चौड़ाई की गणना करके इसे हल कर सकते हैं बटनसेबलसाइज़ और एक्सपायरी बटन।



0

यह समाधान iOS 7 और इसके बाद के संस्करण काम करता है

यूक्बटन को सिर्फ उपवर्ग

@interface UIButton (Image)

- (void)swapTextWithImage;

@end

@implementation UIButton (Image)

- (void)swapTextWithImage {
   const CGFloat kDefaultPadding = 6.0f;
   CGSize buttonSize = [self.titleLabel.text sizeWithAttributes:@{
                                                               NSFontAttributeName:self.titleLabel.font
                                                               }];

   self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView.frame.size.width, 0, self.imageView.frame.size.width);
   self.imageEdgeInsets = UIEdgeInsetsMake(0, buttonSize.width + kDefaultPadding, 0, -buttonSize.width); 
}

@end

उपयोग (अपनी कक्षा में कहीं):

[self.myButton setTitle:@"Any text" forState:UIControlStateNormal];
[self.myButton swapTextWithImage];

0

पिछले उत्तरों पर निर्माण। यदि आप आइकन और बटन के बीच का अंतर चाहते हैं, तो कोड को आंतरिक रूप से आकार के बटन की सीमा से ऊपर लेबल और आइकन के फ्लोटिंग को रोकने के लिए थोड़ा बदलना होगा।

let margin = CGFloat(4.0)
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width)
button.contentEdgeInsets = UIEdgeInsetsMake(0, margin, 0, margin)

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


0

यहाँ मेरा अपना तरीका है, (लगभग 10 साल बाद)

  1. UIButton से उपवर्ग (बटन, जैसा कि हम स्विफ्ट युग में रह रहे हैं)
  2. स्टैक दृश्य में एक छवि और एक लेबल रखो।
class CustomButton: Button {

    var didLayout: Bool = false // The code must be called only once

    override func layoutSubviews() {
        super.layoutSubviews()
        if !didLayout, let imageView = imageView, let titleLabel = titleLabel {
            didLayout = true
            let stack = UIStackView(arrangedSubviews: [titleLabel, imageView])
            addSubview(stack)
            stack.edgesToSuperview() // I use TinyConstraints library. You could handle the constraints directly
            stack.axis = .horizontal
        }
    }
}

0

स्विफ्ट में सिंगल लाइन सॉल्यूशन:

// iOS 9 and Onwards
button.semanticContentAttribute = .forceRightToLeft

यह अच्छा नहीं है क्योंकि यह सभी आरटीएल उपयोगकर्ताओं के लिए लेआउट को तोड़ देगा। आपको उनके लिए दाएं से बाएं बल की आवश्यकता होगी। आप यहां से अन्य समाधान का बेहतर प्रयास करें।
पावेल याकिमेंको
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.