この特定のシナリオでは、私は実際には非常に混乱しています。私は UINavigationBar をサブクラス化し、Apple の古いサンプル コードに注目し、sizeToFit が呼び出されずにオーバーライドされ、必要な高intrinsicContentSize
さlayoutSubviews
を計算することに気付きました。私が提供するカスタム ビューに基づいて高さを計算する場合は、すべてうまく機能します (systemLayoutSizeFittingSize
カスタム コンテンツ ビュー/titleView に基づいて動的に高さを計算するために使用します)。
奇妙な部分は、変更をアニメーション化しようとすると、 custom の変更をアニメーション化できますが、をtitleView
介してintrinsicContentSizeをリロードするinvalidateIntrinsicContentSize()
と、ビューフレームの変更がアニメーション化されないことです。スナップします。
サンプルコード:
let delta = destinationTextFieldContainerView.frame.minX - originTextFieldContainerView.frame.minX + originTextFieldContainerView.frame.height
textContainersSeparatorConstraint.constant = -delta
UIView.animateWithDuration(2, delay: 2, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.customContainerNavigationBar.invalidateIntrinsicContentSize()
self.customContainerNavigationBar.layoutIfNeeded()
}) { (_) in
self.customContainerNavigationBar.invalidateIntrinsicContentSize()
}
1 つの制約値の変更はアニメーション化されますが、残念ながら (navBars は自動レイアウトに依存していないため) フレームの更新に問題があるようです。固有のサイズを無効にする前に、フレームを直接更新しようとしましたが、成功しませんでした。また、高さの制約を試して、異なるタイミング オフセットを持つキー フレーム アニメーションにリストし、異なる時点でレイアウトを無効にしましたが、すべて成功しませんでした。どんな助けでも大歓迎です。
サイズ変更コードは次の場所にあります。
override func intrinsicContentSize() -> CGSize {
var navigationBarSize = super.intrinsicContentSize()
navigationBarSize.width = superview?.frame.width ?? 0
guard let titleView = navigationItem?.titleView else {
return navigationBarSize
}
let fittingSize = CGSize(width: navigationBarSize.width, height: UILayoutFittingCompressedSize.height)
let titleViewSize = titleView.systemLayoutSizeFittingSize(fittingSize)
navigationBarSize.height = max(titleViewSize.height, 44)
navigationBarSize.width = UIViewNoIntrinsicMetric
return navigationBarSize
}
override func layoutSubviews() {
super.layoutSubviews()
guard let navigationItem = navigationItem, titleView = navigationItem.titleView else {
return
}
var navigationBarSize = bounds.size
navigationBarSize.width = superview?.frame.width ?? 0
var fittingSize = CGSize(width: navigationBarSize.width, height: UILayoutFittingCompressedSize.height)
if let leftBarButtonItem = navigationItem.leftBarButtonItem, leftButtonCustomView = leftBarButtonItem.customView {
fittingSize.width -= leftButtonCustomView.frame.width + leftButtonCustomView.frame.origin.x + 22
}
let titleViewSize = titleView.systemLayoutSizeFittingSize(fittingSize, withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityDefaultLow)
titleView.frame = CGRect(origin: CGPoint(x: titleView.frame.origin.x, y: 0), size: titleViewSize)
titleView.setNeedsLayout()
titleView.layoutIfNeeded()
if let leftBarButtonItem = navigationItem.leftBarButtonItem, leftButtonCustomView = leftBarButtonItem.customView {
var customViewFrame = CGRect(origin: CGPoint.zero, size: navigationBarSize)
let customViewSize = leftButtonCustomView.systemLayoutSizeFittingSize(customViewFrame.size, withHorizontalFittingPriority: UILayoutPriorityDefaultLow, verticalFittingPriority: UILayoutPriorityDefaultLow)
customViewFrame.size = customViewSize
leftButtonCustomView.frame = customViewFrame
leftButtonCustomView.setNeedsLayout()
leftButtonCustomView.layoutIfNeeded()
}
invalidateIntrinsicContentSize()
}