Iphone MFMessageComposeViewController:我可以用一个自定义动画来演示这个吗?
这是我想做的。不确定这是否可能,但如果有一个干净的代码,这是应用商店可以接受的答案,我非常乐意给它一个赏金 -使用自定义动画演示MFMessageComposeViewController。它是 模态视图控制器 -然后我想用一个 自定义动画,同时在新实例上设置动画 MFMessageComposecController的。同样,自定义动画 对于这个问题,让我们简单地说,第一个MFMessageComposeViewController应该从右侧滑入,然后当按下send按钮时,它应该滑入左侧,而新实例从右侧滑入,这与导航控制器的默认推送动画非常相似Iphone MFMessageComposeViewController:我可以用一个自定义动画来演示这个吗?,iphone,objective-c,ios,Iphone,Objective C,Ios,这是我想做的。不确定这是否可能,但如果有一个干净的代码,这是应用商店可以接受的答案,我非常乐意给它一个赏金 -使用自定义动画演示MFMessageComposeViewController。它是 模态视图控制器 -然后我想用一个 自定义动画,同时在新实例上设置动画 MFMessageComposecController的。同样,自定义动画 对于这个问题,让我们简单地说,第一个MFMessageComposeViewController应该从右侧滑入,然后当按下send按钮时,它应该滑入左侧,而新
如果这是不可能的,那么解释一下为什么没有办法做到这一点就很好了:这是可能的,&u可以将它用作普通的ViewController,在我使用的一个应用程序中,modalTransistion样式为溶解,它在商店中 还有一件事,开发人员决定如何呈现邮件生成器,以及如何取消它 由我们而非iOS/apple处理的演示和解聘 MFMailComposeViewController作为一个模态视图与苹果的HIG一致。将其推到导航堆栈上是不正确的。使用:
-presentModalViewController:animated:
-presentViewController:animated:completion` (if supporting iOS 5).
如果你真的想表达不同的意思,可以使用modalTransitionStyle
并使用modalPresentationStyle
FMailComposeViewController是一个UINavigationController,不支持推送导航控制器。我认为这是不可能的,因为它是苹果公司提供的自定义组件。好吧,我不得不说,这件事引起了我的好奇心。现在,就你的问题而言,看起来你对此并没有什么可以做的 我采取了两种不同的方法,试图以一种非默认的风格呈现作曲家,但收效甚微。我能得到的最接近的结果是:
UIViewAnimationTransition trans = UIViewAnimationTransitionCurlDown;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:trans forView:[self view] cache:YES];
[self presentViewController:controller animated:NO completion:nil];
[UIView commitAnimations];
使用这种呈现方法,动画效果得以实现,但它实际上似乎并不适用于作曲家。翻页只是一页空白。我还尝试过手动添加过渡效果,如alpha,并直接将变换调整添加到Composer视图属性中,但这也没什么效果
所有的事情都归结为:
重要提示:消息组合接口本身不可用
可自定义,且不能由应用程序修改。在里面
此外,在显示界面后,应用程序无法运行
对SMS内容进行进一步更改。用户可以编辑
使用接口的内容,但忽略编程更改。
因此,如果需要,您必须在
呈现界面
编辑:事实上,我想我可能已经找到了一种方法,使这项工作。你似乎仍然不太可能使用任何类型的自定义转换,我也不能保证苹果会批准这一点,但这应该允许你展示composer导航控制器推送风格
而不是使用:
[self presentViewController:controller animated:YES completion:nil];
使用:
这实际上允许您推送到作曲家。默认情况下,此行为不受支持,并会导致一个错误,表明您无法将导航控制器推送到编写器
接下来,在-void-messagecomposeviewcontroller:MFMessageComposeViewController*控制器中,只需使用以下命令即可完成结果:messagecomposesultresult:
[self.navigationController popToRootViewControllerAnimated:YES];
而不是:
[self dismissViewControllerAnimated:YES completion:nil];
编辑2:对不起,我好像忘了你问题的一个要点。如果要从一个composer实例推送到另一个实例,可以为每个composer创建IVAR,在viewDidLoad中设置它们,然后在didFinishWithResult中处理将它们串联在一起的菊花链。然而,这只能部分解决问题。就目前情况而言,我在下面发布的代码在未来会很好地工作,但在备份时不会那么好。我相信这样做的原因是,作曲家希望在成功发送消息后关闭并使其为零,结果是取消,但会自动禁用
总的来说,如果你把它弄得一团糟,你应该仍然能够让它工作
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
switch (result) {
case MessageComposeResultCancelled:
if (controller == firstComposer) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
else if (controller == secondComposer) {
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
}
break;
case MessageComposeResultFailed:
NSLog(@"Failed");
break;
case MessageComposeResultSent:
if (controller == firstComposer) {
[self.navigationController pushViewController:[[secondComposer viewControllers] lastObject] animated:YES];
[secondComposer becomeFirstResponder];
}
break;
default:
break;
}
}
不,但是你可以做一个小把戏,看起来就像你希望的那样
- (IBAction)showComposer:(id)sender {
// 1) get the prepared image of empty composer
UIImageView *composerView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"preparedImage"]];
composerView.frame = rightOffscreenFrame;
[self.view addSubview:composerView];
// 2) do any transitions, and transforms with it
[UIView animateWithDuration:0.33 animations:^{
composerView.frame = self.view.bounds;
} completion:^(BOOL finished) {
if (finished) {
// 3) when it is time, just add a real composer without animation
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[self presentViewController:composer animated:NO completion:^{
[composerView removeFromSuperview];
}];
}
}];
}
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
// 4) when user will send message, render the new image with content of composer
UIGraphicsBeginImageContext(self.view.bounds.size);
[controller.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *composerView = [[UIImageView alloc] initWithImage:newImage];
composerView.frame = self.view.bounds;
// 5) show it below composer, close composer without animation.
[self.view addSubview:composerView];
[self dismissViewControllerAnimated:NO completion:^{
// 6) do any transitions, and transforms with image.
[UIView animateWithDuration:0.33 animations:^{
composerView.frame = leftOffscreenFrame
} completion:^(BOOL finished) {
if (finished) {
[composerView removeFromSuperview];
}
}];
}];
}
最近面临着这个任务。我需要实现一个类似于推送和弹出导航堆栈的转换。 以下是我的实现:
extension MFMailComposeViewController: UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning {
convenience init(_ customTransition: Bool) {
self.init()
if customTransition { self.transitioningDelegate = self }
}
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
else { return }
var start = transitionContext.initialFrame(for:fromVC)
var end = transitionContext.finalFrame(for:toVC)
if toVC is MFMailComposeViewController {
start.origin.x -= containerView.bounds.width
end.origin.x = 0.0
let v1 = transitionContext.view(forKey:.from)!
let v2 = transitionContext.view(forKey:.to)!
v2.frame.origin.x = containerView.bounds.width
containerView.addSubview(v2)
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
v1.frame.origin.x -= containerView.bounds.width/3
v2.frame = end
}) { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
} else {
start.origin.x = containerView.bounds.width
end.origin.x = 0.0
let v1 = transitionContext.view(forKey:.from)!
let v2 = transitionContext.view(forKey:.to)!
v2.frame.origin.x = -containerView.bounds.width/3
containerView.insertSubview(v2, belowSubview: v1)
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
v2.frame = end
v1.frame = start
}) { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
}
在上面,我们已经实现了MFMailComposeViewController的扩展,其中的键是一个带有一行的初始化:self.transitioningDelegate=self
接下来,我们编写控制器的伪代码,其中将初始化MFMailComposeViewController,并提供我们需要的转换:
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
@IBAction func testAction(_ sender: UIButton) {
let mailComposerVC = MFMailComposeViewController(true)
mailComposerVC.mailComposeDelegate = self
//then we configure the controller for our needs
self.present(mailComposerVC, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: {
//configure result
})
}
}
瞧,一切都像个符咒 据我所知,你说的话没有一句是正确的
后悔对不起,伙计!您不能将其用作普通视图控制器,它无法加载,我已经尝试过了。苹果公司的文档告诉你如何展示它。我不确定当我想要自定义动画时,设置模式转换样式将如何帮助我。我们不决定如何展示它,苹果公司已经限制了我们一小部分的设置模式转换动画,而且它是一个消息生成器,而不是邮件生成器。在模式视图方面,呈现和驳回都由苹果公司处理。至于是否有可能,这还有待观察!谢谢,但这并不能回答我的问题。我知道上面的所有内容,但是我想在模态视图转换中添加自定义动画,这些动画不是上面列出的预定义样式之一。谢谢,我必须做一些奇怪的事情,以确保屏幕截图/图像等中包含键盘,但看起来这种方法最容易使用。有点作弊,但至少我能得到我想要的效果!是的,你可以渲染整个窗口或者在制作动画之前隐藏键盘谢谢你的回答!你已经考虑了很多了。我下载了演示项目,它就快到了,但它似乎有点问题,就像你说的-有很多事情我必须找到解决办法,使工作恰到好处。我选择了一个不那么麻烦的解决方案,这更像是一个诡计/欺骗,而不是解决方案,但是谢谢!尽管如此,还是要投票表决:
extension MFMailComposeViewController: UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning {
convenience init(_ customTransition: Bool) {
self.init()
if customTransition { self.transitioningDelegate = self }
}
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
else { return }
var start = transitionContext.initialFrame(for:fromVC)
var end = transitionContext.finalFrame(for:toVC)
if toVC is MFMailComposeViewController {
start.origin.x -= containerView.bounds.width
end.origin.x = 0.0
let v1 = transitionContext.view(forKey:.from)!
let v2 = transitionContext.view(forKey:.to)!
v2.frame.origin.x = containerView.bounds.width
containerView.addSubview(v2)
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
v1.frame.origin.x -= containerView.bounds.width/3
v2.frame = end
}) { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
} else {
start.origin.x = containerView.bounds.width
end.origin.x = 0.0
let v1 = transitionContext.view(forKey:.from)!
let v2 = transitionContext.view(forKey:.to)!
v2.frame.origin.x = -containerView.bounds.width/3
containerView.insertSubview(v2, belowSubview: v1)
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
v2.frame = end
v1.frame = start
}) { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
@IBAction func testAction(_ sender: UIButton) {
let mailComposerVC = MFMailComposeViewController(true)
mailComposerVC.mailComposeDelegate = self
//then we configure the controller for our needs
self.present(mailComposerVC, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: {
//configure result
})
}