iOS 不規則Button點選(二)
在上一篇文章iOS 不規則Button點選中,講述了按鈕在設定了不規則圖片情況下的響應處理。
這篇文章講述按鈕不規則的另一種情況:當按鈕的形狀是由我們自己繪製出來的時候。
這裡我們直接開始程式碼的編寫了,關於事件傳遞機制可以在上一篇文章iOS 不規則Button點選回顧一下。
按鈕定義
這裡建立了一個繼承自UIButton的子類 IrregularButton。 並提供了三個方法供外界設定:
// 方法都返回了自身,使外界可以鏈式呼叫 func path(type: BtnType) -> IrregularButton// 設定要繪製的path func backgroundColor(color: UIColor) -> IrregularButton// 設定背景顏色 func text(text: String) -> IrregularBtn// 設定文字 複製程式碼
// 這裡定義了一個列舉,定義了我們這個例子中按鈕繪製的型別 enum BtnType { case leftUp case leftDown case rightUp case rightDown case center } class IrregularButton: UIButton { // 繪製出圖形的path private var path = UIBezierPath() // 最終要呈現的圖形 private var drawLayer = CAShapeLayer() // 顯示我們需要顯示的文字 private var textLayer = CATextLayer() override init(frame: CGRect) { super.init(frame: frame) // 將要顯示的layer新增到自身的layer中 self.layer.addSublayer(self.drawLayer) self.layer.addSublayer(self.textLayer) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 外部傳入的path,供我們繪製 func path(type: BtnType) -> IrregularButton { let path = UIBezierPath() switch type { case .leftUp: path.move(to: CGPoint(x: 60, y: 100)) path.addLine(to: CGPoint(x: 0, y: 100)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 100, startAngle: .pi, endAngle: .pi*1.5, clockwise: true) path.addLine(to: CGPoint(x: 100, y: 60)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 40, startAngle: .pi*1.5, endAngle: .pi, clockwise: false) path.close() self.path = path case .leftDown: path.move(to: CGPoint(x: 60, y: 100)) path.addLine(to: CGPoint(x: 0, y: 100)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 100, startAngle: .pi, endAngle: .pi*0.5, clockwise: false) path.addLine(to: CGPoint(x: 100, y: 140)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 40, startAngle: .pi*0.5, endAngle: .pi, clockwise: true) path.close() self.path = path case .rightUp: path.move(to: CGPoint(x: 100, y: 60)) path.addLine(to: CGPoint(x: 100, y: 0)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 100, startAngle: .pi*1.5, endAngle: 0, clockwise: true) path.addLine(to: CGPoint(x: 140, y: 100)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 40, startAngle: 0, endAngle: .pi*1.5, clockwise: false) path.close() self.path = path case .rightDown: path.move(to: CGPoint(x: 140, y: 100)) path.addLine(to: CGPoint(x: 200, y: 100)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 100, startAngle: 0, endAngle: .pi*0.5, clockwise: true) path.addLine(to: CGPoint(x: 100, y: 140)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 40, startAngle: .pi*0.5, endAngle: 0, clockwise: false) path.close() self.path = path case .center: path.move(to: CGPoint(x: 140, y: 100)) path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 40, startAngle: 0, endAngle: .pi*2, clockwise: true) path.close() self.path = path } self.drawLayer.path = self.path.cgPath // 繪製完成,通知layer去重新整理介面 setNeedsDisplay() return self } // 設定需要顯示的文字 func text(text: String) { // 獲取顯示文字的size let stringSize = text.boundingRect(with: CGSize(width:100,height:CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: 14)], context: nil).size // 設定textLayer的位置 textLayer.frame = CGRect(x: self.path.bounds.origin.x+(self.path.bounds.size.width/2)-(stringSize.width/2), y: self.path.bounds.origin.y+(self.path.bounds.size.height/2)-(stringSize.height/2), width: stringSize.width, height: stringSize.height) textLayer.string = NSAttributedString(string: text, attributes: [NSAttributedString.Key.foregroundColor:UIColor.black, NSAttributedString.Key.font:UIFont.systemFont(ofSize: 14)]) textLayer.backgroundColor = UIColor.clear.cgColor textLayer.isWrapped = false//設定是否自動換行 textLayer.contentsScale = UIScreen.main.scale//寄宿圖的畫素尺寸和檢視大小的比例,不設定為螢幕比例文字就會畫素化 setNeedsDisplay() } // 設定按鈕的背景顏色 func backgroundColor(color: UIColor) -> IrregularButton { self.drawLayer.fillColor = color.cgColor setNeedsDisplay() return self } // 重寫此方法。判斷點是否在自身path所包含的區域內。包含則返回true,代表自身處理;否則返回false。 override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { if self.path.contains(point) { return true } return false } } 複製程式碼
按鈕新增
在controller介面中,建立按鈕組並新增到介面上。
class ViewController: UIViewController { private let BTN_TAG = 1001 override func viewDidLoad() { super.viewDidLoad() let colorArr = [UIColor(red: 231/255, green: 15/255, blue: 0, alpha: 1), UIColor(red: 237/255, green: 218/255, blue: 0, alpha: 1), UIColor(red: 248/255, green: 160/255, blue: 0, alpha: 1), UIColor(red: 103/255, green: 226/255, blue: 103/255, alpha: 1), UIColor(red: 67/255, green: 196/255, blue: 242/255, alpha: 1)] let typeArr: [BtnType] = [.leftUp, .rightUp, .leftDown, .rightDown, .center] for index in 0..<colorArr.count { let color = colorArr[index] let type = typeArr[index] let btn = IrregularBtn(frame: CGRect(x: 80, y: 100, width: 200, height: 200)) btn.path(type: type) .backgroundColor(color: color) .text(text: "功能\(index+1)") .addTarget(self, action: #selector(btnClick(_:)), for: .touchUpInside) btn.tag = BTN_TAG + index self.view.addSubview(btn) } } @objc func btnClick(_ sender: UIButton) { var str: String switch sender.tag { case 1001: str = "LeftUp Button" case 1002: str = "RightUp Button" case 1003: str = "LeftDown Button" case 1004: str = "RightDown Button" default: str = "Center Button" } print("current click event is \(str)") } } 複製程式碼