ইউআইবাটন: ইমেজএডজেইনেসেটস এবং শিরোনামএডজিনসেটস ব্যবহার করে একটি চিত্র এবং পাঠ্যকে কীভাবে কেন্দ্র করবেন?


159

আমি যদি একটি বোতামে কেবল একটি চিত্র রাখি এবং চিত্রের অ্যাডজিনেটসটিকে শীর্ষের আরও কাছে সেট করি তবে চিত্রটি কেন্দ্রীভূত থাকে এবং সমস্ত প্রত্যাশা অনুযায়ী কাজ করে:

[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];

যদি আমি একটি বোতামে কেবল একটি পাঠ্য রেখে শিরোনামএডজিনসেটগুলি নীচে আরও কাছাকাছি সেট করি তবে পাঠ্যটি কেন্দ্রীভূত থাকে এবং সমস্ত প্রত্যাশা অনুযায়ী কাজ করে:

[button setTitle:title forState:UIControlStateNormal];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];

তবে, আমি যদি 4 টি লাইন একসাথে রাখি তবে পাঠ্যটি চিত্রটির সাথে হস্তক্ষেপ করে এবং উভয়ই কেন্দ্র বিন্যাসটি হারাবে।

আমার সমস্ত চিত্রের 30 পিক্সেল প্রস্থ রয়েছে এবং আমি যদি 308 টি UIEgegennestMake এর বাম প্যারামিটারে সেটিটলএডিজিনসেটের জন্য রাখি তবে পাঠ্যটি আবার কেন্দ্রীভূত হবে। সমস্যাটি হ'ল চিত্রটি কখনই কেন্দ্রীভূত হয় না কারণ এটি প্রদর্শিত হয় এটি বোতামের উপর নির্ভর করে it শিরোনামের আকারের ab আমি ইতিমধ্যে বোতামের আকার, চিত্রের আকার, শিরোনাম লেবেলের আকার সহ অনেকগুলি গণনার চেষ্টা করেছি এবং কখনই উভয়কে পুরোপুরি কেন্দ্রিকভাবে পাই না।

কারও ইতিমধ্যে একই সমস্যা ছিল?

উত্তর:


412

এটি মূল্যবান কিসের জন্য, কোনও যাদু সংখ্যা ব্যবহার না করেই পাঠ্যের উপরে কেন্দ্রে অবস্থিত চিত্রের এক সাধারণ সমাধান's নোট করুন যে নিম্নলিখিত কোডটি পুরানো এবং আপনার সম্ভবত নীচের আপডেট হওয়া সংস্করণগুলির একটি ব্যবহার করা উচিত :

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and push it right so it appears centered
//  above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

নীচের সংস্করণে iOS 7+ সমর্থন করার জন্য পরিবর্তনগুলি রয়েছে যা নীচের মন্তব্যে সুপারিশ করা হয়েছে। আমি নিজেই এই কোডটি পরীক্ষা করি নি, সুতরাং আমি নিশ্চিত নই যে এটি কতটা ভাল কাজ করে বা আইওএস-এর পূর্ববর্তী সংস্করণগুলির অধীনে ব্যবহৃত হয় তা ভেঙে যায় কিনা।

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and push it right so it appears centered
//  above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);

সুইফ্ট 5.0 সংস্করণ

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

    titleEdgeInsets = UIEdgeInsets(
      top: 0.0,
      left: -imageSize.width,
      bottom: -(imageSize.height + spacing),
      right: 0.0
    )

    let titleSize = text.size(withAttributes: [.font: font])
    imageEdgeInsets = UIEdgeInsets(
      top: -(titleSize.height + spacing),
      left: 0.0,
      bottom: 0.0, right: -titleSize.width
    )

    let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
    contentEdgeInsets = UIEdgeInsets(
      top: edgeOffset,
      left: 0.0,
      bottom: edgeOffset,
      right: 0.0
    )
  }
}

5
আশ্চর্য - ধন্যবাদ! আমি মনে করি অন্যান্য অনেক উত্তর এই "শক্ত পথে" সম্পর্কে যায় - এটি আরও ভাল দেখাচ্ছে looks
জো

3
আমি ওঠার জন্য উপরেরটি পেয়েছি, তবে কীভাবে তা করার জন্য আমার কোনও মানসিক মডেল নেই। স্বতন্ত্র এজজিস্টস প্যারামিটারগুলি কী জিনিসগুলি প্রভাবিত করে তার চিত্রের ব্যাখ্যার জন্য যে কেউ লিঙ্ক পেয়েছে? এবং কেন পাঠ্য প্রস্থ পরিবর্তন হবে?
রবার্ট অ্যাটকিনস

3
বোতামটি ফিট করার জন্য যখন চিত্রটি সঙ্কুচিত করা হচ্ছে তখন এটি কাজ করে না। এটি প্রদর্শিত হয় যে ইউআইবাটন (অন্তত আইওএস 7 এ) ইমেজ.সাইজটি ব্যবহার করে, এর জন্য গণনা কেন্দ্রিক করে রাখার জন্য চিত্র ভিউ.ফ্রেম.সাইজ নয়।
ড্যান জ্যাকসন

5
@ হেম্যাং এবং ড্যান জ্যাকসন, আমি নিজের পরামর্শগুলি নিজেই পরীক্ষা না করেই যুক্ত করছি। আমি এটিকে হাস্যকর বলে মনে করি যে আমি এটি প্রথমটি আইওএস 4 এর জন্য লিখেছিলাম এবং এই বহু সংস্করণের পরেও আমাদের এখনও এ জাতীয় স্পষ্ট বৈশিষ্ট্য পেতে অপরিহার্য ইঞ্জিনিয়ার অ্যাপলের লেআউট অ্যালগরিদমটি আবশ্যক। বা কমপক্ষে আমি ধরে নিয়েছি যে উপাখ্যানগুলির ধারাবাহিক ধারা এবং নীচে সমান হ্যাকিশ উত্তরগুলি (অপমানের উদ্দেশ্যে নয়) থেকে এখনও এর চেয়ে ভাল সমাধান আর নেই।
জেসি ক্রসন

5
আইওএস 8-তে, আমি বোতামের পাঠ্যটি কখনই বদলে যাবে তার button.currentTitleপরিবর্তে ব্যবহার করা আরও ভাল found এখনই জনবহুল, পরিবর্তনের ক্ষেত্রে ধীর গতি হতে পারে যা ভুল স্বাক্ষরিত কীটপতঙ্গ হতে পারে। button.titleLabel.textcurrentTitletitleLabel.text
মজংদা

59

কিভাবে পাওয়া যায়।

প্রথমে titleLabel(শৈলীর কারণে, যেমন, গা bold়, তির্যক ইত্যাদি) পাঠ্যটি কনফিগার করুন । তারপরে, setTitleEdgeInsetsআপনার চিত্রের প্রস্থ বিবেচনা করে ব্যবহার করুন:

[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:10.0]];

// Left inset is the negative of image width.
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -25.0, 0.0)]; 

এর পরে, setTitleEdgeInsetsপাঠ্য সীমার প্রস্থ বিবেচনা করে ব্যবহার করুন :

[button setImage:image forState:UIControlStateNormal];

// Right inset is the negative of text bounds width.
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -button.titleLabel.bounds.size.width)];

এখন চিত্র এবং পাঠ্য কেন্দ্রিক হবে (এই উদাহরণে, চিত্রটি পাঠ্যের উপরে প্রদর্শিত হবে)।

চিয়ার্স।


3
7 বছর, মানুষ। সত্যিই মনে নেই। আমি যখন জিজ্ঞাসা করেছি, আমি নিজের উত্তর দিয়েছি (আমার উত্তরটি তখনকার একমাত্র ছিল)। বর্তমান নির্বাচিত উত্তরের লেখক যখন সেই ম্যাজিক সংখ্যাগুলি মুছে ফেলার বিষয়ে ফোকাস করেছিলেন তখন আমি নির্বাচিত উত্তর পরিবর্তন করেছি। সুতরাং, নির্বাচিত উত্তরে, আপনি কী বোঝাতে চেয়েছেন তা বুঝতে পারেন।
রিনালডলকম্যান 21

20

আপনি এই সুইফট এক্সটেনশানটি দিয়ে এটি করতে পারেন, যা জেসি ক্রোসেনের উত্তরের অংশ ভিত্তিতে ছিল:

extension UIButton {
  func centerLabelVerticallyWithPadding(spacing:CGFloat) {
    // update positioning of image and title
    let imageSize = self.imageView.frame.size
    self.titleEdgeInsets = UIEdgeInsets(top:0,
                                        left:-imageSize.width,
                                        bottom:-(imageSize.height + spacing),
                                        right:0)
    let titleSize = self.titleLabel.frame.size
    self.imageEdgeInsets = UIEdgeInsets(top:-(titleSize.height + spacing),
                                        left:0,
                                        bottom: 0,
                                        right:-titleSize.width)

    // reset contentInset, so intrinsicContentSize() is still accurate
    let trueContentSize = CGRectUnion(self.titleLabel.frame, self.imageView.frame).size
    let oldContentSize = self.intrinsicContentSize()
    let heightDelta = trueContentSize.height - oldContentSize.height
    let widthDelta = trueContentSize.width - oldContentSize.width
    self.contentEdgeInsets = UIEdgeInsets(top:heightDelta/2.0,
                                          left:widthDelta/2.0,
                                          bottom:heightDelta/2.0,
                                          right:widthDelta/2.0)
  }
}

এটি এমন একটি ফাংশন সংজ্ঞায়িত করে centerLabelVerticallyWithPaddingযা শিরোনাম এবং চিত্রের ইনসেটগুলি যথাযথভাবে সেট করে।

এটি এজেন্টস ইনসেটস সামগ্রীও সেট করে, যা আমার বিশ্বাস এটি নিশ্চিত করার জন্য প্রয়োজনীয় intrinsicContentSize এখনও সঠিকভাবে কাজ করে , যা অটো লেআউট ব্যবহার করা দরকার।

আমি বিশ্বাস করি যে সমস্ত সমাধানগুলি সাবক্লাস ইউআইবাটনটি প্রযুক্তিগতভাবে অবৈধ, যেহেতু আপনার ইউআইকিট নিয়ন্ত্রণগুলি সাবক্লাস করার কথা নয়। অর্থাত, তাত্ত্বিকভাবে তারা ভবিষ্যতে মুক্তি পেতে পারে।


IOS9 এ পরীক্ষা করা হচ্ছে। চিত্রটি কেন্দ্রীভূত হয়, তবে পাঠ্যটি বামে প্রদর্শিত হয় :(
এন্ডেভিড

13

সম্পাদনা করুন: সুইফট 3-এর জন্য আপডেট হয়েছে

আপনি যদি জেসি ক্রসনের উত্তরের একটি দ্রুত সমাধানের সন্ধান করছেন, আপনি এটি ইউআইবাটন এর একটি সাবক্লাসে যুক্ত করতে পারেন:

override func layoutSubviews() {

    let spacing: CGFloat = 6.0

    // lower the text and push it left so it appears centered
    //  below the image
    var titleEdgeInsets = UIEdgeInsets.zero
    if let image = self.imageView?.image {
        titleEdgeInsets.left = -image.size.width
        titleEdgeInsets.bottom = -(image.size.height + spacing)
    }
    self.titleEdgeInsets = titleEdgeInsets

    // raise the image and push it right so it appears centered
    //  above the text
    var imageEdgeInsets = UIEdgeInsets.zero
    if let text = self.titleLabel?.text, let font = self.titleLabel?.font {
        let attributes = [NSFontAttributeName: font]
        let titleSize = text.size(attributes: attributes)
        imageEdgeInsets.top = -(titleSize.height + spacing)
        imageEdgeInsets.right = -titleSize.width
    }
    self.imageEdgeInsets = imageEdgeInsets

    super.layoutSubviews()
}

9

এখানে কয়েকটি দুর্দান্ত উদাহরণ রয়েছে, তবে একাধিক পাঠ্য পাঠ্য (পাঠ্য মোড়ানো) নিয়ে কাজ করার সময় আমি সব ক্ষেত্রে এটি কাজ করতে পারি না। অবশেষে এটি কাজে আসার জন্য আমি কয়েকটি কৌশল একত্রিত করেছি:

  1. আমি উপরে জেসি ক্রসনের উদাহরণ ব্যবহার করেছি। যাইহোক, আমি একটি পাঠ্যের উচ্চতার সমস্যাটি স্থির করেছি এবং আমি একটি অনুভূমিক পাঠ্য মার্জিন নির্দিষ্ট করার ক্ষমতা যুক্ত করেছি। পাঠ্য মোড়ানোর সময় প্রান্তিকতা কার্যকর হয় যাতে এটি বোতামের প্রান্তে আঘাত না করে:

    // the space between the image and text
    CGFloat spacing = 10.0;
    float   textMargin = 6;
    
    // get the size of the elements here for readability
    CGSize  imageSize   = picImage.size;
    CGSize  titleSize   = button.titleLabel.frame.size;
    CGFloat totalHeight = (imageSize.height + titleSize.height + spacing);      // get the height they will take up as a unit
    
    // lower the text and push it left to center it
    button.titleEdgeInsets = UIEdgeInsetsMake( 0.0, -imageSize.width +textMargin, - (totalHeight - titleSize.height), +textMargin );   // top, left, bottom, right
    
    // the text width might have changed (in case it was shortened before due to 
    // lack of space and isn't anymore now), so we get the frame size again
    titleSize = button.titleLabel.bounds.size;
    
    button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0.0, 0.0, -titleSize.width );     // top, left, bottom, right        
  2. মোড়ানোর জন্য আপনি পাঠ্য লেবেলটি সেটআপ করেছেন তা নিশ্চিত করুন

    button.titleLabel.numberOfLines = 2; 
    button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
    button.titleLabel.textAlignment = UITextAlignmentCenter;
  3. এটি বেশিরভাগ ক্ষেত্রে এখন কাজ করবে। তবে, আমার কাছে কিছু বোতাম ছিল যা তাদের চিত্রটি সঠিকভাবে রেন্ডার করবে না। চিত্রটি হয় ডান বা বাম দিকে দূরে স্থানান্তরিত হয়েছিল (এটি কেন্দ্রিক ছিল না)। তাই আমি চিত্রের ভিউকে কেন্দ্রীভূত করতে বাধ্য করতে একটি ইউআইবাটন লেআউট ওভাররাইড কৌশল ব্যবহার করেছি।

    @interface CategoryButton : UIButton
    @end
    
    @implementation CategoryButton
    
    - (void)layoutSubviews
    {
        // Allow default layout, then center imageView
        [super layoutSubviews];
    
        UIImageView *imageView = [self imageView];
        CGRect imageFrame = imageView.frame;
        imageFrame.origin.x = (int)((self.frame.size.width - imageFrame.size.width)/ 2);
        imageView.frame = imageFrame;
    }
    @end

দেখে মনে হচ্ছে এটি একটি ভাল সমাধান, তবে বাটনটি করা উচিত নয় tTitleLabel.numberOfLines 0 টি এমন হওয়া উচিত যা এটি যতটা লাইন চায় তাই হতে পারে?
বেন লাচম্যান

আমার ক্ষেত্রে, আমি কেবল দুটি লাইন চেয়েছিলাম। অন্যথায়, ছবিটির বোতামের সামগ্রিক আকারের সমস্যাগুলি থাকবে would
টড কানিংহাম

9

আমি @ টডকানিংহামের উত্তরের জন্য একটি পদ্ধতি তৈরি করেছি

 -(void) AlignTextAndImageOfButton:(UIButton *)button
 {
   CGFloat spacing = 2; // the amount of spacing to appear between image and title
   button.imageView.backgroundColor=[UIColor clearColor];
   button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
   button.titleLabel.textAlignment = UITextAlignmentCenter;
   // get the size of the elements here for readability
   CGSize imageSize = button.imageView.frame.size;
   CGSize titleSize = button.titleLabel.frame.size;

  // lower the text and push it left to center it
  button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height   + spacing), 0.0);

  // the text width might have changed (in case it was shortened before due to 
  // lack of space and isn't anymore now), so we get the frame size again
   titleSize = button.titleLabel.frame.size;

  // raise the image and push it right to center it
  button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, -     titleSize.width);
 }

7

এক্সকোড 11+ এর জন্য আপডেট হয়েছে

আমার আসল উত্তরে বর্ণিত ইনসেটগুলি এক্সকোডের আরও সাম্প্রতিক সংস্করণগুলিতে আকার পরিদর্শকের কাছে সরিয়ে নেওয়া হয়েছে। স্যুইচটি কখন ঘটেছে সে সম্পর্কে আমি 100% স্পষ্ট নই তবে পাঠকগণের আকারের পরিদর্শকের পর্যালোচনা করা উচিত যদি বৈশিষ্ট্য পরিদর্শকের মধ্যে ইনসেট তথ্য না পাওয়া যায়। নীচে নতুন ইনসেট স্ক্রিনের একটি নমুনা দেওয়া হয়েছে (11.5 হিসাবে আকারের বৈশিষ্ট্য পরিদর্শকের শীর্ষে অবস্থিত)।

insets_moved_to_size_inspector

আসল উত্তর

অন্যান্য উত্তরগুলির সাথে কোনওরকম ভুল নেই, তবে আমি কেবল লক্ষ করতে চেয়েছিলাম যে কোডটি শূন্য লাইন ব্যবহার করে এক্সকোডের মধ্যে একই আচরণটি দৃশ্যত সম্পাদন করা যায়। এই সমাধানটি কার্যকর যদি আপনার কোনও গণনা করা মানের প্রয়োজন না হয় বা স্টোরিবোর্ড / এক্সিব দিয়ে তৈরি করা হয় (অন্যথায় অন্যান্য সমাধান প্রয়োগ করা হয়)।

দ্রষ্টব্য - আমি বুঝতে পারি যে ওপি-র প্রশ্নটি একটি প্রয়োজনীয় কোড। আমি কেবল এই উত্তরটি সম্পূর্ণতার জন্য এবং স্টোরিবোর্ড / xibs ব্যবহারকারীদের জন্য একটি যৌক্তিক বিকল্প হিসাবে সরবরাহ করছি।

প্রান্ত ইনসেটগুলি ব্যবহার করে কোনও বোতামের চিত্র, শিরোনাম এবং সামগ্রী ভিউগুলিতে স্পেসিং সংশোধন করতে আপনি বোতামটি / নিয়ন্ত্রণ নির্বাচন করতে পারেন এবং বৈশিষ্ট্য পরিদর্শকটি খুলতে পারেন। পরিদর্শকের মাঝের দিকে নীচে স্ক্রোল করুন এবং এজ ইনসেটের বিভাগটি সন্ধান করুন।

প্রান্ত insets

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

মেনু-অপশন


আমি যা বুঝতে পারি না তা হ'ল কেন আমি কিছু মূল্যবোধের জন্য স্টোরিবোর্ডে নেতিবাচক সংখ্যা লিখতে পারি না।
ড্যানিয়েল টি।

এটি কি নতুন সুইফ্ট সংস্করণের জন্য কাজ করে? আমি এজ বৈশিষ্ট্যটি কোথাও খুঁজে পাচ্ছি না
ব্রোকহ্যাম্পটন

@brockhampton - নতুন অবস্থানের জন্য আপডেট উত্তর দেখার
Tommie সি

6

সিস্টেমের সাথে লড়াই করবেন না। যদি আপনার লেআউটগুলি ইন্টারফেস বিল্ডার + সম্ভবত কিছু সাধারণ কনফিগারেশন কোড ব্যবহার করে পরিচালনা করতে খুব জটিল হয়ে ওঠে তবে বিন্যাসগুলি সরলভাবে ম্যানুয়ালি করে করুনlayoutSubviews - এটাই তার জন্য! অন্য সব কিছুই হ্যাকের পরিমাণ হবে।

একটি UIButton সাবক্লাস তৈরি করুন এবং layoutSubviewsপ্রোগ্রামক্রমে আপনার পাঠ্য এবং চিত্র প্রান্তিককরণের জন্য এর পদ্ধতিটি ওভাররাইড করুন । বা https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h এর মতো কিছু ব্যবহার করুন যাতে আপনি একটি ব্লক ব্যবহার করে বিন্যাসআউটভিউ বাস্তবায়ন করতে পারেন।


6

সাবক্লাস ইউআইবাটন

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat spacing = 6.0;
    CGSize imageSize = self.imageView.image.size;
    CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(self.frame.size.width, self.frame.size.height - (imageSize.height + spacing))];
    self.imageView.frame = CGRectMake((self.frame.size.width - imageSize.width)/2, (self.frame.size.height - (imageSize.height+spacing+titleSize.height))/2, imageSize.width, imageSize.height);
    self.titleLabel.frame = CGRectMake((self.frame.size.width - titleSize.width)/2, CGRectGetMaxY(self.imageView.frame)+spacing, titleSize.width, titleSize.height);
}

6

সুইফট 4 এর জন্য জেসি ক্রসনের আপডেট উত্তর :

extension UIButton {
    func alignVertical(spacing: CGFloat = 6.0) {
        guard let imageSize = self.imageView?.image?.size,
            let text = self.titleLabel?.text,
            let font = self.titleLabel?.font
            else { return }
        self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
        let labelString = NSString(string: text)
        let titleSize = labelString.size(withAttributes: [kCTFontAttributeName as NSAttributedStringKey: font])
        self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
    }
}

এইভাবে ব্যবহার করুন:

override func viewDidLayoutSubviews() {
    button.alignVertical()
}

অনেক পরে, অনেক ঘন্টা। এটিই কেবল কাজ করেছিল :)
হ্যারি ব্লু

4

কোডটির এই অংশের সাথে আপনি এই জাতীয় কিছু পাবেন শিরোনাম এবং চিত্র প্রান্তিককরণ

extension UIButton {
    func alignTextUnderImage() {
        guard let imageView = imageView else {
                return
        }
        self.contentVerticalAlignment = .Top
        self.contentHorizontalAlignment = .Center
        let imageLeftOffset = (CGRectGetWidth(self.bounds) - CGRectGetWidth(imageView.bounds)) / 2//put image in center
        let titleTopOffset = CGRectGetHeight(imageView.bounds) + 5
        self.imageEdgeInsets = UIEdgeInsetsMake(0, imageLeftOffset, 0, 0)
        self.titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset, -CGRectGetWidth(imageView.bounds), 0, 0)
    }
}

2
আমি পজিশনিং ইমেজ এবং বোতামের ভিতরে টেক্সট জন্য ছোট এক্সটেনশন লিখেছি। আপনি যদি আগ্রহী হন তবে এখানে উত্স কোড। github.com/sssbohdan/ ButtonAlignmentExistance
বোহদান সাভিচ

4

সুইফট 3+ সিনট্যাক্স সহ ইউআইবাটন এক্সটেনশন :

extension UIButton {
    func alignImageAndTitleVertically(padding: CGFloat = 6.0) {
        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.size(attributes: [NSFontAttributeName: titleLabel!.font])
        self.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + padding), 0.0, 0.0, -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0)
    }
}

আসল উত্তর: https://stackoverflow.com/a/7199529/3659227


3

জেসি ক্রসনের উত্তরে কেবল একটি সামান্য পরিবর্তন যা এটি আমার পক্ষে পুরোপুরি কার্যকর হয়েছিল:

পরিবর্তে:

CGSize titleSize = button.titleLabel.frame.size;

আমি এটি ব্যবহার করেছি:

CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName:button.titleLabel.font}];

তাই আপনাকে স্বাগতম! পৃথক উত্তর যুক্ত করার পরিবর্তে (একটি স্বল্প পরিবর্তনের জন্য) আপনি সরাসরি এটি জেসিকে লিখতে পারেন যাতে সে তার [স্বীকৃত] উত্তরটি সঠিকভাবে পরীক্ষা করতে এবং আপডেট করতে পারে (প্রয়োজনে)।
হেমানং

3

button.titleLabel.frame.size.widthলেবেলটি কেটে ফেলা না হওয়ায় যথেষ্ট দীর্ঘ সময় ব্যবহার করা সূক্ষ্ম কাজ করে । যখন লেবেল পাঠ্য কেটে ফেলা হয় তবে পজিশনিং কাজ করে না। গ্রহণ

CGSize titleSize = [[[button titleLabel] text] sizeWithFont:[[button titleLabel] font]];

লেবেল পাঠ্য কেটে ফেলা হলেও আমার জন্য কাজ করে।


আপনার বাটন টাইপ আছে
ভিম্বিম

2

আমি বিদ্যমান উত্তরগুলির দিকে নজর রেখেছি তবে আমি এটিও দেখতে পেয়েছি যে বোতামের ফ্রেমটি সেট করা একটি গুরুত্বপূর্ণ প্রথম পদক্ষেপ।

এখানে আমি একটি ফাংশন ব্যবহার করি যা এটির যত্ন নেয়:

const CGFloat kImageTopOffset   = -15;
const CGFloat kTextBottomOffset = -25;

+ (void) centerButtonImageTopAndTextBottom: (UIButton*)         button 
                                     frame: (CGRect)            buttonFrame
                                      text: (NSString*)         textString
                                 textColor: (UIColor*)          textColor
                                      font: (UIFont*)           textFont
                                     image: (UIImage*)          image
                                  forState: (UIControlState)    buttonState
{
    button.frame = buttonFrame;

    [button setTitleColor: (UIColor*)       textColor
                 forState: (UIControlState) buttonState];

    [button setTitle: (NSString*) textString
            forState: (UIControlState) buttonState ];


    [button.titleLabel setFont: (UIFont*) textFont ];

    [button setTitleEdgeInsets: UIEdgeInsetsMake( 0.0, -image.size.width, kTextBottomOffset,  0.0)]; 

    [button setImage: (UIImage*)       image 
            forState: (UIControlState) buttonState ];

    [button setImageEdgeInsets: UIEdgeInsetsMake( kImageTopOffset, 0.0, 0.0,- button.titleLabel.bounds.size.width)];
}

2

অথবা আপনি কেবল এই বিভাগটি ব্যবহার করতে পারেন:

@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);

}


- (void)centerVertically
{  
    const CGFloat kDefaultPadding = 6.0f;

    [self centerVerticallyWithPadding:kDefaultPadding];  
}  


@end

1
এটি কাস্টম ফন্টের সাথে কাজ করবে না। CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
আইওএস 7+

1

আমার ব্যবহারের মামলাগুলি পোকামাকড়কে নিয়ন্ত্রণহীন করে তুলেছে:

  1. বাটনে ব্যাকগ্রাউন্ড চিত্রটি ধারাবাহিক থাকে
  2. গতিশীল পাঠ্য এবং চিত্রের পরিবর্তন যেখানে স্ট্রিং দৈর্ঘ্য এবং চিত্রের আকার পৃথক হয়

এটিই আমি শেষ করেছিলাম এবং এতে আমি বেশ খুশি:

  • একটি পটভূমি চিত্র (ঝাপসা এবং রঙের সাথে বৃত্তাকার বৃত্ত) দিয়ে স্টোরিবোর্ডে বোতামটি তৈরি করুন।

  • আমার শ্রেণিতে একটি ইউআইআইমেজভিউ ঘোষণা করুন:

    @implementation BlahViewController {
        UIImageView *_imageView;
    }
  • ইমেতে চিত্র দর্শন উদাহরণ তৈরি করুন:

    -(id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        if (self) {
            _imageView = [[UIImageView alloc] initWithCoder:aDecoder];
         }
         return self;
     }
  • ViewDidLoad এ আমাদের চিত্র দেখার জন্য বোতামে একটি নতুন স্তর যুক্ত করুন এবং পাঠ্য সারিবদ্ধকরণ সেট করুন:

    [self.btn addSubview:_imageView];
    [self.btn.titleLabel setTextAlignment:NSTextAlignmentCenter];
  • বোতামে ক্লিকের পদ্ধতিতে আমার নির্বাচিত ওভারলে চিত্রটি চিত্রের দৃশ্যে যুক্ত করুন, চিত্রটিকে ফিট করার জন্য এটি আকার করুন এবং এটি বোতামটিতে কেন্দ্র করুন তবে এটি 15 টি উপরে সরিয়ে ফেলুন যাতে আমি পাঠ্যের নীচে অফসেটটি রাখতে পারি:

    [_imageView setImage:[UIImage imageNamed:@"blahImageBlah]];
    [_imageView sizeToFit];
    _imageView.center = CGPointMake(ceilf(self.btn.bounds.size.width / 2.0f),
             ceilf((self.btn.bounds.size.height / 2.0f) - 15));
    [self.btn setTitle:@"Some new text" forState:UIControlStateNormal];

দ্রষ্টব্য: সিল্ফ () এটি চিত্রের মানের জন্য পিক্সেল সীমানায় রয়েছে তা নিশ্চিত করা গুরুত্বপূর্ণ।


1
আমি স্ট্যাক ভিউতে বোতামটি যুক্ত করার কারণে আমার ব্যবহারের ক্ষেত্রে অবশ্যই আরও ভাল পন্থা।
valeCocoa

0

ধরে নিচ্ছেন যে আপনি পাঠ্য এবং চিত্র উভয়ই অনুভূমিকভাবে কেন্দ্রিকভাবে তৈরি করতে চান, উপরের পাঠ্যের চিত্রটি: ইন্টারফেস নির্মাতা থেকে পাঠ্যটিকে কেন্দ্র করুন এবং শীর্ষস্থানীয় ইনসেট যুক্ত করুন (চিত্রের জন্য ঘর তৈরি করুন)। (বাম ইনসেটটি 0 তে রেখে দিন)। চিত্র চয়ন করতে ইন্টারফেস বিল্ডার ব্যবহার করুন - কোড থেকে এটি আসল অবস্থান নির্ধারণ করা হবে, তাই আইবিতে জিনিসগুলি ঠিক দেখাবে না তা ভেবে উদ্বিগ্ন হবেন না। উপরের অন্যান্য উত্তরগুলির মতো নয়, এটি বর্তমানে সমর্থিত সমস্ত আইওএস সংস্করণে (5,6 এবং 7) কাজ করে।

কোডগুলিতে, চিত্রটি ধরার পরে কেবলমাত্র বোতামটির ইমেজভিউটি বাতিল করুন (বোতামটির চিত্রটি নালায় সেট করে) (এটি যদি প্রয়োজন হয় তবে স্বয়ংক্রিয়ভাবে পাঠ্যটিকেও কেন্দ্র করে নিয়ে যাবে)। তারপরে একই ফ্রেমের আকার এবং চিত্রের সাথে আপনার নিজের ইমেজভিউ ইনস্ট্যান্ট করুন এবং এটি মাঝখানে অবস্থান করুন।

এইভাবে আপনি এখনও ইন্টারফেস বিল্ডার থেকে চিত্রটি চয়ন করতে পারেন (যদিও এটি সিমুলেটারের মতো আইবিতে সংযুক্ত হবে না, তবে আবার, অন্যান্য সমাধানগুলি সমস্ত সমর্থিত আইওএস সংস্করণে সামঞ্জস্য নয়)


0

আমি এটি করার জন্য সংগ্রাম করে যাচ্ছিলাম কারণ আমি আমার ভিউর কনস্ট্রাক্টরে ইমেজের আকার এবং পাঠ্য প্রস্থ পেতে পারি নি। জেসির উত্তরে দুটি ছোট পরিবর্তন আমার পক্ষে কাজ করেছে:

CGFloat spacing = 3;
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - image.size.width, - (image.size.height + spacing), 0.0);
CGSize titleSize = [name sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

পরিবর্তনগুলি হ'ল:

  • ব্যবহার [NSString sizeWithAttributes]পাঠ্য প্রস্থ পেতে ;
  • এর UIImageপরিবর্তে সরাসরি চিত্রের আকার পানUIImageView

0

বিভিন্ন চিত্রের প্রস্থ এবং বিভিন্ন শিরোনাম দৈর্ঘ্যের সাথে এটি বেশ কয়েকটি বোতামের জন্য আমার পক্ষে ভাল কাজ করে:

উপশ্রেণী UIButton

override func layoutSubviews() {
    super.layoutSubviews()

    if let image = imageView?.image {

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


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

}

0

বোতামের আকার 80x80 পিক্সেলের জন্য সূক্ষ্মভাবে কাজ করা।

[self.leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, 10.0, 20.0, 10.0)];    
[self.leftButton setTitleEdgeInsets:UIEdgeInsetsMake(60, -75.0, 0.0, 0.0)];

0

চিত্রটি অনুভূমিকভাবে বিন্যস্ত করার জন্য আমি কিছু সামঞ্জস্য করেছি:

// the space between the image and text
        let spacing = CGFloat(36.0);

        // lower the text and push it left so it appears centered
        //  below the image
        let imageSize = tutorialButton.imageView!.frame.size;
        tutorialButton.titleEdgeInsets = UIEdgeInsetsMake(
            0, -CGFloat(imageSize.width), -CGFloat(imageSize.height + spacing), 0.0);

        // raise the image and push it right so it appears centered
        //  above the text
        let titleSize = tutorialButton.titleLabel!.frame.size;
        tutorialButton.imageEdgeInsets = UIEdgeInsetsMake(
            -CGFloat(titleSize.height + spacing), CGFloat((tutorialButton.frame.width - imageSize.width) / 2), 0.0, -CGFloat(titleSize.width));

0

প্রান্ত ইনসেট ব্যবহার করা কি বাধ্যতামূলক? যদি তা না হয় তবে আপনি সেন্টার প্যারেন্ট ভিউয়ের প্রতি শ্রদ্ধা জানানোর চেষ্টা করতে পারেন

extension UIButton 
{
    func centerImageAndTextVerticaAlignment(spacing: CGFloat) 
    {
        var titlePoint : CGPoint = convertPoint(center, fromView:superview)
        var imageViewPoint : CGPoint = convertPoint(center, fromView:superview)
        titlePoint.y += ((titleLabel?.size.height)! + spacing)/2
        imageViewPoint.y -= ((imageView?.size.height)! + spacing)/2
        titleLabel?.center = titlePoint
        imageView?.center = imageViewPoint

    }
}

প্রশ্নটি স্পষ্টভাবে ইমেজএন্ডসেটস এবং শিরোনামএডজিনসেটস ব্যবহারের জন্য জিজ্ঞাসা করেছে যাতে এটি সম্ভবত বাধ্যতামূলক
তিব্রোগর্গান

0

আপনাকে পাঠ্যের প্রস্থের সাহায্যে চিত্রটি ডানদিকে সরানো দরকার। তারপরে চিত্রটির প্রস্থের সাহায্যে পাঠ্যটি বাম দিকে সরান।

UIEdgeInsets imageEdgeInsets = self.remoteCommandsButtonLights.imageEdgeInsets;
imageEdgeInsets.left = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[button.titleLabel font]}].width;
imageEdgeInsets.bottom = 14.0;
button.imageEdgeInsets = imageEdgeInsets;

UIEdgeInsets titleEdgeInsets = self.remoteCommandsButtonLights.titleEdgeInsets;
titleEdgeInsets.left = -button.currentImage.size.width;
titleEdgeInsets.top = 20.0;
button.titleEdgeInsets = titleEdgeInsets;

তারপরে Y- অক্ষটি সামঞ্জস্য করতে উপরের এবং নীচের কীটগুলি সামঞ্জস্য করুন। এটি সম্ভবত প্রোগ্রামগতভাবেও করা যেতে পারে তবে এটি আপনার চিত্রের আকারের জন্য ধ্রুবক হওয়া উচিত। যেখানে এক্স-অক্ষ ইনসেটগুলি প্রতিটি বোতামের পাঠ্য লেবেলের আকারের ভিত্তিতে পরিবর্তন করতে হবে।


0

এক্সটেনশনে এই কোডটি যুক্ত করুন সুইফট ৪.২

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

0

কেবল আমার 2 সেন্ট ভিতরে toুকতে, এটি আমার পক্ষে কাজ করেছে:

extension UIButton {
  public func centerImageAndTextVertically(spacing: CGFloat) {
    layoutIfNeeded()
    let contentFrame = contentRect(forBounds: bounds)
    let imageFrame = imageRect(forContentRect: contentFrame)
    let imageLeftInset = bounds.size.width * 0.5 - imageFrame.size.width * 0.5
    let imageTopInset = -(imageFrame.size.height + spacing * 0.5)
    let titleFrame = titleRect(forContentRect: contentFrame)
    let titleLeftInset = ((bounds.size.width - titleFrame.size.width) * 0.5) - imageFrame.size.width
    let titleTopInmset = titleFrame.size.height + spacing * 0.5
    imageEdgeInsets = UIEdgeInsets(top: imageTopInset, left: imageLeftInset, bottom: 0, right: 0)
    titleEdgeInsets = UIEdgeInsets(top: titleTopInmset, left: titleLeftInset, bottom: 0, right: 0)
  }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.