Open4
UIButton.Configurationを使うときはaddSubviewの順番に気をつける
- UIButtonで作ったボタンにバッジをつけるため実装していた時に、
UIButton.Configuration
を使った時に変な挙動を発見したのでメモ - バッジの実装はUIButtonの上にバッジに見立てたUIViewをのせるような実装
- 以下のコードは意図した通りに動作したもの
override func viewDidLoad() {
super.viewDidLoad()
// ボタンを作成
let button = UIButton(configuration: .plain())
button.configuration?.image = .init(systemName: "house.fill")
button.translatesAutoresizingMaskIntoConstraints = false
// viewに追加
view.addSubview(button)
NSLayoutConstraint.activate([
button.widthAnchor.constraint(equalToConstant: 32),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
// ボタンの上に赤丸を設置
let badgeView = UIView()
badgeView.backgroundColor = .red
badgeView.layer.cornerRadius = 4
badgeView.translatesAutoresizingMaskIntoConstraints = false
button.addSubview(badgeView)
NSLayoutConstraint.activate([
badgeView.topAnchor.constraint(equalTo: button.topAnchor, constant: 4),
badgeView.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: -4),
badgeView.widthAnchor.constraint(equalToConstant: 8),
badgeView.heightAnchor.constraint(equalToConstant: 8)
])
}
おかしな挙動
- UIViewControllerのviewへaddSubviewするよりも前に、buttonへbadgeViewをaddSubviewしてみる
- するとバッジのレイヤが画像よりも後ろになってしまう
override func viewDidLoad() {
super.viewDidLoad()
// ボタン作成
let button = UIButton(configuration: .plain())
button.configuration?.image = .init(systemName: "house.fill")
button.translatesAutoresizingMaskIntoConstraints = false
// ボタンの上に赤丸を設置
let badgeView = UIView()
badgeView.backgroundColor = .red
badgeView.layer.cornerRadius = 4
badgeView.translatesAutoresizingMaskIntoConstraints = false
button.addSubview(badgeView)
NSLayoutConstraint.activate([
badgeView.topAnchor.constraint(equalTo: button.topAnchor, constant: 4),
badgeView.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: -4),
badgeView.widthAnchor.constraint(equalToConstant: 8),
badgeView.heightAnchor.constraint(equalToConstant: 8)
])
// viewに追加
view.addSubview(button)
NSLayoutConstraint.activate([
button.widthAnchor.constraint(equalToConstant: 32),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
- ヒエラルキーでも画像よりも後ろへ配置されてしまっていることがわかる
- configurationを使わずに
setImage(_:for:)
を使った場合は問題ない - setImageでもconfigurationを設定した場合は発生するので注意
override func viewDidLoad() {
super.viewDidLoad()
// ボタンを設置
let button = UIButton()
button.setImage(.init(systemName: "house.fill"), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
// ボタンの上に赤丸を設置
let badgeView = UIView()
badgeView.backgroundColor = .red
badgeView.layer.cornerRadius = 4
badgeView.translatesAutoresizingMaskIntoConstraints = false
button.addSubview(badgeView)
NSLayoutConstraint.activate([
badgeView.topAnchor.constraint(equalTo: button.topAnchor, constant: 4),
badgeView.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: -4),
badgeView.widthAnchor.constraint(equalToConstant: 8),
badgeView.heightAnchor.constraint(equalToConstant: 8)
])
// viewに追加
view.addSubview(button)
NSLayoutConstraint.activate([
button.widthAnchor.constraint(equalToConstant: 32),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}