WIN*_*gey 12 cocoa core-animation nsscrollview
我想在简单的UI中在转换之间创建软动画:



移动的视图

当调用scrollToPoint: for move view指向该过渡没有动画时.我是Cocoa编程的新手(iOS是我的背景).我不知道如何正确使用.animator或NSAnimationContext.
我也读过核心动画指南,但没有找到解决方案.
源可以在Git Hub存储库上访问
请帮忙 !!!
mah*_*tin 23
scrollToPoint不可动画.只有动画属性,如NSAnimatablePropertyContainer中的边界和位置等动画属性.你不需要对CALayer做任何事情:删除wantsLayer和CALayer的东西.然后使用以下代码进行动画处理.
- (void)scrollToXPosition:(float)xCoord {
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:5.0];
NSClipView* clipView = [_scrollView contentView];
NSPoint newOrigin = [clipView bounds].origin;
newOrigin.x = xCoord;
[[clipView animator] setBoundsOrigin:newOrigin];
[_scrollView reflectScrolledClipView: [_scrollView contentView]]; // may not bee necessary
[NSAnimationContext endGrouping];
}
Run Code Online (Sandbox Code Playgroud)
建议的答案有一个明显的缺点:如果用户尝试在正在进行的动画期间滚动,则输入将导致抖动,因为动画将强制继续进行直到完成。如果您设置了非常长的动画持续时间,问题就会变得明显。这是我的用例,动画滚动视图以捕捉到部分标题(同时尝试向上滚动):
我提出以下子类:
public class AnimatingScrollView: NSScrollView {
// This will override and cancel any running scroll animations
override public func scroll(_ clipView: NSClipView, to point: NSPoint) {
CATransaction.begin()
CATransaction.setDisableActions(true)
contentView.setBoundsOrigin(point)
CATransaction.commit()
super.scroll(clipView, to: point)
}
public func scroll(toPoint: NSPoint, animationDuration: Double) {
NSAnimationContext.beginGrouping()
NSAnimationContext.current.duration = animationDuration
contentView.animator().setBoundsOrigin(toPoint)
reflectScrolledClipView(contentView)
NSAnimationContext.endGrouping()
}
}
Run Code Online (Sandbox Code Playgroud)
通过覆盖正常scroll(_ clipView: NSClipView, to point: NSPoint)(在用户滚动时调用)并在CATransactionwith 中手动执行滚动setDisableActions,我们取消了当前动画。但是,我们不调用reflectScrolledClipView,而是调用super.scroll(clipView, to: point),它将执行其他必要的内部过程,然后执行reflectScrolledClipView。
上面的类产生更好的结果:
这个答案的 Swift 4代码
func scroll(toPoint: NSPoint, animationDuration: Double) {
NSAnimationContext.beginGrouping()
NSAnimationContext.current.duration = animationDuration
let clipView = scrollView.contentView
clipView.animator().setBoundsOrigin(toPoint)
scrollView.reflectScrolledClipView(scrollView.contentView)
NSAnimationContext.endGrouping()
}
Run Code Online (Sandbox Code Playgroud)