This article was transferred from Jian Shu 2016.09.04 14:35:01
# UIButton
Related attributes of
UIButton provides methods to set title and image, default is image on the left and text on the right. The diagram below:
During development, we often have to adjust to text on the left and picture on the right, or text on top and picture on bottom.
EdgeInsets are also provided to set the position of images and text
@property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets titleEdgeInsets; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets imageEdgeInsets; // default is UIEdgeInsetsZero
Copy the code
Tip:UI_APPEARANCE_SELECTOR
The attributes of the tag are customizable through the appearance proxy.
So we can adjust the relative position of the image and text by setting titleEdgeInsets and imageEdgeInsets;
# Let’s seeUIEdgeInsets
The interpretation of the
-
type
typedef struct UIEdgeInsets { CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset' } UIEdgeInsets; Copy the code
-
Set each value meaning
//UIEdgeInsetsMake(<#T##top: CGFloat##CGFloat#>, <#T##left: CGFloat##CGFloat#>, <#T##bottom: CGFloat##CGFloat#>, <#T##right: CGFloat##CGFloat#>) testBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 40, 10); //10 means that the left border has moved 10 to the right (similarly -10 means that the left border has moved 10 to the left) //40 means that the bottom border has moved up 40 //10 means that the right border has moved 10 to the left (similarly -10 means that the right border has moved 10 to the right)Copy the code
In short: the positive values of these parameters are the corresponding distance to move in the opposite direction (for example, a positive value for top means move down, a negative value for move up) so that we can easily set the desired style outside the UIButton
# start implementing
Let’s now pull out the relevant Settings and make an extension method (below, set the text on the left and the image on the right).
1. Create a new swift file called Button_Extension and add the following code;
import UIKit
extension UIButton {
/// Set text to left and image to right. The default spacing is' 0.0 '
func setupImageAtRight(space: CGFloat = 0.0) {
/ * 1 * /
DRPrint("Get imageWidth")
guard letimageWidth = imageView? .frame.size.widthelse {
DRPrint("noImage")
return
}
/ * 2 * /
DRPrint("Get titleWidth")
guard lettitleWidth = titleLabel? .frame.size.widthelse {
DRPrint("noTitle")
return
}
//(Note: 'button' does not act as' navigationItem.titleView 'is the default' titleLabel 'and' imageView 'have a gap between the boundary)
titleEdgeInsets = UIEdgeInsetsMake(0.0, -(imageWidth + space * 0.5), 0, imageWidth + space * 0.5)
imageEdgeInsets = UIEdgeInsetsMake(0.0, titleWidth + space * 0.5.0.0, -(space * 0.5 + titleWidth))
// Open the comment to see that the normal 'button' default 'titleLabel' and 'imageView' distance boundary is' 0 '
//backgroundColor = UIColor.greenColor()}}Copy the code
The above code is all operations, but the first encapsulation put /*2*/ before /*1*/ and never got the right effect.
# Doubt & Clarification
Here in question: Why is titleWidth not 0.0 when titlelabel. text and titlelabel. font are available when titlelabel. font is available when titleWidth is available when imageWidth is available , the correct titleWidth can be obtained?
The study found that:
Discovered by customizing a DRButton rewrite -LayoutSubViews method, calling imageView? TitleLabel?. Frame does not call -layoutSubviews, so getting the titleWidth first does not get the correct value 0.0.
You can also write it yourself
import UIKit
class TestBtn: UIButton {
override func layoutSubviews(a) {
super.layoutSubviews()
DRPrint("button.layoutSubiews")}}Copy the code
Try the printout
-
First get the print result of imageWidth
Button_extension.swift-setupImageAtRight-14: get imageWidthTestBtn.swift-layoutSubviews()-15:button.layoutSubiews TestBtn.swift-layoutSubviews()-15:button.layoutSubiews Button_extension.swift-setupImageAtRight-19: get titleWidthTestBtn.swift-layoutSubviews()-15:button.layoutSubiews TestBtn.swift-layoutSubviews()-15:button.layoutSubiews Copy the code
-
Get the printed titleWidth first
Button_extension.swift-setupImageAtRight-14: get titleWidthButton_extension.swift-setupImageAtRight-19: get imageWidthTestBtn.swift-layoutSubviews()-15:button.layoutSubiews TestBtn.swift-layoutSubviews()-15:button.layoutSubiews TestBtn.swift-layoutSubviews()-15:button.layoutSubiews TestBtn.swift-layoutSubviews()-15:button.layoutSubiews Copy the code
# call
import UIKit
class ViewController: UIViewController {
override func viewDidLoad(a) {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
addButton()
//addButton("testTitle")
//addButton("testLongLongTitle")
}
override func didReceiveMemoryWarning(a) {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.}}// MARK:- Set up UI
extension ViewController {
func addButton(title: String = "78987fded") {
view.backgroundColor = UIColor.lightGrayColor()
let button = TestBtn()
button.setTitle(title, forState: .Normal)
button.setImage(UIImage(named: "navigationbar_arrow_down"), forState: .Normal)
button.setImage(UIImage(named: "navigationbar_arrow_up"), forState: .Selected)
//button.setTitleColor(UIColor.grayColor(), forState: .Normal)button.titleLabel? .font =UIFont.systemFontOfSize(14);
button.sizeToFit()
button.center = view.center
// Set the position of the image and caption
button.setupImageAtRight()
button.backgroundColor = UIColor.greenColor()
view.addSubview(button)
}
}
Copy the code
Effect:
Complete code with comments at the end
/// Set the image to the right with the default spacing of '0.0'
func setupImageAtRight(space: CGFloat = 0.0) {
// First method: adjust by calculating the length of the string
/* let titleString = currentTitle! as NSString let size = CGSizeMake(CGFloat(MAXFLOAT), bounds.size.height) let atttibutes = [NSFontAttributeName:titleLabel!.font] let titleWidth = titleString.boundingRectWithSize(size, options: .UsesLineFragmentOrigin, attributes: atttibutes, context: nil).size.width */
/* where: Why is' titleWidth 'always not' 0.0 'when' titlelabel. text 'and' titlelabel. font 'are available, but when' imageWidth 'is available first, TitleWidth: 🐷 find the correct 'titleWidth' by customizinga 'DRButton' rewrite '-layoutSubviews' method and calling' imageView? Frame will call '-layoutSubviews' first to get' imageWidth ', while 'titleLabel?. Frame' will not call '-layoutSubviews', so getting' titleWidth 'first will not get the correct value, but will get' 0.0 ` * /
// Adjust by getting 'titleLabel' width
guard letimageWidth = imageView? .frame.size.widthelse {
return
}
guard lettitleWidth = titleLabel? .frame.size.widthelse {
return
}
/* DRPrint("titleWidth = \(titleWidth)") DRPrint("bounds.size = \(bounds.size)") DRPrint(" titlelabel.frame = \(titleLabel! .frame)") DRPrint(" imageView.frame = \(imageView! .frame)") DRPrint(titleLabel?.frame.size.width) */
/* testBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 40, 10); 0 indicates that the top is 0. 10 indicates that the left border is moved 10 to the right (similarly, -10 indicates that the left border is moved 10 to the left). 40 Indicates that the bottom border is moved up 40 Move the corresponding distance in the opposite direction */
titleEdgeInsets = UIEdgeInsetsMake(0.0, -(imageWidth + space * 0.5), 0, imageWidth + space * 0.5)
imageEdgeInsets = UIEdgeInsetsMake(0.0, titleWidth + space * 0.5.0.0, -(space * 0.5 + titleWidth))
}
Copy the code
// MARK:- Simple print
func DRPrint<T>(message: T,file: NSString = #file,lineNum: Int = #line,funcName:String = #function) -> Void{#if DEBUG
let fileName = (file as NSString).lastPathComponent
print("\(fileName)-\(funcName)-\(lineNum):\(message)")
#endif
}
Copy the code
If you can’t print out information, please#if
Statement to remove