はじめに
iOS7からUIButtonの見た目がフラットになってしまい、
普通に使うと文字だけの残念なボタンになってしまいました。
今回はそんなiOS標準っぽいボタンを自作してみます。
タッチ処理も含めてのカスタマイズになります。(UIButtonクラスは継承しません)
swiftバージョンは1.2になります
完成版は下記のような感じ↓
実装
クラス
UIViewのサブクラスとしてクラスを作成
import UIKit
class PMFlatButton: UIView {
}
プロパティ
//MARK: Properties
//Public
var lineColor : UIColor = (UIColor(red: 0.294, green: 0.431, blue: 0.988, alpha: 1.000)) {
didSet{
contentView.layer.borderColor = lineColor.CGColor
textLabel.textColor = lineColor
}
}
var disableColor = UIColor.lightGrayColor()
var disableTextColor = UIColor.whiteColor()
var highlightedTextColor = UIColor.whiteColor()
var textLabel : UILabel!
var highlighted : Bool = false {
didSet{
if (highlighted != oldValue){ reloadButtonColors() }
}
}
var enabled : Bool = true {
didSet{
if (enabled != oldValue){
self.userInteractionEnabled = enabled
reloadButtonColors()
}
}
}
//Private
private var contentView : UIView!
private weak var target : AnyObject?
private var selector : Selector?
private var clickHandler: (() -> Void)?
lineColor
,highlighted
,enabled
は値の変更を監視して見た目や挙動を変えられるようにします。
初期化
//MARK: Initializer
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
self.alpha = 1.0
contentView = UIView(frame: CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame)))
contentView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
contentView.backgroundColor = UIColor.clearColor()
contentView.layer.borderColor = lineColor.CGColor
contentView.layer.borderWidth = 1.0
contentView.layer.cornerRadius = 5.0
contentView.layer.masksToBounds = true
self.addSubview(contentView)
textLabel = UILabel(frame: CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame)))
textLabel.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
textLabel.backgroundColor = UIColor.clearColor()
textLabel.textColor = lineColor
textLabel.numberOfLines = 0
textLabel.textAlignment = NSTextAlignment.Center
textLabel.font = UIFont.systemFontOfSize(14)
self.addSubview(textLabel)
}
パブリックメソッド
文字のセットとクリック時のハンドラー用関数を追加。
UIButtonのSelector方式と、お手軽に使えるクロージャー方式の2つを用意
//MARK: Class Method
func setText(text: NSString){
textLabel.text = text as String
}
func setTarget(target: AnyObject, selector: Selector){
self.target = target;
self.selector = selector
}
func setClickHandler(handler : () -> Void){
self.clickHandler = handler
}
プライベートメソッド
見た目変更用の関数
//MARK: Private Method
private func reloadButtonColors(){
if(enabled == true){
contentView.backgroundColor = (highlighted) ? lineColor : UIColor.clearColor()
textLabel.textColor = (highlighted) ? highlightedTextColor : lineColor
}else{
contentView.backgroundColor = disableColor
contentView.layer.borderColor = disableColor.CGColor
textLabel.textColor = disableTextColor
}
}
タッチイベント
UIViewのタッチイベント関数を使ってボタンのタッチ判定を実装します
//MARK: Touch Event
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
highlighted = true
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
highlighted = false
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as? UITouch
var touchPoint : CGPoint = CGPointZero
if let _touch = touch{
touchPoint = _touch.locationInView(self)
}
//タッチ領域から外れた場合はキャンセル扱いにする
if(touchPoint.x > CGRectGetWidth(self.bounds) || touchPoint.x < 0 || touchPoint.y > CGRectGetHeight(self.bounds) || touchPoint.y < 0){
touchesCancelled(touches, withEvent: event)
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
if (!highlighted){
return
}
if (target != nil && selector != nil && target!.respondsToSelector(selector!)){
var control : UIControl = UIControl()
control.sendAction(selector!, to: target, forEvent: nil)
}
if (clickHandler != nil){
clickHandler!()
}
highlighted = false
}
使用例
var flatButton : PMFlatButton = PMFlatButton(frame: CGRectMake(0, 0, 200, 50))
flatButton.setText("Flat Button")
//クリックハンドラーは下2行のどちらかを使用
flatButton.setTarget(self, selector: "buttonDidPush:")
flatButton.setClickHandler { () -> Void in
NSLog(__FUNCTION__+" Button clicked")
}
contentView.addSubview(flatButton)
func buttonDidPush(sender : AnyObject){
NSLog(__FUNCTION__+" Button clicked")
}
ソースコードは下記githubにて公開しております。
PMFlatButton_demo_swift - GitHub
終わりに
iOS標準っぽい見た目のボタンができました。
UIViewを継承しているので、いろいろなカスタマイズができます。