0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

えーえすAdvent Calendar 2024

Day 1

UILabelが角丸にならない!- clipsToBoundsとは何か?-

Last updated at Posted at 2024-11-30

はじめに

UILabelを角丸にしたいのに角丸にならない!という経験をしたことある人、結構多いんじゃないでしょうか?

こうやって書いてるのに!
label.layer.cornerRadius = 10

この時以下のように、1行追加すると途端に角丸になります。

正解
label.layer.cornerRadius = 10
label.clipsToBounds = true

clipsToBounds=trueとは一体何なんでしょうか?

UILabelとUIButtonの構造の違い

混乱の原因となっているのはUIButtonの挙動で、こっちは1行で角丸になります。

これで角丸になる
button.layer.cornerRadius = 10

ここで、UILabelUIButtonの構造をHierarchyを用いて観察してみます。

以下のように、layer.cornerRadiusのみ設定した状態だと画像のようになります。

label.layer.cornerRadius = 10
button.layer.cornerRadius = 10

スクリーンショット 2024-11-28 17.48.28.png

やはりUILabelだけうまく角丸になりません。

ここで実行中に以下のボタンをクリックすることで構造を見ることができます。

スクリーンショット 2024-11-28 16.52.45.png

スクリーンショット 2024-11-28 16.53.35.png

ここで大事なのは、UIButtonのclipsToBoundsもfalseであること。それは以下のように確認されます。

スクリーンショット 2024-11-28 17.08.40.png

そもそもclipsToBoundsは何をしている?

公式ドキュメントでは、

A Boolean value that determines whether subviews are confined to the bounds of the view.

とあります。

ここでのboundsとはViewのと捉えてよいので、(frameとは座標系の差しかない)、Viewの枠の外側に要素を描画するかどうかということになります。

外側にはみ出るとはどういう場合か、については、以下の記事が大変参考になります。

では、根本的な原因は何なのでしょうか。

構造が異なることが原因

ここで大事なのは、UILabelとUIButtonの層の数が異なるということです。
UIButtonはこのように3つの層からできており、一番後ろのView(UIButton)のSubviewとして_UISystemBackgroundViewUILabelがあることが確認できます。

スクリーンショット 2024-11-28 16.56.04.png

スクリーンショット 2024-11-28 17.00.41.png

一方UILabelは一つしか層がありません。

スクリーンショット 2024-11-28 17.01.34.png

さて、ここで以下の2行を追加して、UILabelのboundsを描画してみましょう。

label.layer.borderColor = CGColor(red: 1, green: 0, blue: 0, alpha: 1)
label.layer.borderWidth = 2.0

すると以下のようになります。

スクリーンショット 2024-11-28 17.19.52.png

したがって、boundsはしっかり角丸になっているが、背景の要素がboundsをはみ出て描画されていることが原因だとわかります。

UIButtonが角丸になる原因の考察

UIKitのパーツは内部構造がブラックボックス化されているため完全な理由は分かりませんが、Hierarchyからヒントをもらうことは可能です。

最下層のViewをクリックすると、以下のような情報が出てきます。

UILabel

スクリーンショット 2024-11-28 17.28.59.png

UIButton

スクリーンショット 2024-11-28 17.29.11.png

UIButtonはただのCALayerで実装されていますが、UILabelは特注の_UILabelLayerなるもので実装されていることがわかります。

ここで、dump(button.layer)などしてみる(printでも可)と、button.layerでアクセスされるのはこのCALayerであることがわかります。

スクリーンショット 2024-11-28 17.38.16.png

したがって、

  • UIButton.layer.cornerRadiusは最下層のlayerを角丸にするため、boundsどおり角丸になる
  • UILabel.layer.cornerRaduisでは、_UILabelLayerで背景とboundsが別の層にあると考えられ、bounds通りに角丸にならない

と考えられます。

UILabelを角丸にする方法

原理を理解したところで、角丸にする方法をおさらいしましょう。

layerを角丸にする

label.layer.cornerRadius = 10
label.clipsToBounds = true

また、layerをboundsの形に合わせるという処理として、

label.layer.cornerRadius = 10
label.layer.masksToBounds = true

ともかけます。

まとめ

UIViewの内部構造が秘匿されているため完全に原因を究明できないのが残念ですが、Hierarchyを駆使すればここまで構造を把握することができます。
ここまで理解できたら、clipsToBoundsと書くのも苦じゃないですね!

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?