Edited at

DZNEmptyDataSetでbuttonTitleに合わせてBackgroundImageのsizeを調節する

More than 3 years have passed since last update.

今国際化に伴い、アプリを大幅改修しています。

こんな感じの画面を作ろうと思っていました。

ライブラリはDZNEmptyDataSetを使っています。

Screen Shot 0028-07-17 at 18.37.09.png



今まで

文言(画像のCreate New Streamの部分)を日本語で指定していた

=> 自ずと文言のサイズは一意的に決まる

=> そのLabelのサイズに合わせてpaddingを指定して、かつ、文言も含んだImageを用意していた


国際化

文言は国・地域によって変化する

=> 文言のサイズはもちろん動的に変化する

=> 背景画像だけ別で用意して、動的に変化するLabelのサイズに合わせて大きさを上手い感じに合わせる必要がある

というわけで流れとしては、


  • 背景画像の用意(Normal/Highlighted)

  • titleLabelのサイズを測って変数に格納しておく

  • backgroundImageの描画の際に、上記のサイズに合わせてimageのwidthを調節する

サクッと元のソースコードを見ながら自分でもサンプルを作ってみました。


DZNEmptyDataSetとは

TableView, collectionViewが空の時に代わりに表示するものを作成するためのライブラリ

参考


delegate method一覧

func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {

// titleを指定する
}

func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {

// 説明文を指定
}

func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {

// 画像を指定
}

func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {

// buttonのtitleを指定
}

func buttonImageForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> UIImage! {

// buttonに貼る画像を指定
}

func buttonBackgroundImageForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> UIImage! {

// buttonの背景画像を指定
}

func backgroundColorForEmptyDataSet(scrollView: UIScrollView!) -> UIColor! {

// 全体のviewの背景の色を指定
}

func verticalOffsetForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {

// contentsの位置をviewの上端からどれくらいの距離離すかを指定
}

func spaceHeightForEmptyDataSet(scrollView: UIScrollView!) -> CGFloat {

// contentsが複数ある場合、それぞれの距離をどれくらい離すかを指定
}

func emptyDataSetShouldDisplay(scrollView: UIScrollView!) -> Bool {

// emptyDataSetのcontentsを表示するか否か
}

func emptyDataSetDidTapView(scrollView: UIScrollView!) {

// 全体のviewをtapした時のアクションを指定
}

func emptyDataSetDidTapButton(scrollView: UIScrollView!) {

// 作成したbuttonをtapした時のactionを指定
}


buttonBackgroundImageForEmptyDataSetでtitleに合わせてsizeを変える

これが面倒だったのでshareします。

やりたいことは最初に説明した通りです。

func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {

let str = "Create New Stream"
let font = UIFont.systemFontOfSize(14.0, weight: 2.0)

// 文言のサイズを格納しておく
titleSize = str.widthWithConstrainedHeight(44, font: font)

return NSAttributedString(
string: str,
attributes: [
NSFontAttributeName: font,
NSForegroundColorAttributeName: ColorUtil.rgba(172, green: 175, blue: 189)
]
)
}

func buttonBackgroundImageForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> UIImage! {

// 引き伸ばされたbackgroundImageとview.bounds.size.widthとの比率。
// どの機種でもだいたい88%でした
let ratioViewBoundsWidthAndButton: CGFloat = 0.88

// 引き伸ばされたbackgroundImageのsize
let defaultSize = view.bounds.size.width * ratioViewBoundsWidthAndButton

// titleLabelのpadding.お好みで
let padding: CGFloat = 20

// 背景画像を引き伸ばしてからtitleLabelに合わせてwidthを調節してUIImageを返す
return UIImage.makeBackgroundImage(state).shrinkImageAdjustingObject(before: defaultSize, objectSize: messageSizeForEmptyDataSet, padding: padding)
}

extension UIImage {

// 引き延ばした画像を返すメソッド
class func makeBackgroundImage(state: UIControlState) -> UIImage {

let baseImage = (state == UIControlState.Highlighted) ? R.image.btn_highlight()! : R.image.btn()!

// capInsetsは引き延ばす時に引き伸ばしたくない一部分を指定できる
// ここでは四端5.0×5.0だけそのままのサイズで他を引き延ばすイメージ
let capInsets = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)

return baseImage.resizableImageWithCapInsets(capInsets, resizingMode: UIImageResizingMode.Stretch)
}

// 内部のobjectのサイズとpaddingを指定すれば、imageのwidthを拡大・縮小するメソッド
func shrinkImageAdjustingObject(before imageSize: CGFloat, objectSize: CGFloat, padding: CGFloat) -> UIImage {

var rectInsets = UIEdgeInsetsZero

// imageの端と内部のオブジェクトの端までの距離(片方ずつ)
let widthBetweenBackgroundAndLabel = (imageSize - objectSize)/2

// paddingを考慮してimageをどれくらい拡大・縮小させるか、の指定
let shrinkWidth = widthBetweenBackgroundAndLabel - padding
rectInsets = UIEdgeInsets(top: 0, left: -shrinkWidth, bottom: 0, right: -shrinkWidth)

return imageWithAlignmentRectInsets(rectInsets)
}

}

参考