我想制作一个自定义演示文稿(推送或模态)以在"内部显示"内部显示视图控制器。我四处搜索,但大多数方法是从不同的方向(从右边,从上面)呈现视图控制器而不是默认方向,但我需要的是包括在viewController中缩放缩放的内容,如果有任何解决方案的话该..
答案 0 :(得分:0)
您可以实施自己的自定义UIViewControllerAnimatedTransitioning
。这是C#中自定义圆圈渐变(内向外)过渡的示例(不应该很难在swift中重现):
/// <summary>
/// Circle fade transition animator.
/// </summary>
public class CircleFadeTransitionAnimator : UIViewControllerAnimatedTransitioning
{
public bool IsPresentation = true;
nfloat screenHeight = UIScreen.MainScreen.Bounds.Height;
nfloat screenWidth = UIScreen.MainScreen.Bounds.Width;
public override void AnimateTransition(IUIViewControllerContextTransitioning transitionContext)
{
//The current view controller
var fromVC = transitionContext.GetViewControllerForKey(UITransitionContext.FromViewControllerKey);
var fromView = fromVC.View;
//The view controller we wish to present to the user
var toVC = transitionContext.GetViewControllerForKey(UITransitionContext.ToViewControllerKey);
var toView = toVC.View;
// Set up some variables for the animation.
var containerView = transitionContext.ContainerView;
// Always add the "to" view to the container.
// And it doesn't hurt to set its start frame.
containerView.AddSubview(toView);
// Creates two circular UIBezierPath instances; one is the size of the button, and the second has a radius
// large enough to cover the entire screen. The final animation will be between these two bezier paths.
CGSize size;
if (fromVC is LogInViewController)
size = new CGSize(5, 5);
else
size = new CGSize(screenWidth * 0.65, screenWidth * 0.65);
var startingRect = new CGRect(screenWidth / 2 - size.Width/2, screenHeight / 2 - size.Height/2, size.Width, size.Height);
var circleMaskPathInitial = UIBezierPath.FromOval(startingRect);
var extremePoint = new CGPoint(screenWidth / 2, screenHeight / 2 - toView.Bounds.Height);
var radius = (nfloat) Math.Sqrt((extremePoint.X * extremePoint.X) + (extremePoint.Y * extremePoint.Y));
var circleMaskPathFinal = UIBezierPath.FromOval(startingRect.Inset(-radius, -radius));
// Creates a new CAShapeLayer to represent the circle mask. Assign its path value with the final circular path
// after the animation to avoid the layer snapping back after the animation completes.
var maskLayer = new CAShapeLayer();
maskLayer.Path = circleMaskPathFinal.CGPath;
toVC.View.Layer.Mask = maskLayer;
// Creates a CABasicAnimation on the path key path that goes from circleMaskPathInitial to circleMaskPathFinal.
var maskLayerAnimation = CABasicAnimation.FromKeyPath("path");
maskLayerAnimation.SetFrom(circleMaskPathInitial.CGPath);
maskLayerAnimation.SetTo(circleMaskPathFinal.CGPath);
maskLayerAnimation.Duration = TransitionDuration(transitionContext);
maskLayerAnimation.Delegate = new CircleAnimationDelegate(transitionContext);
maskLayer.AddAnimation(maskLayerAnimation, "path");
}
/// <summary>
/// How long will the transition last?
/// </summary>
/// <returns>The duration.</returns>
/// <param name="transitionContext">Transition context.</param>
public override double TransitionDuration(IUIViewControllerContextTransitioning transitionContext)
{
return 0.3;
}
}
您还需要实现自己的CAAnimationDelegate
,如下所示:
/// <summary>
/// Circle animation delegate.
/// </summary>
class CircleAnimationDelegate : CAAnimationDelegate
{
IUIViewControllerContextTransitioning transitionContext;
//UIView toView;
/// <summary>
/// Initializes a new instance of the <see cref="T:Plimes.CircleAnimationDelegate"/> class.
/// </summary>
/// <param name="transitionContext">Transition context.</param>
public CircleAnimationDelegate(IUIViewControllerContextTransitioning transitionContext)
{
this.transitionContext = transitionContext;
//this.toView = toView;
}
/// <summary>
/// On Animations stopped.
/// </summary>
/// <param name="anim">Animation.</param>
/// <param name="finished">If set to <c>true</c> finished.</param>
public override void AnimationStopped(CAAnimation anim, bool finished)
{
transitionContext.CompleteTransition(!transitionContext.TransitionWasCancelled);
transitionContext.GetViewControllerForKey(UITransitionContext.ToViewControllerKey).View.Layer.Mask = null;
transitionContext.GetViewControllerForKey(UITransitionContext.FromViewControllerKey).View.Layer.Mask = null;
//toView.RemoveFromSuperview();
}
}
然后你可以继承你的UINavigationController
并覆盖它的GetAnimationControllerForOperation()
委托方法,如下所示:
/// <summary>
/// Navigation controller subclass for assigning custom delegate.
/// </summary>
public partial class NavigationController : UINavigationController
{
/// <summary>
/// Initializes a new instance of the <see cref="T:Plimes.NavigationController"/> class.
/// </summary>
/// <param name="handle">Handle.</param>
public NavigationController (IntPtr handle) : base (handle)
{
Delegate = new NavigationControllerDelegate();
}
}
/// <summary>
/// Navigation controller delegate for custom transition animations.
/// </summary>
public class NavigationControllerDelegate : UINavigationControllerDelegate
{
/// <summary>
/// Gets the animation controller for operation.
/// </summary>
/// <returns>The animation controller for operation.</returns>
/// <param name="navigationController">Navigation controller.</param>
/// <param name="operation">Operation.</param>
/// <param name="fromViewController">From view controller.</param>
/// <param name="toViewController">To view controller.</param>
public override IUIViewControllerAnimatedTransitioning GetAnimationControllerForOperation(UINavigationController navigationController, UINavigationControllerOperation operation, UIViewController fromViewController, UIViewController toViewController)
{
// If left-right transition is needed
if (operation == UINavigationControllerOperation.Push)
{
var animator = new CircleFadeTransitionAnimator();
animator.IsPresentation = true;
return animator;
}
}
}
希望这会有所帮助!