読者です 読者をやめる 読者になる 読者になる

cockscomblog?

cockscomb on hatena blog

UIButtonの画像の位置を変えたい

UIButton の画像の位置を、タイトルの左側じゃなく上側や右側にしたい。画像が左側じゃないボタンのモックを見たとき、どうやって実現するかいつも少し悩む。ということでいくつかのアプローチを検討したい。

drawRect(_:) など

UIButtonvar titleLabel: UILabel? { get }var imageView: UIImageView? { get } といった view を内包していて、描画はそういった view の側で行われるので、drawRect(_:) などの描画関連のメソッドをオーバーライドするべきではない。

独自に UIImageView を足したり CALayer を足したりして、表示される画像を追加することはできる。

setBackgroundImage(_:forState:)

画像を背景にする。UIImageresizableImageWithCapInsets(_:) と組み合わせれば、わりと好きな位置に画像を表示できるはずである。不毛な感じはする。

titleEdgeInsetsimageEdgeInsets

タイトルの画像の UIEdgeInsets でチマチマ調整する方法。もともと画像が左にあるところからがんばって計算することになって厳しい。

titleRectForContentRect(_:)imageRectForContentRect(_:)

titleRectForContentRect(_:)imageRectForContentRect(_:) といったメソッドをオーバーライドしていい感じの CGRect を返す。

似たような backgroundRectForBounds(_:) メソッドのドキュメントには

Subclasses that provide custom background adornments can override this method and return a modified bounds rectangle to prevent the button from drawing over any custom content.

ということが書いてあって、オーバーライドしてよいことがわかる。しかし contentRectForBounds(_:) を含む同種の他のメソッドには書いていない。同種の他のメソッドには対応する UIEdgeInsets があるので、そういうのを考慮しているからオーバーライドしないようにという意味なのか、温度感がわからない。

UIControl のサブクラス

完全に独自の Button を作ることもできる。UIControl を継承して何もかも自分で作ることで、自由な内容を描画できる。特に不都合はないが、面倒ではある。


titleRectForContentRect(_:)imageRectForContentRect(_:) のオーバーライドがいちばん現実的ではないか。という結論に至った。

詳解 Swift 改訂版

詳解 Swift 改訂版