스토리 보드, 코드, 팁 및 몇 가지 단점
다른 답변은 괜찮지 만 최근 예제를 사용하여 제약 조건에 애니메이션을 적용하는 몇 가지 중요한 문제점을 강조합니다. 나는 다음을 깨닫기 전에 많은 변형을 겪었습니다.
강력한 참조를 유지하기 위해 대상 변수를 클래스 변수로 만듭니다. 스위프트에서는 게으른 변수를 사용했습니다.
lazy var centerYInflection:NSLayoutConstraint = {
let temp = self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
return temp!
}()
몇 가지 실험을 한 후에 나는 제약 조건이 정의 된 두 개의 보기 위 의 뷰 (일명 슈퍼 뷰) 에서 제약 조건을 얻어야한다고 언급했습니다 . 아래 예에서 (MNGStarRating과 UIWebView는 둘 사이에 제약 조건을 만드는 두 가지 유형의 항목이며 self.view 내의 하위보기입니다).
필터 체이닝
Swift의 필터 방법을 활용하여 변곡점으로 사용할 원하는 구속 조건을 분리합니다. 하나는 훨씬 더 복잡해질 수 있지만 필터는 여기서 잘 작동합니다.
스위프트를 사용하여 구속 조건 애니메이션
Nota Bene-이 예제는 스토리 보드 / 코드 솔루션이며 스토리 보드에서 기본 제한 조건을 설정했다고 가정합니다. 그런 다음 코드를 사용하여 변경 사항에 애니메이션을 적용 할 수 있습니다.
정확한 기준으로 필터링하고 애니메이션의 특정 변곡점을 얻는 속성을 생성한다고 가정하면 (물론 여러 제약 조건이 필요한 경우 배열을 필터링하고 반복 할 수 있음) :
lazy var centerYInflection:NSLayoutConstraint = {
let temp = self.view.constraints.filter({ $0.firstItem is MNGStarRating }).filter ( { $0.secondItem is UIWebView }).filter({ $0.firstAttribute == .CenterY }).first
return temp!
}()
....
언젠가 ...
@IBAction func toggleRatingView (sender:AnyObject){
let aPointAboveScene = -(max(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height) * 2.0)
self.view.layoutIfNeeded()
//Use any animation you want, I like the bounce in springVelocity...
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 0.75, options: [.CurveEaseOut], animations: { () -> Void in
//I use the frames to determine if the view is on-screen
if CGRectContainsRect(self.view.frame, self.ratingView.frame) {
//in frame ~ animate away
//I play a sound to give the animation some life
self.centerYInflection.constant = aPointAboveScene
self.centerYInflection.priority = UILayoutPriority(950)
} else {
//I play a different sound just to keep the user engaged
//out of frame ~ animate into scene
self.centerYInflection.constant = 0
self.centerYInflection.priority = UILayoutPriority(950)
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}) { (success) -> Void in
//do something else
}
}
}
많은 잘못된 차례
이 노트는 실제로 내가 작성한 팁입니다. 나는 개인적으로 고통스럽게 모든 것을하지 않았다. 이 안내서가 다른 사람들을 아끼지 않기를 바랍니다.
zPositioning을 조심하십시오. 아무 일도 일어나지 않는 경우 다른 뷰를 숨기거나 뷰 디버거를 사용하여 애니메이션 뷰를 찾아야합니다. 스토리 보드의 XML에서 사용자 정의 런타임 속성이 손실되어 애니메이션 뷰가 작동하는 경우를 발견했습니다.
설명서 (신규 및 이전), 빠른 도움말 및 헤더를 읽으려면 항상 1 분 정도 걸립니다. Apple은 AutoLayout 제약 조건을보다 잘 관리하기 위해 많은 변경을 계속하고 있습니다 (스택 뷰 참조). 또는 적어도 AutoLayout Cookbook 입니다. 때때로 가장 좋은 솔루션은 이전 문서 / 비디오에 있습니다.
애니메이션의 값을 가지고 놀면서 다른 animateWithDuration 변형 사용을 고려하십시오.
특정 레이아웃 값을 다른 상수에 대한 변경 사항을 결정하기위한 기준으로 하드 코딩하지 말고 대신 뷰의 위치를 결정할 수있는 값을 사용하십시오. CGRectContainsRect
하나의 예입니다
- 필요한 경우 제약 조건 정의에 참여하는 뷰와 관련된 레이아웃 여백을 사용하는 것을 망설이지 마십시오
let viewMargins = self.webview.layoutMarginsGuide
.
- 스토리 보드에 제약 조건이있는 모든 뷰에는 self.viewName.constraints 속성에 제약 조건이 첨부되어 있습니다.
- 제한 조건의 우선 순위를 1000 미만으로 변경하십시오. 스토리 보드에서 내 값을 250 (낮음) 또는 750 (높음)으로 설정했습니다. (코드에서 1000 우선 순위를 변경하려고하면 1000이 필요하기 때문에 앱이 중단됩니다)
- activateConstraints 및 deactivateConstraints를 즉시 사용하려고 시도하지 마십시오 (그 자리가 있지만 배우는 경우 또는 스토리 보드를 사용하는 경우 아마도 너무 많은 것을 의미합니다 ~ 아래에 표시된 것처럼 장소가 있음)
- 실제로 코드에 새 제약 조건을 추가하지 않는 한 addConstraints / removeConstraints를 사용하지 마십시오. 대부분의 경우 스토리 보드의 뷰를 원하는 제약 조건 (보기를 화면 외부에 배치)으로 배치 한 다음 코드에서 뷰 스토리에서 이전에 생성 된 제약 조건에 애니메이션을 적용하여 뷰를 이동시키는 것으로 나타났습니다.
- 새로운 NSAnchorLayout 클래스와 하위 클래스로 제약 조건을 구축하는 데 많은 시간을 낭비했습니다. 이것들은 잘 작동하지만 필요한 모든 제약 조건이 스토리 보드에 이미 존재한다는 것을 깨닫는 데 시간이 걸렸습니다. 코드에서 제약 조건을 작성하는 경우이 방법을 사용하여 제약 조건을 집계하십시오.
스토리 보드를 사용할 때 피해야 할 빠른 솔루션 샘플
private var _nc:[NSLayoutConstraint] = []
lazy var newConstraints:[NSLayoutConstraint] = {
if !(self._nc.isEmpty) {
return self._nc
}
let viewMargins = self.webview.layoutMarginsGuide
let minimumScreenWidth = min(UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height)
let centerY = self.ratingView.centerYAnchor.constraintEqualToAnchor(self.webview.centerYAnchor)
centerY.constant = -1000.0
centerY.priority = (950)
let centerX = self.ratingView.centerXAnchor.constraintEqualToAnchor(self.webview.centerXAnchor)
centerX.priority = (950)
if let buttonConstraints = self.originalRatingViewConstraints?.filter({
($0.firstItem is UIButton || $0.secondItem is UIButton )
}) {
self._nc.appendContentsOf(buttonConstraints)
}
self._nc.append( centerY)
self._nc.append( centerX)
self._nc.append (self.ratingView.leadingAnchor.constraintEqualToAnchor(viewMargins.leadingAnchor, constant: 10.0))
self._nc.append (self.ratingView.trailingAnchor.constraintEqualToAnchor(viewMargins.trailingAnchor, constant: 10.0))
self._nc.append (self.ratingView.widthAnchor.constraintEqualToConstant((minimumScreenWidth - 20.0)))
self._nc.append (self.ratingView.heightAnchor.constraintEqualToConstant(200.0))
return self._nc
}()
이러한 팁 중 하나 또는 layoutIfNeeded를 추가 할 위치와 같은보다 간단한 팁 중 하나를 잊어 버린 경우 아무 일도 일어나지 않을 것입니다.이 경우 다음과 같은 반 구운 솔루션이있을 수 있습니다.
주의 사항-아래의 자동 레이아웃 섹션과 원본 안내서를 읽으십시오. 이러한 기술을 사용하여 동적 애니메이터를 보완하는 방법이 있습니다.
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.3, initialSpringVelocity: 1.0, options: [.CurveEaseOut], animations: { () -> Void in
//
if self.starTopInflectionPoint.constant < 0 {
//-3000
//offscreen
self.starTopInflectionPoint.constant = self.navigationController?.navigationBar.bounds.height ?? 0
self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)
} else {
self.starTopInflectionPoint.constant = -3000
self.changeConstraintPriority([self.starTopInflectionPoint], value: UILayoutPriority(950), forView: self.ratingView)
}
}) { (success) -> Void in
//do something else
}
}
자동 레이아웃 안내서의 스 니펫 (두 번째 스 니펫은 OS X 사용을위한 것입니다). BTW-이것은 더 이상 현재 안내서에 없습니다. 선호하는 기술은 계속 발전하고 있습니다.
자동 레이아웃으로 변경 사항 애니메이션
자동 레이아웃으로 변경 한 애니메이션 효과를 완전히 제어해야하는 경우 프로그래밍 방식으로 구속 조건을 변경해야합니다. 기본 개념은 iOS와 OS X 모두 동일하지만 약간의 차이가 있습니다.
iOS 앱에서 코드는 다음과 같습니다.
[containerView layoutIfNeeded]; // Ensures that all pending layout operations have been completed
[UIView animateWithDuration:1.0 animations:^{
// Make all constraint changes here
[containerView layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes
}];
OS X에서는 레이어 기반 애니메이션을 사용할 때 다음 코드를 사용하십시오.
[containterView layoutSubtreeIfNeeded];
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
[context setAllowsImplicitAnimation: YES];
// Make all constraint changes here
[containerView layoutSubtreeIfNeeded];
}];
레이어 기반 애니메이션을 사용하지 않는 경우 제약 조건의 애니메이터를 사용하여 상수에 애니메이션을 적용해야합니다.
[[constraint animator] setConstant:42];
시각적으로 더 잘 배우려면 Apple의 초기 비디오를 확인하십시오 .
집중 해주세요
종종 문서에는 더 큰 아이디어로 이어지는 작은 메모 나 코드 조각이 있습니다. 예를 들어 자동 레이아웃 제약 조건을 동적 애니메이터에 연결하는 것이 좋습니다.
행운을 빈다.