創建圖文混排并整體居中的UIButton

之前一直對UIButton的圖文混排一直很迷糊,知道可以通過titleEdgeInset和imageEdgeInset屬性來調整,但一直不知道inset的各個值是相對誰的或者說怎么計算的。直到前天看見2篇關于圖文混排的文章參考文章1參考文章2,才豁然開朗,然后自己寫代碼實踐并記錄下(它們的比我考慮的情況多,本篇假設button的高寬都足夠容納下文本和圖片的情況)。友情提示:如果不想看計算過程可以直接跳到尾部copy代碼
如后一篇文章里說的的前置知識點:
imageEdgeInsets(top,left,bottom,right) 和 titleEdgeInsets(top,left,bottom,right)的值就是我們想要的最終結果與按鈕初始狀態比較圖片和標題的位置分別在上下左右位移的值
對于各種排版就知道怎么計算titleEdgeInset和imageEdgeInset,下面配合圖文說明就很容易理解了。
當設置好button的圖片和文本后的初始狀態如下:

初始狀態

這個時候是圖片和文本組成的整體是居中于button里的,且圖片在左,文本在右。項目里經常遇到圖片和文本之間有個padding啊,或者圖片在文本上邊,右邊或者下邊的情況。如下圖:
圖片和文本之間只是多了個padding:

這個時候怎么計算titleEdgeInset和imageEdgeInset呢?就是用最終狀態的坐標減去初始狀態的坐標。具體來說,對于imageView,它的垂直坐標沒變,也就是top和bottom都是0,titleLabel也是。imageView的左邊相對于而言往左移動了padding / 2.0,相應的titleLabel 相比原來而言則右移了padding/2.0。算下來就是:

imageEdgeInset =  UIEdgeInsetsMake(0, -padding / 2.0, 0, padding / 2.0);
titleEdgeInset = UIEdgeInsetsMake(0, padding / 2.0, 0, -padding / 2.0);

對于圖片在右,文本在左的排版如下圖:

同樣的,imageView和titleLabel的垂直左邊均沒有改變,top和bottom都是0,imageView的左邊相對于其初始狀態向右移動了titleLabel.size.width+padding / 2.0,其左邊自然也相對于其初始狀態左邊右移了titleLabel.size.width+padding / 2.0,titleLabel的左邊相對于初始狀態左邊左移了imageView.size.wdith + padding / 2.0,其右邊自然也相對于其初始狀態右邊左移了imageView.size.wdith + padding / 2.0,計算下來:

imageEdgeInset =  UIEdgeInsetsMake(0, titleLabel.frame.size.width + padding / 2.0, 0, -titleLabel.frame.size.width - padding / 2.0);
titleEdgeInset = UIEdgeInsetsMake(0, -imageView.frame.size.width - padding / 2.0, 0, imageView.frame.size.width + padding / 2.0);

對于圖片在上,文本在下的排版如下:

圖片在左

imageView和titleLabel作為一個整體是居中于button里的,因此可以偏移量可以如下計算:

imageEdgeInset.left = button.frame.size.width/ 2.0 -  CGRectGetMidX(imageView.frame)//通過他們的水平中心點來計算
titleEdgeInset.left =  button.frame.size.width/ 2.0 -  CGRectGetMidX(titleLabel.frame)//通過他們的水平中心點來計算

對于top的計算同樣根據最終的坐標減去初始坐標,先計算最終態的imageView.origin.y

y  = (button.frame.size.height - imageView.frame.size.height - padding - titleLabel.frame.size.height) / 2.0;

因此:

imageEdgeInset.top =  y - imageView.frame.origin.y = (button.frame.size.height - imageView.frame.size.height - padding - titleLabel.frame.size.height) / 2.0 - imageView.frame.origin.y;

同理可以算出titlLabel的top偏移量為

titleEdgeInset.top = y + imageView.frame.size.height + padding - titleLabel.frame.origin.y = (button.frame.size.height - imageView.frame.size.height - padding - titleLabel.frame.size.height) / 2.0 + imageView.frame.size.height + padding - titleLabel.frame.origin.y = button.frame.size.height / 2.0 + imageView.frame.size.height / 2.0 + padding / 2.0 - titleLabel.frame.origin.y;

是時候綜合下了:

imageEdgeInset = UIEdgeInsetsMake(y - imageView.frame.origin.y, button.frame.size.width/ 2.0 -  CGRectGetMidX(imageView.frame),  -y + imageView.frame.origin.y, -button.frame.size.width/ 2.0 +  CGRectGetMidX(imageView.frame));
titleEdgeInset = UIEdgeInsetsMake(y + imageView.frame.size.height + padding - titleLabel.frame.origin.y, button.frame.size.width/ 2.0 -  CGRectGetMidX(titleLabel.frame), -(y + imageView.frame.size.height + padding - titleLabel.frame.origin.y), -button.frame.size.width/ 2.0 +  CGRectGetMidX(titleLabel.frame));

代碼復制好累,最后一種情況圖片在下,文本在上:
計算思路,同上一種情況一樣,不寫具體的計算代碼了最后總結下自己寫了一個UIButton的分類,有興趣的可以直接拷貝下面這段

typedef NS_ENUM(NSInteger, CPButtonStyle) {
    CPButtonStyleDefault = 0,
    CPButtonStyleImageUp,
    CPButtonStyleImageRight,
    CPButtonStyleImageBottom
};

- (void)setButtonStyle:(CPButtonStyle)style imageTitlePadding:(CGFloat)padding {

    CGRect tempFrame = self.frame;
    UILabel *label = [[UILabel alloc] init]; //為了防止拿不到titleLabel的高寬,新建一個UILabel,獲取高寬
    label.font = self.titleLabel.font;
    label.text = self.titleLabel.text;
    [label sizeToFit];
    CGRect titleFrame = label.frame;
    
    UIImageView *imageView = [[UIImageView alloc] init];//為了防止拿不到button的imageView的高寬,新建一個UIImageView,獲取高寬
    imageView.image = self.imageView.image;
    [imageView sizeToFit];
    CGRect imageFrame = imageView.frame;
    if (imageFrame.size.width == 0 || imageFrame.size.height == 0 || titleFrame.size.width == 0 || titleFrame.size.height == 0) {
        padding = 0;
    }
    CGRect frame = self.frame;
    frame.size.width = SCREEN_WIDTH; //這樣做目的是盡可能顯示下圖片和標題
    frame.size.height = SCREEN_HEIGHT;
    CGFloat iTop, iLeft, iRight, iBottom;
    CGFloat tTop, tLeft, tRight, tBottom;
    iTop = iLeft = iRight = iBottom = tTop = tLeft = tRight = tBottom = 0.0;
    if (style == CPButtonStyleImageRight) {
        iLeft = titleFrame.size.width + padding / 2.0;
        tLeft = -imageFrame.size.width - padding / 2.0;
    }
    if (style == CPButtonStyleImageUp) {
        CGFloat temp = (frame.size.height - (titleFrame.size.height + imageFrame.size.height + padding)) / 2.0;
        iLeft = frame.size.width / 2.0 - CGRectGetMidX(imageFrame);
        iTop = temp - imageFrame.origin.y;
        
        tLeft = frame.size.width / 2.0 - CGRectGetMidX(titleFrame);
        tTop = temp + imageFrame.size.height + padding - titleFrame.origin.y;
    }
    
    if (style == CPButtonStyleImageBottom) {
        CGFloat temp = (frame.size.height - (titleFrame.size.height + imageFrame.size.height + padding)) / 2.0;
        iLeft = frame.size.width / 2.0 - CGRectGetMidX(imageFrame);
        iTop = temp + titleFrame.size.height + padding - imageFrame.origin.y;
        
        tLeft = frame.size.width / 2.0 - CGRectGetMidX(titleFrame);
        tTop = temp - titleFrame.origin.y;
    }
    if (style == CPButtonStyleDefault) {
        iLeft = -padding /2.0;
        tLeft = padding / 2.0;
    }
    iRight = -iLeft;
    iBottom = -iTop;
    
    tRight = -tLeft;
    tBottom = -tTop;
    self.imageEdgeInsets = UIEdgeInsetsMake(iTop, iLeft, iBottom, iRight);
    self.titleEdgeInsets = UIEdgeInsetsMake(tTop, tLeft, tBottom, tRight);
    if (style == CPButtonStyleImageRight || style == CPButtonStyleDefault) {//設置完后,button的大小為剛好容納圖片和標題的大小,原始的sizeToFit方法不會算入這個padding
        tempFrame.size.width = imageFrame.size.width + titleFrame.size.width + padding;
        tempFrame.size.height = MAX(imageFrame.size.height, titleFrame.size.height);
    } else {
        tempFrame.size.width = MAX(imageFrame.size.width, titleFrame.size.width);
        tempFrame.size.height = imageFrame.size.width + titleFrame.size.width + padding;
    }
    self.frame = tempFrame;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,552評論 25 708
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,814評論 1 92
  • iOS的UIButton是一個非常常見而且常用的控件,我們一般用他來實現某個功能的提交以及選擇操作。我們可以建立只...
    歐陽大哥2013閱讀 6,921評論 18 125
  • retain cycle產生情況 A和B兩個對象,A持有B,B同時也持有A,A只有B釋放之后才有可能釋放,同樣B只...
    Mystical閱讀 267評論 0 0
  • 從大學和男人交往兩年了,一直都很愉快。畢業后,我們都留在北京工作,有結婚打算。最近我們計畫一起住,一來省房租,二來...
    高浩容閱讀 31,364評論 139 413