目前很多app首页功能区都类似工具栏上图标加下文字的方式来自定义按钮。当然,我们也可以用两个控件实现,但是,提升不了我们的逼格。接下来就介绍几种自定义这种上图标下文字的按钮的几种方式。先上图。

一、利用属性文本NSAttributedString来生成图片文本上下排列的按钮
1.复写NSAttributedString方法
extension NSAttributedString {
class func imageTextInit(image: UIImage, imageW: CGFloat, imageH: CGFloat, labelTitle: String, fontSize: CGFloat, titleColor: UIColor, labelSpacing: CGFloat) -> NSAttributedString{
let attachment = NSTextAttachment()
attachment.image = image
attachment.bounds = CGRectMake(0, 0, imageW, imageH)
let imageText = NSAttributedString(attachment: attachment)
let titleDict = [NSFontAttributeName: UIFont.systemFontOfSize(fontSize), NSForegroundColorAttributeName: titleColor]
let text = NSAttributedString(string: labelTitle, attributes: titleDict)
let spaceDict = [NSFontAttributeName:UIFont.systemFontOfSize(labelSpacing)]
let lineText = NSAttributedString(string: "\n\n", attributes: spaceDict)
let mutableAttr = NSMutableAttributedString(attributedString: imageText)
mutableAttr.appendAttributedString(lineText)
mutableAttr.appendAttributedString(text)
return mutableAttr.copy() as! NSAttributedString
}
}
class func YWHomeListButton(imageName: String, titleName: String!) -> UIButton {
//创建按钮类型为Custom
let btn = UIButton(type: .Custom)
//获取我们刚得到的属性文本,直接是NSAttributedString的子方法了
let attrStr = NSAttributedString.imageTextInit(UIImage(named: imageName)!, imageW: SCREEN_WIDTH/8*3/2, imageH: SCREEN_WIDTH/8, labelTitle: titleName, fontSize: 12, titleColor: UIColor.lightGrayColor(), labelSpacing: 4)
//设置按钮基本属性
btn.titleLabel?.textAlignment = .Center
btn.titleLabel?.numberOfLines = 0
btn.setAttributedTitle(attrStr, forState: .Normal)
return btn
}
3.接下来就可以用我们刚自己定义的按钮了
let btn1 = UIButton.YWHomeListButton("homeList1", titleName: "抽奖")
let btn2 = UIButton.YWHomeListButton("homeList2", titleName: "领红包")
let btn3 = UIButton.YWHomeListButton("homeList3", titleName: "蜂抱团")
let btn4 = UIButton.YWHomeListButton("homeList4", titleName: "一元购")
二、修改UIButton系统的titleRectForContentRect和imageRectForContentRect方法来改变文字和图片的相对位置
1.通过计算得出我们需要的上下排列的效果
import UIKit
class YWButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//设置按钮的基本属性
func commonInit() {
self.titleLabel?.textAlignment = .Center
self.imageView?.contentMode = .ScaleAspectFit
self.titleLabel?.font = UIFont.systemFontOfSize(12)
}
//调整系统UIButton的文字的位置
override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
let titleX = 0
let titleY = contentRect.size.height * 0.35
let titleW = contentRect.size.width
let titleH = contentRect.size.height - titleY
return CGRectMake(CGFloat(titleX), titleY, titleW, titleH)
}
//调整系统UIButton的图片的位置
override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
let imageW = CGRectGetWidth(contentRect)
let imageH = contentRect.size.height * 0.4
return CGRectMake(0, 5, imageW, imageH)
}
}
2.接下来就可以直接应用我们自己的控件了
let basketBtn = YWButton(type: .Custom)
basketBtn.setTitleColor(themeColor, forState: .Normal)
basketBtn.setTitle("购物车", forState: .Normal)
basketBtn.setImage(UIImage(named: "YS_car_sel"), forState: .Normal)
toolBarView.addSubview(basketBtn)
let storeBtn = YWButton(type: .Custom)
storeBtn.setTitleColor(themeColor, forState: .Normal)
storeBtn.setTitle("店铺", forState: .Normal)
storeBtn.setImage(UIImage(named: "ysstoreIcon"), forState: .Normal)
toolBarView.addSubview(storeBtn)
extension UIButton {
func layoutButton(imageTitleSpace: CGFloat) {
let imageWidth = self.imageView?.frame.size.width
let imageHeight = self.imageView?.frame.size.height
var labelWidth: CGFloat! = 0.0
var labelHeight: CGFloat! = 0.0
labelWidth = self.titleLabel?.intrinsicContentSize().width
labelHeight = self.titleLabel?.intrinsicContentSize().height
var imageEdgeInsets = UIEdgeInsetsZero
var labelEdgeInsets = UIEdgeInsetsZero
imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-imageTitleSpace/2, 0, 0, -labelWidth)
labelEdgeInsets = UIEdgeInsetsMake(0, -imageWidth!, -imageHeight!-imageTitleSpace/2, 0)
break;
self.titleEdgeInsets = labelEdgeInsets
self.imageEdgeInsets = imageEdgeInsets
}