[iOS]UIStackViewのアニメーションが変!
世間話
今更UIStackViewと戯れているんですが、ちょいちょいわけわからん動きをしますね。
UITableViewと格闘して大嫌いになった人達がUIStackViewを絶賛していましたが、彼らは大丈夫だったんでしょうか。こっちも結構曲者ですよ・・・
Hide/Showアニメーションが変
UIStackViewの良いところは、なんと言ってもisHiddenでViewの表示/非表示が簡単にできるところですよね。
iOSでもAndroidのgoneが使いたいんだ!と何度思ったことが。
ですが、表示/非表示のAnimationをしようとしたところ、変な動きになりました。
// コードのイメージ
UIView.animate(withDuration: 0.3) {
self.stackView.arrangedSubviews[index].isHidden.toggle()
self.stackView.layoutIfNeeded()
}
一番上と一番下、お前らなんなん!?
ここらへん、ググっても全然出てきませんでした。
ちなみに条件は
- Alignment Fill
- Distribution Fill
- Spacing 0
- 各Viewにheightのconstraint
ああ、え、そういうこと?
半透明にしたらわかりました。
例えば3番目のViewをhiddenにしようとすると、4番目以降のViewが上にせり上がってきて、4番目のViewが3番目のViewに達したあとで3番目のViewが見えなくなります。
何で?(殺意)
これで最下部のViewの動きに合点がいきます。
最上部のViewの動きは何かルールが違っている気がしますが。。
意図した動きにするにはどうすればいいか?
この動きは非常に厄介です。
例えばViewが2つのStackViewを作って、上部をタイトル情報、下部に詳細情報にして、タップしたら開くとか、そういう基本的な動きすらアニメーションができなくなります。
そうだ、ClipToBoundsだ!
天啓を得てUIStackViewのClipToBoundsをtrueにしてみました。
何の成果も得られませんでした。
何で?(殺意)
解1:親Viewを作って、親ViewをClipToBoundsにする
上下左右をAutoLayoutでつないでやります。
これでいけました。
解2:高さのconstraintのPriorityを999にする
ちょっと隠れ方の挙動が違いますがこれでもいけました。
何で?(殺意)
すいませんが、これまだ理解できていません。
1000ならダメで、999ならいけるんです。
別の条件でも試してみる
DistributionをFillEqualyにしてみる①
UIStackView自体の高さを縛りました。
予想通りですが若干キモいですね、使い所が限られそう?
DistributionをFillEqualyにしてみる②
今度は一番上のViewの高さを縛ってみました
良さそうな動きをしますが、基準となる一番上のViewをhiddenにしたところ壊れてしまいました。
どのように高さを設定するか考える必要が出てきそうです。
確実に表示するViewがあればいいんですが。
Spacingがついていたらどうなる?①
Spacingをつけて、各Viewの高さを縛りました。
ああっ!そうなっちゃいますよね。
これはいけません。
Spacingがついていたらどうなる?②
UIStackViewの高さを縛ってみました。
これはちょっと使えそうですね。
Spacingがついていたらどうなる?③
動いてから消えるのが良くないので、消してから動かしてみましょう。
isHiddenは使えないので透明度をいじっています。
手品っぽくなりました。これはギリギリよさそうです。
UITableViewと連携する
やっぱり同じセルが増えてくるとTableViewに頼らざるを得なくなってきます。
UITableViewCellにUIStackViewを入れて、アニメーションしてみましょう。
AutoLayoutは上下左右をひっつけます。
何で?(殺意)
ちなみにアニメーションは
tableView.beginUpdates()
tableView.endUpdate()
こうか
UIView.animate(withDuration: 1.0) {
tableView.beginUpdates()
tableView.endUpdate()
}
こうです
さっきは、動いてから消えましたよね。
何で今回は消えてから動くんですか????
5分ぐらい考えてみましたがわかりません。保留です。
self sizingを諦める
しょうがないので、UITableView.automaticDimensionを諦めてみます。
UIStackViewとCellを、上左右のみ設定して、UIStackViewの高さのコントロールは上でやったとおりにします。
そしてCellの開閉アニメーションはオーソドックスにheightを変更して行います。
できました。
しかしself sizing好きなので、これには私も憤慨です。
特に今の高さではなくて、1個のViewをhidden/showしたあとの高さを求めるのがだるくてしょうがないです。
一応作りましたけど。スマートではないですね。
func expectedHeight(when viewOfIndex:Int, isHidden:Bool) -> CGFloat {
let height = arrangedSubviews.filter { !$0.isHidden }.reduce(0, { $0 + $1.frame.height })
if isHidden && !arrangedSubviews[viewOfIndex].isHidden {
return height - arrangedSubviews[viewOfIndex].frame.height
}
if !isHidden && arrangedSubviews[viewOfIndex].isHidden {
return height + arrangedSubviews[viewOfIndex].frame.height
}
return height
}
おわりに
内部でAutoLayoutがどうなってるのか見えにくいので、わからないことが多すぎます。
一個一個知識や経験として仲良くなっていくしか無い気がします。
闇が深い・・・
間違いや備考などあったら後ほど追加します。
次回
UIStackViewってちょいちょい言うこと聞かないですよね。
それで「私の本当に欲しかったStackView」を作ったのでその話をします。
→ 何か使ってみるとイマイチパッとしなかったのでやめます
よりリッチなものは既にライブラリが存在します。すばらしいです、よく作りますねこんなの。
ただちょっとヘビー?
StackViewController
https://github.com/seedco/StackViewController
AloeStackView
https://github.com/airbnb/AloeStackView
Author And Source
この問題について([iOS]UIStackViewのアニメーションが変!), 我々は、より多くの情報をここで見つけました https://qiita.com/netetahito/items/64d9689f371a773f9e2e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .