詳解iOS App開發中改變UIButton內部控制項的基本方法_IOS

來源:互聯網
上載者:User

UIButton內部預設有個UIImageView、UILabel控制項,可以分別用下面屬性訪問:

複製代碼 代碼如下:

@property(nonatomic,readonly,retain) UIImageView *imageView;
@property(nonatomic,readonly,retain) UILabel     *titleLabel;

UIButton之所以能顯示文字,完全是因為它內部的titleLabel也,也就是說,UIButton的setTitle:forState:方法設定的字串就是顯示到了titleLabel上

 UIButton的setImage:forState:方法設定的圖片顯示到了內部的imageView上。

注意:
1.設定按鈕的文字或文字顏色,必須用下面的方法

複製代碼 代碼如下:

- (void)setTitle:(NSString *)title forState:(UIControlState)state;
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;

warnning:不能直接拿到titleLabel設定文字和文字顏色,比如下面的做法是錯誤的:
複製代碼 代碼如下:

button.titleLabel.text = @"12323";
button.titleLabel.textColor = [UIColor redColor];

2.設定按鈕內部的小圖片,必須用下面的方法

複製代碼 代碼如下:

- (void)setImage:(UIImage *)image forState:(UIControlState)state;

warnning:不能直接拿到imageView設定圖片,比如下面的做法是錯誤的:
複製代碼 代碼如下:

button.imageView.image = [UIImage imageNamed:@"abc.png"];

好了,回顧完之後,我們下面來進入本文的主題~

改變UIButton內部控制項
當給UIButton設定title和image後,就相當於UIButton是由一個UIButtonLabel + 一個UIImageView組成。但是它們預設的格式是固定的,即左面是一個UIImage,右面是一個UIButtonLabel。現在如果我們想讓UIImage顯示在這個button的上面,讓UIButtonLabel顯示在這個button的下面。

我們可以完全自訂一個控制項來實現上面所說的,也可以在UIButton的基礎上改變它的內部子控制項。這裡採用第二種方法。

1.首先,如果想改變子控制項的位置,那麼最先想到的可能是拿到這個button,然後通過訪問它的imageView和titleLabel屬性。

我們可以首先對這個button列印一下看看內部的結構:

複製代碼 代碼如下:

NSLog(@"%@", self.button.subviews);

列印的結果是一個空數組!這是怎麼回事呢?

實際上UIButton內部的子控制項採用的是懶載入,也就是說如果沒有使用到相應的子控制項,那麼是不會載入的。

那麼我們就重新給這兩個控制項的frame賦值,這樣不僅用到了這兩個控制項使其載入,也可以看看是否可以直接改變這兩個控制項的frame以達到將這兩個控制項重新排列的目的。

但是如果你這麼做,你會發現實際顯示的這個button內部並沒有改變,說明直接改變UIButton內部控制項的frame是無法達到重新排列的目的的。

接著將這個button內部的子控制項列印出來:

複製代碼 代碼如下:

NSLog(@"%@", self.button.subviews);

會發現subviews這個數組裡現在是一個UIImageView + 一個UIButtonLabel,現在它們有了值(因為前面用到了這兩個控制項,所以進行了懶載入)。

可是仔細觀察,會發現這兩個控制項的frame明明是我們剛剛賦值的frame,但是顯示出來的為什麼又不是按這個frame顯示的呢?

因為列印出來的frame只是我們剛剛設定的,而UIButton在顯示的時候會根據它的UIImageView和UIButtonLabel裡面的內容重新計算大小,所以即使我們改變了子控制項的frame,也無法真正更改子控制項的位置和尺寸。

2.第二種思路是可以繼承UIButton,在原來的按鈕的基礎上進行改變。

比如我們建立一個UIButton的子類CYLButton,在CYLButton的實現檔案中實現下面的方法:

複製代碼 代碼如下:

- (CGRect)titleRectForContentRect: (CGRect)contentRect // 控制label顯示在哪和大小
{
    return CGRectMake(0, contentRect.size.width, contentRect.size.width, contentRect.size.height - contentRect.size.width);
}

- (CGRect)imageRectForContentRect: (CGRect)contentRect // 控制image顯示在哪和大小
{
    return CGRectMake(0, 0, contentRect.size.width, contentRect.size.width);
}

// contentRect一般來代表UIButton的bounds.size

// 我們也可以在initWithFrame:方法中設定UIButton的內部控制項的屬性
- (instancetype)initWithFrame: (CGRect)frame
{
      if (self = [super initWithFrame: frame]) {
        self.titleLabel.backgroundColor = [UIColor blueColor];
          self.titleLabel.textAlignment = NSTextAlignmentCenter;
          self.imageView.backgroundColor = [UIColor yellowColor];
      }
      return self;
}


可以看到這種方法可以滿足我們的要求。但是也有弊端,如果我們在其中一個方法中設定的某一些想在另一個方法中也用到,那麼就不是很方便。

3.更好的方法是重寫layoutSubviews方法,因為這個方法可以很方便地調整子控制項。

複製代碼 代碼如下:

- (void)layoutSubviews
{
    [super layoutSubviews];

      CGFloat imageW = self.bounds.size.width;
      CGFloat imageH = imageW;
      self.imageView.frame = CGRectMake(0, 0, imageW, imageH);

      CGFloat titleY = imageH;
      CGFloat titleW = imageW;
      CGFloat titleH = self.bounds.size.height - titleY;
    self.titleLabel.frame = CGRectMake(0, titleY, titleW, titleH);
}


這樣做可能會很奇怪,因為剛才在這個類的外面我們也改變的是imageView和titleLabel的frame,可是毫無作用,而在layoutSubviews方法裡同樣修改,為什麼會起作用了呢?

因為剛才我們在外面修改子控制項的frame,但是當執行到內部的layoutSubviews方法的時候會重新將它們的frame設定為image和title對應的大小。而現在我們直接在layoutSubviews中修改它們的frame,相當於覆蓋了之前將它們的frame設定為預設大小這一步驟,所以現在是可以成功的,並且因為在一個方法中,是可以共用變數的。

另外需要注意,如果繼承自UIButton(比如CYLButton),那麼當有了資料模型,想在CYLButton的setter方法中給子控制項賦值的時候,不能直接這樣:

複製代碼 代碼如下:

self.imageView = ...
self.text = ...

因為self(CYLButton)是繼承自UIButton,所以無論是image還是title都是分狀態的,所以需要這樣:
複製代碼 代碼如下:

[self setImage...];
[self setTitle...];

所以說能不能直接修改,取決於這個屬性分不分狀態。如果分狀態,那麼就不能直接修改。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.