當需要實現一個自定義佈局圖片和標題的按鈕時候,不知道有多少少年直接佈局了UIButton,亦或是自定義一個UIView,然後以空白UIButton、UILabel、UIImageVew作為subViews。 兩者其實都一樣,因為UIButton的內部subViews中,就已經存在一個UILabel和 ...
當需要實現一個自定義佈局圖片和標題的按鈕時候,不知道有多少少年直接佈局了UIButton,亦或是自定義一個UIView,然後以空白UIButton、UILabel、UIImageVew作為subViews。
兩者其實都一樣,因為UIButton的內部subViews中,就已經存在一個UILabel和UIImageView。
不談論優劣,只記錄一下直接佈局UIButton的過程。
因為UIButton已經有一個UILabel顯示標題,一個ImageView顯示圖片,所以可以直接佈局。但是需要註意下麵記錄的問題。
首先,對一個UIButton實例button直接設置title(使用setTitle或者setAttributedTitle方法)和image(使用setImage方法),會發現,圖片和標題依次緊貼併排居中顯示。
然後,修改一下這個button的titleLabel和imageView的frame,會發現,並沒有什麼作用。
最後,嘗試使用方法setTitleEdgeInsets和setImageEdgeInsets,會發現,沒有作用或者佈局異常。
問題在於:
1.獲取titleLabel的frame時候,size始終是(0, 0)
2.修改titleLabel的frame時機不對
將上述修改操作放在方法layoutSubviews中是合適的。
至於創建UIButton的子類重載方法,還是創建分類來swizzle方法都可以。
即使在這個時機,使用setTitleEdgeInsets還是可能會出現文字顯示不全的問題。建議直接修改titleLabel的frame。
我採用了創建分類的方案。定義了一個方法,在+load方法中與layoutSubViews交換。
- (void)base_layoutSubviews { [self base_layoutSubviews]; if (self.resetTitleAndImageLayoutBlock) { self.resetTitleAndImageLayoutBlock(); } }
代碼中自定義的block變數,將重置佈局代碼延遲到此處調用。
以下代碼,是我寫的UIButton分類中自定義圖片和標題佈局的主要方法,其中圖片位置暫時只自定義了四種:
- (void)resetButtonTitleAndImageLayoutWithMidInset:(CGFloat)midInset imageLocation:(ButtonImageLocation)imageLocation { CGSize titleSize = [self.titleLabel.attributedText boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;; CGSize imageSize = self.imageView.size; __weak typeof(self) weakSelf = self; //因為UIButton在layoutSubviews時候,會重置titleLabel的frame,所以需要延遲調用block self.resetTitleAndImageLayoutBlock = ^{ switch (imageLocation) { case ButtonImageLocationUp: { CGFloat imageOriginX = (weakSelf.width - imageSize.width) / 2.0; CGFloat imageOriginY = (weakSelf.height - titleSize.height - midInset - imageSize.height) / 2.0; weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, weakSelf.height - imageOriginY - imageSize.height, imageOriginX); CGFloat titleOriginX = (weakSelf.width - titleSize.width) / 2.0; CGFloat titleOriginY = imageOriginY + imageSize.height + midInset; weakSelf.titleEdgeInsets = UIEdgeInsetsMake(titleOriginY, titleOriginX, weakSelf.height - titleOriginY - titleSize.height, titleOriginX); break; } case ButtonImageLocationLeft: { CGFloat imageOriginX = (weakSelf.width - imageSize.width - midInset - titleSize.width) / 2.0; CGFloat imageOriginY = (weakSelf.height - imageSize.height) / 2.0; weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, imageOriginY, weakSelf.width - imageOriginX - imageSize.width); CGFloat titleOriginX = imageOriginX + imageSize.width + midInset; //橫向時候,label的frame可以取較大範圍 // CGFloat titleOriginY = (weakSelf.height - titleSize.height) / 2.0; // weakSelf.titleLabel.frame = CGRectMake(titleOriginX, titleOriginY, titleSize.width, titleSize.height); weakSelf.titleLabel.frame = CGRectMake(titleOriginX, 0, weakSelf.width - titleOriginX, weakSelf.height); [weakSelf.titleLabel setTextAlignment:NSTextAlignmentLeft]; break; } case ButtonImageLocationDown: { CGFloat titleOriginX = (weakSelf.width - titleSize.width) / 2.0; CGFloat titleOriginY = (weakSelf.height - titleSize.height - midInset - imageSize.height) / 2.0; weakSelf.titleEdgeInsets = UIEdgeInsetsMake(titleOriginY, titleOriginX, weakSelf.height - titleOriginY - titleSize.height, titleOriginX); CGFloat imageOriginX = (weakSelf.width - imageSize.width) / 2.0; CGFloat imageOriginY = titleOriginY + titleSize.height + midInset; weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, weakSelf.height - imageOriginY - imageSize.height, imageOriginX); break; } case ButtonImageLocationRight: { CGFloat titleOriginX = (weakSelf.width - imageSize.width - midInset - titleSize.width) / 2.0; //橫向時候,label的frame可以取較大範圍 // CGFloat titleOriginY = (weakSelf.height - titleSize.height) / 2.0; // weakSelf.titleLabel.frame = CGRectMake(titleOriginX, titleOriginY, titleSize.width, titleSize.height); weakSelf.titleLabel.frame = CGRectMake(0, 0, titleOriginX + titleSize.width, weakSelf.height); [weakSelf.titleLabel setTextAlignment:NSTextAlignmentRight]; CGFloat imageOriginX = titleOriginX + titleSize.width + midInset; CGFloat imageOriginY = (weakSelf.height - imageSize.height) / 2.0; weakSelf.imageEdgeInsets = UIEdgeInsetsMake(imageOriginY, imageOriginX, imageOriginY, weakSelf.width - imageOriginX - imageSize.width); break; } } }; }
完整的代碼請參考Base項目中UIButton的分類。
Base項目已更新:https://github.com/ALongWay/base.git