Help us understand the problem. What is going on with this article?

iOS13でUISegmentedControlの見た目をカスタマイズする

※ 実装/動作確認環境: Xcode 11 beta5 + Simulator
※※ iOS13正式リリース前につき、スクリーンショットは未掲載(100%見た目についての話なのでなんとも物足りない感じですが…)。

背景

iOS13ではUISegmentedControlの見た目が変更される。
それに伴い、見た目(主に色)のカスタマイズをする場合、iOS12以前とは異なる方法で行う必要がある。

さしあたりの対応として行ったことをメモ。
(DarkMode対応なども鑑みるとカスタマイズなしで使うようにUIを設計し直すのが妥当とは思うが…)

iOS12以前

tintColorがビューやラベルの色に適用されるため、ここに任意の色を指定するだけでOKだった。

tintColor = UIColor.orange

iOS13

デフォルトの表示が無彩色となり、tintColorに依存しなくなった。

以下の方法でそれなりにカスタマイズできる。しかしそれぞれ一長一短あり。

selectedSegmentTintColor を使用する方法

tintColor ではなく selectedSegmentTintColor を指定することで、選択中のセグメントの背景色を設定できる。
また、文字色はデフォルトで黒色であるため、設定する背景色によっては文字色も変更したほうがベター。

func configure() {
  let color = UIColor.orange

  selectedSegmentTintColor = color
  setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .selected)
  setTitleTextAttributes([NSAttributedString.Key.foregroundColor: color], for: .normal)
}
メリット

コード量も少なく、やっていることも明確である点。
基本的にはこの程度のカスタマイズで収めたい。

デメリット

この方法ではビューの背景にある薄いグレーはそのままなので、selectedSegmentTintColor の明度によってはコントラストが弱くなる恐れがある。
(View Hierarchyを確認したところ、SegmentControlのsubview内に半透明のグレー画像が設定されたUIImageViewがある模様)

コントラストに懸念があり、かつ色も変更できない場合は次の方法で薄いグレーの背景を除去するのがよさそう(ただし急場しのぎ。詳細は後述)。

setBackgroundImage() を使用する方法

func configure() {
  let color = UIColor.orange

  // 背景を単色画像に差し替え
  setBackgroundImage(UIColor.clear.toImage(), for: .normal, barMetrics: .default)
  setBackgroundImage(color.toImage(), for: .selected, barMetrics: .default)

  // ラベルのスタイルを設定(選択中のセグメントのラベルがBoldでなくなるので、合わせて設定)
  setTitleTextAttributes(
    [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 13.0),
     NSAttributedString.Key.foregroundColor: UIColor.white],
    for: .selected)
  setTitleTextAttributes([NSAttributedString.Key.foregroundColor: color], for: .normal)

 // グレー領域がなくなったことで境界がわかりづらくなるので、ボーダーを追加
 layer.borderColor = color.cgColor
 layer.borderWidth = 1.0
}

↑で使用している UIColor.toImage() は1x1の単色UIImageを生成する拡張メソッド。実装方法はこちらの記事等を参照。

メリット

背景のグレーがなくなるので、SegmentedControlの色をより自由に決められる点。

デメリット

ビューの構造も変わってしまうらしく、見た目はiOS12以前のSegmentedControlのようになってしまう。

また、たかだか6ステップ程度ではあるが、先の方法よりは回りくどい。
そうまでしてiOS12以前っぽい見た目にするのか?となるので、やはりiOS13標準に則ったUIに変更するのが真っ当だと思う。

参考

gaussbeam
通りすがりのiOSアプリ開発者
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした