ios开发 自定义btn_iOS一步步实现一个高度自定义UIButton控件
需求背景
日常開發中UIButton的圖片與標題默認的布局是固定的,是在水平方向左右排列。但是我們會經常需要更改image和title的位置來實現需求,這是個很常見的需求就不多說了。所以下面就來談談如何一步步的實現一個高度自定義的UIButton控件。
實現思路
默認情況下,在button有固定的寬高值的時候,image和title是以相對左右排列,整體居中于button來顯示的,如果沒有固定的寬高值,即大小自適應的情況下,整個UIButton將自動縮放到剛好可以容納image和title的大小。如圖所示:
自適應大小.png
了解UIButton的各個屬性
在準備自定義之前,我們需要了解UIButton的各個屬性都是怎么運用和實現的,因為要修改title和image的位置與這些屬性是密不可分的。
因為這些都是基本的開發知識,我就不再過多敘述,分別以圖片來展示效果:
UIControlContentVerticalAlignment
UIControlContentVerticalAlignment各種效果.png
UIControlContentHorizontalAlignment
UIControlContentHorizontalAlignment各種效果.png
通過上面兩張圖可以清楚地看到UIControlContentVerticalAlignment和UIControlContentHorizontalAlignment在不同值下的效果,灰色背景的就是一個button的實際大小,center就是系統默認的值,明顯的在兩種fill值下,圖片都出現了拉伸的情況,而且在水平fill下,圖片并沒有像垂直情況下水平鋪滿整個控件,image和title還重疊到了一起去。
UIEdgeInsets
UIButton的另一個重要的屬性就是這個了,稱之為偏移量,他分別有contentEdgeInsets,imageEdgeInsets,titleEdgeInsets三個相關屬性。
默認情況下:contentEdgeInsets的top、left、bottom、right都是相對于button本身,控制著image和title整體的偏移量;
imageEdgeInsets的top、left、bottom相對于button,right相對于title,控制著image的相對偏移量;
titleEdgeInsets的top、bottom、right相對于button,left相對于image,控制著title的相對偏移量;
我用一張圖來解釋一下:
偏移量.png
上圖的正負值就代表偏移方向
我們想要的效果
寫到這里,我們需要考慮一下我們的需求,我們并不是來分析button的實現原理,而是要實現一個自定義的button,自定義image和title的相對位置是最起碼的要求。相信看到這里大家也知道我們只需要修改imageEdgeInsets和titleEdgeInsets的值就可以隨意布局image和title的相對位置。比如左title右image,上image下title。
要實現這個需求有兩種方式:新建一個UIButton的分類UIButton + xx,在layoutSubviews里修改imageEdgeInsets和titleEdgeInsets的值。這種方式可以簡單實現我們的基本需求,但如果想要添加更多的自定義屬性還需要通過runtime來實現,好處就是擁有調用系統API的舒爽,直接UIButton調用,沒什么代碼侵入性。
封裝一個繼承自UIButton的CustomButton,可以自由添加自定義方法、屬性,在layoutSubviews里重置image和title的frame來實現不同的布局方式。
其實這兩種方式都可以實現自定義的效果,具體選用哪個就看你自己的需求了,我這里就第二種方式來實現一下。
上面所說到的contentEdgeInsets,imageEdgeInsets,titleEdgeInsets默認值都是zero,但是我們現在假設他們都有一個默認值x;
button簡易圖示.png
這里實現的思路就是通過self.bounds減去四周的偏移量先獲取整個content的實際size,再由contentSize減去image和title的對應偏移量來獲取image和title的實際size。總之就是先獲取image和title的實際大小,然后根據不同的布局重置image和title的x、y坐標和bound,從而得到對應的frame,就可以實現自由布局了。
上面所說的是button有固定寬高值的情況,如果button的寬高自適應,即調用sizeToFit方法時,我們需要在- (CGSize)sizeThatFits:(CGSize)size內針對不同情況重新計算出button的size,不然的話,系統會根據image和title的大小默認返回它們左右排列的size,此時的size是錯誤的,如圖:
沒做適配的結果.png
具體的布局分析思路就是這些了,因為代碼太多,就不在這里粘貼詳細代碼了,如果需要代碼的可以在文章底部找到demo的下載鏈接,demo里面也有詳細的注釋說明。
但是,到這里我們只是自定義了image和title的相對布局,我們的目的是自定義整個UIButton,所以系統默認的點擊效果,CALayer的所有默認動畫都需要移除掉,替換成我們自定義的layer效果。比如說系統button的默認高亮狀態下圖片顏色也會加深,這個其實很惡心,所以我們應該移除掉,就像圖下所示:
系統button高亮狀態.png
ok,現在我們來整理一下需要的常用屬性,分別為normal、highlighted、disabled這幾種狀態下的背景色,透明度變化,圖片的tintColor,邊框線的顏色,我們就針對這幾個點進行修改。
下面粘貼幾塊代碼段大概展示一下:
highlighted邏輯-?(void)setHighlighted:(BOOL)highlighted?{
[super?setHighlighted:highlighted];
if?(highlighted?&&?!self.originBorderColor)?{
//?手指按在按鈕上會不斷觸發setHighlighted:,所以這里做了保護,設置過一次就不用再設置了
self.originBorderColor?=?[UIColor?colorWithCGColor:self.layer.borderColor];
}
//?渲染背景色
if?(self.highlightedBackgroundColor?||?self.highlightedBorderColor)?{
[self?adjustsButtonHighlighted];
}
//?如果此時是disabled,則disabled的樣式優先
if?(!self.enabled)?{
return;
}
//?自定義highlighted樣式
if?(self.adjustsButtonWhenHighlighted)?{
if?(highlighted)?{
self.alpha?=?0.5f;
}?else?{
[UIView?animateWithDuration:0.25f?animations:^{
self.alpha?=?1;
}];
}
}
}
enabled邏輯-?(void)setEnabled:(BOOL)enabled?{
[super?setEnabled:enabled];
if?(!enabled?&&?self.adjustsButtonWhenDisabled)?{
self.alpha?=?0.5f;
}?else?{
[UIView?animateWithDuration:0.25f?animations:^{
self.alpha?=?1;
}];
}
}
移除系統layer,添加自定義layer-?(void)adjustsButtonHighlighted?{
if?(self.highlightedBackgroundColor)?{
if?(!self.highlightedBackgroundLayer)?{
self.highlightedBackgroundLayer?=?[CALayer?layer];
[self.highlightedBackgroundLayer?FS_removeDefaultAnimations];
[self.layer?insertSublayer:self.highlightedBackgroundLayer?atIndex:0];
}
self.highlightedBackgroundLayer.frame?=?self.bounds;
self.highlightedBackgroundLayer.cornerRadius?=?self.layer.cornerRadius;
self.highlightedBackgroundLayer.backgroundColor?=?self.highlighted???self.highlightedBackgroundColor.CGColor?:?[UIColor?colorWithRed:1?green:1?blue:1?alpha:0].CGColor;
}
if?(self.highlightedBorderColor)?{
self.layer.borderColor?=?self.highlighted???self.highlightedBorderColor.CGColor?:?self.originBorderColor.CGColor;
}
}
因為需要大量的自定義屬性來代替系統默認屬性,雖然我很想在這里解釋每個屬性的用處,但是太麻煩了,所以還是建議直接下載demo,配合代碼看文章,代碼有詳細的注釋
這里就直接展示一下demo的效果圖:
FSCustomButtonDemo.gif
以前項目用到的時候,我也是直接網上找的一個庫,不過那個庫包含內容太多,很多都沒用,所以我將其中的部分代碼抽離了出來直接在項目中運用,效果還可以很穩定,所以最近抽時間將代碼從項目中抽離封裝了一下,寫了一個demo上傳在github,需要的可以直接前往下載:
文章和demo中涉及到的知識點:
如果對你有所幫助,就點個贊吧作者:PURE藍胖子
鏈接:http://www.jianshu.com/p/4603e9bbba56
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的ios开发 自定义btn_iOS一步步实现一个高度自定义UIButton控件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 485不用双绞线可以吗_加装迎宾踏板可以
- 下一篇: 点击定位到指定位置_以三菱PLC来举例说