LoginSignup
24
24

More than 5 years have passed since last update.

iOS標準っぽいボタンを自作する

Last updated at Posted at 2015-05-13

はじめに

iOS7からUIButtonの見た目がフラットになってしまい、
普通に使うと文字だけの残念なボタンになってしまいました。

今回はそんなiOS標準っぽいボタンを自作してみます。
タッチ処理も含めてのカスタマイズになります。(UIButtonクラスは継承しません)

swiftバージョンは1.2になります

完成版は下記のような感じ↓

screen1.png

実装

クラス

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を継承しているので、いろいろなカスタマイズができます。

24
24
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
24