2017-01-25 15 views
0

私はUITableViewに似たいくつかのアイテムを表示している、軸が垂直のUIStackViewを持っています。しかし、私はそれらをDispatchQueue.main.asyncAfterを使ってアニメーション化しています。このアプリは、古いデバイスを取り組む必要があるとして、少なくともシミュレータ上で(私は、これは問題にすべきとは思わない、いくつかの理由についてCABasicAnimationはUIStackViewでは信頼できませんか?

let anim = CABasicAnimation(keyPath: "transform.translation.x") 
anim.duration = 0.2 
anim.fromValue = UIScreen.main.bounds.size.width 
anim.toValue = 0 
anim.isRemovedOnCompletion = true 
anim.fillMode = kCAFillModeRemoved 

:ここ

は私がCABasicAnimationを作成するために使用していたコードです、またはiPhone 7+などの強力なデバイス)、アニメーションが必ずしも同じ場所に着くとは限りません。

時には、セルが飛び込み、左から約8ピクセル、時には約12、時には約20になることもあります。一貫しているようには見えません。しかし、私はtoValueが0であると思う、私は層にアニメーションを追加しなかった場合、それは通常どこに表示されるはずです。

isRemovedOnCompletionをtrueに設定し、fillModeを削除しようとしましたが、これはアニメーションを修正していないようです。

アニメーションが続くにつれて、セルが水平UIStackViewから作成され、そこに配置されたサブビューが非表示になる点が1つあります。私はUIView.animateWithDurationメソッドを使って隠れた値をfalseに設定し、サブビューをアニメーション化します。

私は、これが起こると、上記のセルが数ピクセル離れているのではなく、その位置にポップバックするためです。

アニメーションを作成した後にセルでsetNeedsDisplayを試してみましたが、verticalStackViewでも動作しませんでした。私は何が起こっているのか、なぜこれらのレイヤーが正しい位置にアニメーション化されないのか理解できません。誰のアイデアですか?

P.S.垂直スタックビューは、ViewControllerのinitメソッドですべて初期化されます。アニメーションは、viewDidAppearメソッドで発生します。 DispatchQueue.main.asyncAfterを追加してアニメーションをオフセットしてみましたが、super.viewDidAppear(アニメーション)の後に最初に試しましたが、どちらも同じ結果でした。

+0

Xの位置を変換しようとするのではなく、おそらくより効果的にアニメーション化することになります。スタックビューはautolayoutを広く使用しており、このシステムの外で効果的に作業しています。 – Paulw11

+0

UIViewがUIStackView内にあるUIViewの主要な値のストーリーボード内の定数を編集しようとしました。それはそれを好まない。 stackviewがそれを許さない場合、どのように位置の制約をアニメーション化するのですか?たぶん、プレースホルダーセルを作成する必要があります。コンテンツをアニメーション化しますか? – Kjell

+0

はい、プレースホルダを追加し、それを修正しました。 – Kjell

答えて

1

実際にスタックビューの内外にアイテムをアニメーション化するのは、非常に簡単です。

ビューのフレームをスタックビューに追加する前に開始する場所に設定し、新しいビューを追加した直後にアニメーションブロック内でlayoutIfNeeded()を呼び出すだけで済みます。ここに、作業中のアプリケーションから取得したサンプルコードの一部を示します。

let newView = createNewView() 
self.stackView.addArrangedSubview(newView) 
if sender != nil { 
    UIView.animate(withDuration: 0.2) { 
    self.stackView.layoutIfNeeded() 
    } 
} 
+0

したがって、すべてのセルを左からフライしたい場合は、そのフレームを、配置されたサブビューとして追加された後の位置に設定する必要がありますが、xPositionのscreenWidthをマイナスしますか?それはちょっと複雑に思えるので、私はそれを計算しなければなりません。その場合、なぜすべての計算を単純化しないと、スタックビューを使って始めますか? – Kjell

+0

これは、ユーザごとに新しいarrangedSubviewsのインタラクションを追加した状況ではかなり良い解決策になります。UIStackViewに計算させる代わりに、計算した位置から発信してほしいと思っていました。ユーザーがプラスボタンをタップした場所と同様に、金貨などの袋から金貨が一度に1つずつアニメーション化されます。 – Kjell

+0

うん、それは私が心に持っていたことだ。 –

0

この問題を解消しました。ここに問題があります...

1)プレゼンテーションレイヤーだけをアニメーション化したいが、UIStackViewポジショニングのために要素の実際の位置を保持したい。だからCoreAnimationは素晴らしい選択肢のようだ。

2)あなたはUIStackViewを扱っているため、一見すると、その配置されたサブビューの位置制約をアニメーション化することはできません。したがって、制約をアニメートしたくないもう一つの理由は、CoreAnimationを使うことです。

したがって、CoreAnimationを選択します。それは重要なプレゼンテーションレイヤーなので、制約をアニメートする必要はありませんか?ユーザーのインタラクティブなビューの部分を制約に従わせたい場合は、実際にそれらを行う必要があります。はい、いいえ。

しかし、CoreAnimationは何らかの理由で何をするかはしません。多分、アップルはそれを将来修正するだろう。しかし、そうでないかもしれない。ああ、それは問題ではない。これは解決策です:

stackview内のすべての配置されたサブビューのプレースホルダを使用します。私の場合、これはUIView内のコンテンツに基づいてサイズを変更するUIViewに過ぎませんでした。

ここで、このプレースホルダに背景色がありません。今までにアニメートしたくない目に見えるコンテンツだけを許可します。私はセル全体をアニメーション化しているので、backgroundColorを持たない空のUIViewがあります。

プレースホルダビューのこのプレースホルダビューのサブビューに対する制約を設定します。これで、通常のAutoLayoutアニメーションツールでこれらの制約をアニメートできます。例:

constraint.constant = 0 
UIView.animate(withDuration: 0.2, 
    delay: 0.1, 
    options: UIViewAnimationOptions.curveEaseOut, 
    animations: { 
     cell.layoutIfNeeded() 
    }, completion: nil) 

Booyah!アニメーションは滑らかで、実際には、配置されたサブビューを基準にして、どこで終了しますか。ウーホー!

関連する問題