この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
UISegmentedControlの真ん中にボタンを置きたい
UISegmentedControlのセグメントとセグメントの間にボタンを配置する方法を調べてみました。
先に動作結果をご覧ください。
検証環境
本記事は以下の環境で検証を行っています。
- macOS Sierra バージョン 10.12.5
- Xcode Version 8.3.3 (8E3004b)
- iPhone 7シミュレータ iOS 10.3(14E8301)
- Swift 3.1
ビューのレイアウト
最初にUISegmentedControlとUIButtonを持つカスタムビューを作ります。
今回はMyView
というクラスを作成しました。
クラスを作成したらxibで以下のようにレイアウトを行います。
UISegmentedControlは通常通り配置し、UIButtonも親ビューの中心に配置しているだけなので
この時点ではUISegmentedControlとUIButtonは重なって表示されています。
これらのコンポーネントはIBOutletでソースコードと紐づけておきましょう。
コードでUISegmentedControlのセグメント間にスペースを空ける
レイアウトが出来たら、UISegmentedControlのセグメント間にボタンの幅分のスペースを空けてあげましょう。
UISegmentedControlにはsetDividerImage
というメソッドがあるのでこれを使います。
このメソッドは区切り画像を設定するためのメソッドですが、透明な画像を指定することでスペースが空いているように見せることができます。
UIImageの生成にはiOS 10から使えるUIGraphicsImageRenderer
を使用しています。
ソースコード
import UIKit
/// UISegmentedControlとUIButtonを持つView
class MyView: UIView {
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var button: UIButton!
override func layoutSubviews() {
super.layoutSubviews()
// SegmentedControlにボタン幅分のスペースを空ける。
let dividerImage = UIImage.image(withColor: .clear,
size: button.bounds.size)
segmentedControl.setDividerImage(dividerImage,
forLeftSegmentState: .normal,
rightSegmentState: .normal,
barMetrics: .default)
}
}
// MARK: - UIImage
extension UIImage {
/// 色とサイズを指定してUIImageを生成する。
///
/// - Parameters:
/// - color: 色
/// - size: サイズ
/// - Returns: 生成したUIImage
static func image(withColor color: UIColor, size: CGSize) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { ctx in
ctx.cgContext.setFillColor(color.cgColor)
ctx.fill(CGRect(origin: .zero, size: size))
}
}
}
カスタムビューをnibから読み込んで表示する
ここまで出来たらあとはカスタムビューを読み込んで表示してあげるだけです。
以下ではViewControllerが管理しているビューの下部に固定の高さで表示しています。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// nibからViewを読み込む
let nib = UINib(nibName: String(describing: MyView.self), bundle: nil)
let myView = nib.instantiate(withOwner: nil, options: nil).first as! MyView
// Auto Layoutの制約を設定
myView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myView)
view.leadingAnchor.constraint(equalTo: myView.leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: myView.trailingAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: myView.bottomAnchor).isActive = true
myView.heightAnchor.constraint(equalToConstant: 48).isActive = true
}
}
おわりに
ちょっとしたテクニックを使ってUISegmentedControlのセグメントとセグメントの間にボタンを配置してみました。どなたかの参考になれば幸いです。