モノトーンの伝説日記

スプラトゥーンが大好き。

<mini> 3D touch を使用したビューの peek/pop と本番の表示を切り替えたい件

 3D touch のときは NavigationBar が出ていませんが,そのあとは表示されるので,それの対策。

 基本的に iOS 11 をターゲットにする場合はある程度,この辺りうまくやってくれるんですが,iOS 10 だとうまく動作しないので,画面上に寄せるとき,3D touch が有効か,そうでないか,という実装がキモになります。

 まず,イベントの流れを以下の記事を参考にすると,

qiita.com

3D touch から通常ビューに切り替わるときには disappear で一度非表示になり,そのあと appear で表示状態になるので,そのタイミング,つまり appear で制約を更新する命令を走らせるのがベターでしょう (Xamarin の C# コードで申し訳ない;;)

private bool _didSetupConstraints;

public override void ViewWillAppear(bool animated)
{
  base.ViewWillAppear(animated);

  // 制約の更新を促す
  View.SetNeedsUpdateConstraints();
}

public override void UpdateViewConstraints()
{
  // iOS 10 以前のみで補正します。11 はそのあたりうまくやってくれるので。
  if (!UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
  {
    // NavigationController == null のとき,3D touch,そうでない場合通常ビューです。
    dynamicConstraint.Constant = NavigationController == null ? 0 : navigationBar.Frame.Bottom;
  }

  if (!_didSetupConstraints)
  {
    // 動的に更新する必要のない制約を定義します。
    staticConstraint.Constant = 0;

    _didSetupConstraints = true;
  }

  base.UpdateViewConstraints();
}

 これで問題なく動くはずです。iOS 11 で自動でシステムがやってしまうのと干渉するような動作が見られるのでちょっとやりづらいですね;;

 iOS 11 前提で作れるようになれば別の話ですが……