Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone MFMessageComposeViewController:我可以用一个自定义动画来演示这个吗?_Iphone_Objective C_Ios - Fatal编程技术网

Iphone MFMessageComposeViewController:我可以用一个自定义动画来演示这个吗?

Iphone MFMessageComposeViewController:我可以用一个自定义动画来演示这个吗?,iphone,objective-c,ios,Iphone,Objective C,Ios,这是我想做的。不确定这是否可能,但如果有一个干净的代码,这是应用商店可以接受的答案,我非常乐意给它一个赏金 -使用自定义动画演示MFMessageComposeViewController。它是 模态视图控制器 -然后我想用一个 自定义动画,同时在新实例上设置动画 MFMessageComposecController的。同样,自定义动画 对于这个问题,让我们简单地说,第一个MFMessageComposeViewController应该从右侧滑入,然后当按下send按钮时,它应该滑入左侧,而新

这是我想做的。不确定这是否可能,但如果有一个干净的代码,这是应用商店可以接受的答案,我非常乐意给它一个赏金

-使用自定义动画演示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
    })
}