0

私は数日間、次の問題と戦っています。私が間違っていることについてのドキュメントには何も見つかりません。デバッガーをクロールして、あらゆる種類の情報をコンソールにダンプしましたが、表示されているものを修正する方法がわかりません。

私の最上位ビュー コントローラーは、UINavigationController のサブクラスです。これには、データを視覚化するために使用される UIPageViewController のサブクラスが含まれています。また、アプリ設定を設定するための UITableViewController のサブクラスも含まれています。この「オプション」ビューは、プッシュ セグエを介してページ ビュー コントローラに「リンク」されます。この時点で、すべてが正常に機能しました。

問題は、データを視覚化するさまざまな方法 (ページ ビュー コントローラーでの水平スクロール) とオプション ビューの表示の間の視覚的な遷移を区別したかったときに始まりました。そこで、オプション コントローラを画面上部から「引き伸ばす」(プッシュ時)、またはオプション コントローラを画面上部に「ロールアップする」(ポップ時) カスタム アニメーションを作成しました。このアニメーションは、navigationController:animationControllerFor:operation:from:to: メソッドを使用してナビゲーション コントローラーに設定します。

オプションコントローラーを表示する前は、デバイスの回転中にすべてが正常に機能しているようです。 オプション コントローラーを表示/非表示にした後、回転中にデータ視覚化コントローラーのレイアウトが崩れます。オプション コントローラーを閉じたときのデバイスの向きでは正しく表示されますが、反対の向きでは正しく再生されません。

ナビゲーション コントローラー (またはおそらくページ ビュー コントローラー) が、ステータス、ナビゲーション、およびツールバーの高さを処理する方法を忘れているようです。


次のデバッグ スクリーンショットは、5 秒シミュレーターでの問題を示しています。

  1. 初期状態。コンテンツ ビュー (赤) は、ステータス、ナビゲーション、およびツールバーの下にあることに注意してください。

ここに画像の説明を入力

  1. 向きを水平に回転しました。これまでのところ、すべて問題ありません。デバッグ コンソールには、ビューが "回転" されるサイズ (568x212)、ステータス、ナビゲーション、ツールバーの前後の高さ、画面サイズ、フレームの四角形、およびレイヤーの位置が表示されます。ここでは示していませんが、レイヤーのアンカーポイントが (0.5, 0.5) から変化することはありません。

ターゲット ローテーション サイズは、次のルールを使用して設定されることに注意してください。

  • rot_width(568) = old_frame_height(460) + sum_of_bar_heights(108)
  • rot_height(212) = old_frame_width(320) - sum_of_bar_heights(108)

結果のフレーム サイズは、次のルールを使用して設定されます。

  • new_frame_width(568) = rot_width(568)
  • new_frame_height(256) = rot_height(212) + change_in_bar_height(108-64)

結果のフレーム原点 (0,64) は、ステータス バー (20) とナビゲーション バー (44) の合計によって、画面の上部からオフセットされます。

ここに画像の説明を入力

  1. 向きを回転させて垂直に戻しました。繰り返しますが、すべて問題ありません。デバッグ コンソールは、「逆」回転について上記と同じ情報を追加します。回転サイズと結果のフレーム サイズは、上記と同じ規則に従います。

ここに画像の説明を入力

  1. カスタム アニメーションを使用してオプション エディター コントローラー ビューをナビゲーション スタックにプッシュしました。デバッグ コンソールは、上記と同じ情報を (現在表示されていない) コンテンツ ビューに追加します。何も変わっていないことに注意してください。

ここに画像の説明を入力

  1. カスタム アニメーションを使用して、オプション エディター コントローラー ビューをナビゲーション スタックからポップしました。上のコンテンツ ビューがビューに戻ります。デバッグ コンソールは、上記と同じ情報を追加します。繰り返しますが、何も変わっていません。

注意:オプション エディタが表示される前 とは、重なり順が異なります。

このスタックの並べ替えは、デフォルトのトランジション アニメーターを使用する場合には保持されません (pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted から nil を返すことにより)。

ここに画像の説明を入力

  1. ステップ1 の繰り返し。コンテンツ ビューは、ナビゲーション バーやツールバーにぴったりと収まりません。デバッグ コンソールは、ローテーションに入るすべてがステップ 1 と同じように見えることを示しています。

しかし、ローテーションの結果はステップ 1 とは異なります。ルールが変更されたようです。結果のフレーム サイズは、ステータス、ナビゲーション、およびツールバーの高さの変更を考慮して調整されなくなり、フレームの原点は回転前の値から変更されません。

ここに画像の説明を入力

  1. 手順 2 を繰り返します。すべてが修正されたように見えますが、それは単に新しいサイズ変更ルールに従って再生されているためです。

ここに画像の説明を入力


私のアニメータークラスはここに示されています(上記のデバッグ情報を生成するために使用されたプローブを除いて、全体として):

class OptionsViewAnimator: NSObject, UIViewControllerAnimatedTransitioning
{
  var type : UINavigationControllerOperation

  init(_ type : UINavigationControllerOperation)
  {
    self.type = type
  }

  func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
  {
    return 0.35
  }

  func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
  {
    if      self.type == .push { showOptions(using:transitionContext) }
    else if self.type == .pop  { hideOptions(using:transitionContext) }
  }

  func showOptions(using context: UIViewControllerContextTransitioning)
  {
    let src       = context.viewController(forKey: .from)!
    let srcView   = context.view(forKey: .from)!
    let dstView   = context.view(forKey: .to)!
    var dstEnd    = context.finalFrame(for: context.viewController(forKey: .to)!)

    let barHeight = (src.navigationController?.toolbar.frame.height) ?? 0.0

    dstEnd.size.height += barHeight

    dstView.frame = dstEnd
    dstView.layer.position = dstEnd.origin
    dstView.layer.anchorPoint = CGPoint(x:0.0,y:0.0)
    dstView.transform = dstView.transform.scaledBy(x: 1.0, y: 0.01)

    UIApplication.shared.keyWindow!.insertSubview(dstView, aboveSubview: srcView)

    UIView.animate(withDuration: 0.35, animations:
      {
        dstView.transform = .identity
      }
    ) {
      (finished)->Void in
      context.completeTransition( !context.transitionWasCancelled )
    }
  }

  func hideOptions(using context: UIViewControllerContextTransitioning)
  {
    let dst       = context.viewController(forKey: .to)!
    let srcView   = context.view(forKey: .from)!
    let dstView   = context.view(forKey: .to)!
    let dstEnd    = context.finalFrame(for: context.viewController(forKey: .to)!)

    dstView.frame = dstEnd

    srcView.layer.position = dstEnd.origin
    srcView.layer.anchorPoint = CGPoint(x:0.0,y:0.0)
    srcView.transform = .identity

    UIApplication.shared.keyWindow!.insertSubview(dstView, belowSubview: srcView)

    UIView.animate(withDuration: 0.35, animations:
      {
        srcView.transform = srcView.transform.scaledBy(x: 1.0, y: 0.01)
      }
    ) {
      (finished)->Void in
      context.completeTransition( !context.transitionWasCancelled )
    }
  }
}

あらゆる/すべての助けに感謝します。 マイク

4

2 に答える 2