- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想在两个 View Controller 之间实现交互式转换。我希望它是模态或现在的过渡。
我知道我需要使用以下内容。
transitioningDelegate
animationController(forPresented:presenting:Source:)
interactionControllerForPresentation(Using:)
UIPercentDrivenInteractiveTransition
我无法弄清楚如何实现所有这些。我似乎在 swift 3 中找不到任何有用的东西或任何工作示例。现在我创建了一个简单的单 View 应用程序,它有两个 View Controller VC1(蓝色背景)和 VC2(黄色背景)来轻松测试任何可能的解决方案。
最佳答案
参见 WWDC 2013 视频 Custom Transitions Using View Controllers用于讨论过渡委托(delegate)、动画 Controller 和交互 Controller 。查看 WWDC 2014 视频 View Controller Advancements in iOS 8和 A Look Inside Presentation Controllers用于介绍演示 Controller (您也应该使用它)。
基本思想是创建一个转换委托(delegate)对象,该对象标识将用于自定义转换的动画 Controller 、交互 Controller 和演示 Controller :
class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
/// Interaction controller
///
/// If gesture triggers transition, it will set will manage its own
/// `UIPercentDrivenInteractiveTransition`, but it must set this
/// reference to that interaction controller here, so that this
/// knows whether it's interactive or not.
weak var interactionController: UIPercentDrivenInteractiveTransition?
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PullDownAnimationController(transitionType: .presenting)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PullDownAnimationController(transitionType: .dismissing)
}
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return PresentationController(presentedViewController: presented, presenting: presenting)
}
func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return interactionController
}
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return interactionController
}
}
然后您只需指定正在使用的自定义转换以及应使用的转换委托(delegate)。您可以在实例化目标 View Controller 时执行此操作,或者您可以将其指定为目标 View Controller 的 init
的一部分,例如:
class SecondViewController: UIViewController {
let customTransitionDelegate = TransitioningDelegate()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
modalPresentationStyle = .custom
transitioningDelegate = customTransitionDelegate
}
...
}
动画 Controller 指定动画的细节(如何制作动画、用于非交互式过渡的持续时间等):
class PullDownAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
enum TransitionType {
case presenting
case dismissing
}
let transitionType: TransitionType
init(transitionType: TransitionType) {
self.transitionType = transitionType
super.init()
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let inView = transitionContext.containerView
let toView = transitionContext.view(forKey: .to)!
let fromView = transitionContext.view(forKey: .from)!
var frame = inView.bounds
switch transitionType {
case .presenting:
frame.origin.y = -frame.size.height
toView.frame = frame
inView.addSubview(toView)
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
toView.frame = inView.bounds
}, completion: { finished in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
case .dismissing:
toView.frame = frame
inView.insertSubview(toView, belowSubview: fromView)
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
frame.origin.y = -frame.size.height
fromView.frame = frame
}, completion: { finished in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
}
上面的动画 Controller 处理呈现和解散,但如果感觉太复杂,理论上你可以将它分成两个类,一个用于呈现,另一个用于解散。但我不喜欢两个不同的类如此紧密地耦合在一起,所以我将承担 animateTransition
的轻微复杂性的代价,以确保它们都很好地封装在一个类中。
无论如何,我们想要的下一个对象是展示 Controller 。在这种情况下,表示 Controller 告诉我们从 View 层次结构中删除原始 View Controller 的 View 。 (在这种情况下,我们这样做是因为您要过渡到的场景恰好占据了整个屏幕,因此无需在 View 层次结构中保留旧 View 。)如果您要添加任何其他额外的镶边(例如添加调光/模糊 View 等),它们将属于呈现 Controller 。
无论如何,在这种情况下,呈现 Controller 非常简单:
class PresentationController: UIPresentationController {
override var shouldRemovePresentersView: Bool { return true }
}
最后,您可能想要一个手势识别器:
UIPercentDrivenInteractiveTransition
; UIPercentDrivenInteractiveTransition
;UIPercentDrivenInteractiveTransition
(以确保它不会挥之不去,因此它不会干扰您稍后可能想做的任何非交互式转换......这是一个微妙的小点容易被忽视)。所以“呈现” View Controller 可能有一个手势识别器,它可能会做类似的事情:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let panDown = UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
view.addGestureRecognizer(panDown)
}
var interactionController: UIPercentDrivenInteractiveTransition?
// pan down transitions to next view controller
func handleGesture(_ gesture: UIPanGestureRecognizer) {
let translate = gesture.translation(in: gesture.view)
let percent = translate.y / gesture.view!.bounds.size.height
if gesture.state == .began {
let controller = storyboard!.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
interactionController = UIPercentDrivenInteractiveTransition()
controller.customTransitionDelegate.interactionController = interactionController
show(controller, sender: self)
} else if gesture.state == .changed {
interactionController?.update(percent)
} else if gesture.state == .ended || gesture.state == .cancelled {
let velocity = gesture.velocity(in: gesture.view)
if (percent > 0.5 && velocity.y == 0) || velocity.y > 0 {
interactionController?.finish()
} else {
interactionController?.cancel()
}
interactionController = nil
}
}
}
您可能还想更改此设置,使其仅识别向下的手势(而不是任何旧的平底锅),但希望这能说明这个想法。
并且您可能希望“呈现的” View Controller 具有用于关闭场景的手势识别器:
class SecondViewController: UIViewController {
let customTransitionDelegate = TransitioningDelegate()
required init?(coder aDecoder: NSCoder) {
// as shown above
}
override func viewDidLoad() {
super.viewDidLoad()
let panUp = UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
view.addGestureRecognizer(panUp)
}
// pan up transitions back to the presenting view controller
var interactionController: UIPercentDrivenInteractiveTransition?
func handleGesture(_ gesture: UIPanGestureRecognizer) {
let translate = gesture.translation(in: gesture.view)
let percent = -translate.y / gesture.view!.bounds.size.height
if gesture.state == .began {
interactionController = UIPercentDrivenInteractiveTransition()
customTransitionDelegate.interactionController = interactionController
dismiss(animated: true)
} else if gesture.state == .changed {
interactionController?.update(percent)
} else if gesture.state == .ended {
let velocity = gesture.velocity(in: gesture.view)
if (percent > 0.5 && velocity.y == 0) || velocity.y < 0 {
interactionController?.finish()
} else {
interactionController?.cancel()
}
interactionController = nil
}
}
@IBAction func didTapButton(_ sender: UIButton) {
dismiss(animated: true)
}
}
参见 https://github.com/robertmryan/SwiftCustomTransitions用于演示上述代码。
看起来像:
但是,归根结底,自定义转场有点复杂,所以我再次向您推荐那些原始视频。在发布任何进一步的问题之前,请确保您仔细观察了它们。您的大部分问题可能会在这些视频中得到解答。
关于ios - 自定义交互过渡动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42192127/
在 python 交互中,有没有办法在每次输入命令后自动从 python 文件执行方法? 例如:如果我有一个打印文件信息的方法,但我不想不断调用该方法,我怎样才能让它在 python 交互中的每个命令
当你使用Edge等浏览器或系统软件播放媒体时,Windows控制中心就会出现相应的媒体信息以及控制播放的功能,如图。 SMTC (SystemMedia
我在主菜单上使用标准的剪切,复制,粘贴操作。它们具有快捷键Ctrl-X,Ctrl-C和Ctrl-V。 当我打开模态表单时FindFilesForm.ShowModal,然后所有快捷方式都可以从表单中使
这是我想要实现的目标:打开一个 shell(korn 或 bash,没关系),从那个 shell,我想打开一个 ssh 连接(ssh user@host)。在某些时候,可能会提示我输入密码,或者可能会
我正在测试在C / C++程序中嵌入Python,但是我缺乏理解。 测试程序很简单: 初始化解释器; 从启动Timer的文件中执行python脚本(每0.1秒增加一个变量); 等待5秒(C++); 从
我正在尝试用java创建Excel文件。现在,我正在使用 Apache POI 库创建文件并将其保存到本地驱动器。有没有办法启动 Excel 并填充数据而不将其保存到硬盘驱动器? 最佳答案 考虑 Do
我有一个黑盒函数,它接受大约 10 个整数输入。该函数返回一个 pandas 数据框,我想捕获输出窗口(通过使用 bbwidget.children)并显示在布局中的其他地方。到目前为止,交互/交互似
我正在体验新的 QQuickWidget。我如何在 QQuickWidget 和 C++ 之间进行交互? C++ QQuickWidget *view = new QQuickWidget(); vi
我正在尝试设置一个使用 TWAIN 的 C# 应用程序 example from code project 除了我需要将 Form 转换为 IMessageFilter 和调用 IMessageFil
我想在使用 redis 的 python 中编写应用程序。我用谷歌搜索,但找不到我的问题的任何结果。通常,我这样做: import redis rs = redis.Redis('localhost'
最近做一个小项目,网页中嵌入google maps,输入经纬度坐标可以定位地图位置并加注标记,点击标记获取远端摄像头数据并在视频窗口实现播放。在实际操作过程中,由于经纬度数据和视频登录的用户名密码数
我需要在这里澄清一些事情: 我有一个网站,每次在浏览器中重新加载网站时都会更新两个变量的值。这个页面显然是一个 HTML 页面,但变量是由 javascript 函数更新的。此页面在我的服务器上运行。
我注意到,auto忽略双条件。这是一个简化的示例: Parameter A B : Prop. Parameter A_iff_B : A B. Theorem foo1: A -> B. Proo
使用 interactive使用多个小部件相当简单,例如: interactive(foo, w1=widget1, w2=widget2, ...) 但是,我想使用 VBox 和 HBox 的组合以
我们提供类似于 imagemagick 的浏览器页面 JavaScript,可帮助人们将图像转换为不同大小和格式。但是,它需要网页交互。 是否可以让人们自动进行这种交互——无需将图像发送到我们的服务器
大家好,我正在尝试制作一个具有大量动画和效果的交互式 UI。 但我不知道是否: 核心图形可以支持用户交互(触摸、拖动等) 核心图形支持对象旋转 核心图形可以以任何方式与 UIKit 和核心动画交互 谢
这是获取维基百科上一篇关于高盛的文章的介绍的链接。 http://en.wikipedia.org/w/api.php?action=query&prop=extracts&titles=Goldma
我正在尝试编写一个 AppleScript 来查询 iCal 并在任何日历中查找给定日期的所有事件。 我首先编写了一个简单的脚本,它对给定日历中的每个事件执行一些简单的操作: tell applica
我在我的 hudson 服务器上使用 jira 插件。将代码提交到 svn 时,我的提交注释包含在我的 jira 问题中,但有什么办法可以将注释归因于执行提交的实际人员,而不是让一个全局 jira 用
我正在播放一段视频来装饰我的用户界面。我隐藏了 AV 播放器控件,但用户仍然可以控制视频。例如,他们可以使用滑动手势快进或快退。 这让我特别惊讶,因为 AVPlayerView 上面有一个覆盖 Vie
我是一名优秀的程序员,十分优秀!