AloeStackViewとは
AloeStackViewはAirbnbが作ったUIを速くつるるためのViewで、UITableViewみたいな縦のリストレイアウトがUITableViewのようにdelegateやdataSourceを用意せずに簡単に実装できます。
これまでだとこういった用途の場合は、UIStackViewで縦に並べて実装したりしていましたが、タップ時の挙動やセパレーターをつくったりなど細かいところをいちいち自前で実装しなければなりませんでした。AloeStackViewも中身はUIStackViewですが、こういった面倒なところがぱぱっとできるようにinterfaceが用意されているので自前でUIStackViewを使うより便利になっています。
ただ、AloeStackViewは速くシンプルに作ることを目的としているので、UITableViewのようにViewの再利用はしません。大きい画面だとメモリを食いますし、最初の描画に時間がかかってしまうというデメリットもあります。なので完全にUITableViewを置き換えるものではありません。
コードが500行以下と小さく(UIScrollViewにUIStackViewを配置して縦に並べているだけ)、外部のライブラリも使ってないので導入のハードルは低めですので、気軽に試しやすいライブラリではないかなと思います。
Airbnbのblogでも紹介されているので興味ある方はこちらも御覧ください。
AloeStackViewの使い方
基本
viewを作って
import AloeStackView
let stackView = AloeStackView()
表示するviewをaddRowするだけです
let label = UILabel()
label.text = "Label"
stackView.addRow(label)
そうするとこのようにUITableViewでcellを追加したかのような表示になります。
Viewの再利用はないので、このLabelのテキストを更新したい場合は
label.text = "Text"
単純にviewを更新するだけです。(UITableViewのようにcellをreloadする必要はありません)
画面全体でAloeStackViewを使いたい場合はAloeStackViewControllerが用意されているのでこれを使ってもよいです。現在(v1.0.1)時点ではStoryboardに対応していないのでコードでAloeStackViewControllerを生成しなればなりません。(Storyboard上でAloeStackViewControllerを設定するのは☓)
import AloeStackView
class ViewController: AloeStackViewController {
override func viewDidLoad() {
super.viewDidLoad()
stackView.addRow(...)
}
}
Rowの追加、挿入、削除
Row(UITableViewでいうところのcell)の追加、削除には、それぞれ一つのRowを追加、削除するメソッドと複数のRowをまとめて追加、削除するメソッドの両方が用意されています。
末尾に追加
func addRow(_ row: UIView, animated: Bool = false)
func addRows(_ rows: [UIView], animated: Bool = false)
先頭に挿入
func prependRow(_ row: UIView, animated: Bool = false)
func prependRows(_ rows: [UIView], animated: Bool = false)
指定したRow(View)の前に挿入
func insertRow(_ row: UIView, before beforeRow: UIView, animated: Bool = false)
func insertRows(_ rows: [UIView], before beforeRow: UIView, animated: Bool = false)
指定したRow(View)の後に挿入
func insertRow(_ row: UIView, after afterRow: UIView, animated: Bool = false)
func insertRows(_ rows: [UIView], after afterRow: UIView, animated: Bool = false)
指定したRowの削除
func removeRow(_ row: UIView, animated: Bool = false)
func removeRows(_ rows: [UIView], animated: Bool = false)
全Row削除
func removeAllRows(animated: Bool = false)
タップ
Rowをタップしたときに処理を行うには2通りの方法があります。
TapHandlerを使うパターン
一つはTapHandlerを使う法法です。
func setTapHandler<RowView: UIView>(forRow row: RowView, handler: ((RowView) -> Void)?)
stackView.setTapHandler(
forRow: label,
handler: { [weak self] label in
self?.showAlert(title: "Row Tapped", message: "Tapped on: \(label.text ?? "")")
})
label.isUserInteractionEnabled = true
気をつけることは、isUserInteractionEnable
がtrueのときにしか反応しないようになっている点です。
Tappableを使うパターン
もう一つの方法はRowにaddするViewをTappableに適用させてdidTapView()を実装することです。
そうするとタップするとdidTapView()が呼ばれます。
class ToggleLabel: UILabel, Tappable {
func didTapView() {
textColor = textColor == .red ? .black : .red
}
}
let label = ToggleLabel()
label.text = "Label"
label.isUserInteractionEnabled = true
stackView.addRow(label)
こちらの場合も、isUserInteractionEnable
がtrueのときにしか反応しないようになっています。
タップしたときにハイライトする
Highlightableプロトコルを適用してやるだけです。
class ToggleLabel: UILabel, Highlightable {
}
Rowの表示非表示
非表示
func hideRow(_ row: UIView, animated: Bool = false)
func hideRows(_ rows: [UIView], animated: Bool = false)
表示
func showRow(_ row: UIView, animated: Bool = false)
func showRows(_ rows: [UIView], animated: Bool = false)
表示・非表示
上のshowRow
hideRow
との違いはisHiddenで表示非表示をセットするかの違いです。
func setRowHidden(_ row: UIView, isHidden: Bool, animated: Bool = false)
func setRowsHidden(_ rows: [UIView], isHidden: Bool, animated: Bool = false)
表示非表示状態の取得
func isRowHidden(_ row: UIView) -> Bool
スタイル
Rowの余白の設定と、背景色、選択色、セパレータのデフォルトの色や個別のRowの色の設定を行うことができます。
RowのInset(Padding)
Rowの上下左右の余白を変更したい場合に使います。
-
var rowInset
- addしたあとに変更しても変わりません
-
func setInset(forRow row: UIView, inset: UIEdgeInsets)
-
func setInset(forRows rows: [UIView], inset: UIEdgeInsets)
- addした後変更したい場合はこちらを使います。
背景色
Rowの背景色を変更したい場合に使います。
-
var rowBackgroundColor
- デフォルトは透明。
- addしたあとにrowBackgroundColorを変更しても変わりません
-
func setBackgroundColor(forRow row: UIView, color: UIColor)
-
func setBackgroundColor(forRows rows: [UIView], color: UIColor)
- addした後変更したい場合はこちらを使います。
選択色
Rowを選択したときの色を変更したい場合に使います。
※StackViewCellのメソッドなのでcellForRow()でStackViewCellを取得して呼ぶ必要があります。
var rowHighlightColor
セパレータ関連
セパレータの色
var separatorColor
セパレータの高さ
var separatorHeight
セパレータのInset
-
var separatorInset: UIEdgeInsets
- addしたあとに変更しても変わりません
-
func setSeperatorInset(forRow row: UIView, inset: UIEdgeInsets)
-
func setSeperatorInset(forRows rows: [UIView], inset: UIEdgeInsets)
- addした後変更したい場合はこちらを使います。
セパレータの表示非表示
-
var hidesSeparatorsByDefault
- デフォルト値:false
- デフォルトでセパレータを非表示にする設定。addしたあとに変更しても変わりません
-
func hideSeparator(forRow row: UIView)
-
func hideSeparators(forRows rows: [UIView])
-
func showSeparator(forRow row: UIView)
-
func showSeparators(forRows rows: [UIView])
- addした後変更したい場合はこちらを使います。
-
var automaticallyHidesLastSeparator
- デフォルト値:
false
- 一番下のRowのセパレータを自動で隠す設定。
- デフォルト値:
-
SeparatorHidingプロトコル
-
SeparatorHidingプロトコルを適用してやるとそのRowだけセパレータが表示されません。
class ToggleLabel: UILabel, SeparatorHiding {
}
その他
全Row取得
func getAllRows() -> [UIView]
Rowがあるか
func containsRow(_ row: UIView) -> Bool
Rowを見える位置にスクロール
func scrollRowToVisible(_ row: UIView, animated: Bool = true)
AloeStackViewを継承して使う用
-
func cellForRow(_ row: UIView) -> StackViewCell
- cellを追加したりしたときの呼ばれてrowに対応するStackViewCellを返す。
-
func configureCell(_ cell: StackViewCell)
- 中身は空。生成時(rowのadd, insert)に呼ばれる。
まとめ
一通り実装を見ていくと、move系以外はUITableViewでできること主なことはだいたいできるようでした。
一番下の行のセパレータを自動で隠す機能についてはUITableViewよりもAloeStackViewのほうが便利だなと思いました。