2017-04-30 3 views

Antwort

1

Sie müssen auf benutzerdefinierte Renderer zurückgreifen und so etwas in C# implementieren: https://github.com/katleta3000/RotateController (dieses Beispiel ist in Swift für iOS, möglicherweise etwas ähnliches existiert auch für Android).

Es ist in reinen Xamarin Forms meines Wissens nicht möglich.

Dies ist, wie das bereitgestellte Beispiel wie in C# aussehen würde (Anmerkung: Ich habe das Ergebnis nicht getestet, damit die beiden Todo im folgenden Code):

// Example Swift code licensed by MIT license. Converted to C#. 
// Original author: katleta3000 

using System; 
using CoreAnimation; 
using UIKit; 

namespace MyProject.iOS 
{ 
    public enum RotationDirection : int 
    { 
     Right = 0, 
     Left 
    } 

    public enum RotationType : int 
    { 
     Push = 0, 
     Pop 
    } 

    class FCBlackBackgroundView : UIView 
    { 

    } 

    class FCRotateLayer : CALayer 
    { 
    } 

    public class RotatingController : UINavigationController 
    { 
     public void PushViewController(UIViewController controller, RotationDirection rotateDirection) { 
      Perform3DRotate(RotationType.Push, rotateDirection, controller); 
     } 

     public void PopViewController(RotationDirection rotateDirection) { 
      Perform3DRotate(RotationType.Pop, rotateDirection, null); 
     } 

     // MARK: - private 

     private void Perform3DRotate(RotationType type, RotationDirection rotateDirection, UIViewController controller) { 
      var layer = RotationLayer(); 

      var cube = CubeTransform(rotateDirection, layer: layer); 

      if (type == RotationType.Push) { 
       this.PushViewController(controller, animated: false); 
      } else if (type == RotationType.Pop) { 
       this.PopViewController(animated: false); 
      } 
      layer.AddSublayer(LayerFromView(this.View, transform: cube)); 

      this.View.AddSubview(BackgroundView(UIColor.White)); 

      this.View.Layer.AddSublayer(layer); 

      layer.AddAnimation(RotationAnimation(rotateDirection), "rotate"); 

     } 

     private CATransform3D CubeTransform(RotationDirection rotateDirection, CALayer layer) 
     { 
      var cube = CATransform3D.MakeTranslation(0, 0, 0); 

      layer.AddSublayer(LayerFromView(this.View, transform: cube)); 

      cube.Rotate(Radians(90), 0, 1, 0); 

      cube.Translate(CubeSize(), 0, 0); 

      if (rotateDirection == RotationDirection.Left) { 
       cube.Rotate(Radians(90), 0, 1, 0); 

       cube.Translate(CubeSize(), 0, 0); 

       cube.Rotate(Radians(90), 0, 1, 0); 

       cube.Translate(CubeSize(), 0, 0); 

      } 
      return cube; 

     } 

     private FCRotateLayer RotationLayer() 
     { 
      FCRotateLayer layer = new FCRotateLayer(); 

      layer.Frame = this.View.Frame; 

      layer.AnchorPoint = new CoreGraphics.CGPoint(0.5, 0.5); 

      CATransform3D transform = CATransform3D.Identity; 

      transform.m34 = 1.0f/-750; 

      layer.SublayerTransform = transform; 

      return layer; 

     } 

     private CAAnimation RotationAnimation(RotationDirection direction) 
     { 
      CATransaction.Flush(); 

      var animationGroup = new CAAnimationGroup(); 

      animationGroup.Duration = 0.4; 

      CABasicAnimation rotation = null; 
      CABasicAnimation translationX = null; 

      if (direction == RotationDirection.Right) { 
       rotation = CABasicAnimation.FromKeyPath("sublayerTransform.rotation.y"); 

       rotation.To = FromObject(Radians(-90)); 

       translationX = CABasicAnimation.FromKeyPath("sublayerTransform.translation.x"); 

       translationX.To = FromObject(-TranslationForAnimation()); 

      } 
      else if (direction == RotationDirection.Left) { 
       rotation = CABasicAnimation.FromKeyPath("sublayerTransform.rotation.y"); 

       rotation.To = FromObject(Radians(90)); 

       translationX = CABasicAnimation.FromKeyPath("sublayerTransform.translation.x"); 

       translationX.To = FromObject(TranslationForAnimation()); 

      } 

      var translationZ = CABasicAnimation.FromKeyPath("sublayerTransform.translation.z"); 

      translationZ.To = FromObject(-TranslationForAnimation()); 

      animationGroup.Animations = new CAAnimation[] { rotation, translationX, translationZ }; 

      animationGroup.FillMode = CoreAnimation.CAFillMode.Forwards; //TODO: maybe convert nsstring to string 

      animationGroup.RemovedOnCompletion = false; 

      //TODO: unsubscribe necessary? 
      animationGroup.AnimationStopped += (sender, e) => 
      { 
       var layers = this.View.Layer.Sublayers; 
       if (layers != null) { 
        foreach (var layer in layers) { 
         if (layer is FCRotateLayer) { 
          layer.RemoveFromSuperLayer(); 
         } 
        } 
       } 
       foreach(var view in this.View.Subviews) { 
        if (view is FCBlackBackgroundView) { 
         view.RemoveFromSuperview(); 
        } 
       } 
      }; 

      animationGroup.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut); 

      return animationGroup; 
     } 

     private CALayer LayerFromView(UIView view) { 
      var rect = CoreGraphics.CGRect.FromLTRB(0, 0, this.View.Bounds.Size.Width, this.View.Frame.Size.Height); 

      CALayer imageLayer = new CALayer(); 

      imageLayer.AnchorPoint = new CoreGraphics.CGPoint(1, 1); 

      imageLayer.Frame = rect; 
      UIGraphics.BeginImageContextWithOptions(view.Frame.Size, false, UIScreen.MainScreen.Scale); 
      var context = UIGraphics.GetCurrentContext(); 
      if (context != null) { 
       view.Layer.RenderInContext(context); 
      } 
      UIImage image = UIGraphics.GetImageFromCurrentImageContext(); 

      UIGraphics.EndImageContext(); 

      imageLayer.Contents = image.CGImage; 
      return imageLayer; 
     } 

     private CALayer LayerFromView(UIView view, CATransform3D transform) { 
      var layer = LayerFromView(view); 

      layer.Transform = transform; 
      return layer; 
     } 

     private FCBlackBackgroundView BackgroundView(UIColor color) 
     { 
      var view = new FCBlackBackgroundView 
      { 
       Frame = this.View.Frame 
      }; 

      view.BackgroundColor = color; 
      return view; 
     } 

     private float Radians(float degrees) { 
      return degrees * (float)Math.PI/180; 
     } 

     private nfloat TranslationForAnimation() { 
      return CubeSize()/2; 
     } 

     private nfloat CubeSize() { 
      return UIScreen.MainScreen.Bounds.Width; 
     } 
    } 
} 
0

Hier ist eine C# Version des verknüpften schneller Controller. Einige Dinge, die ich nicht von Swift übersetzen konnte. Wäre toll, wenn jemand die Zahlenkonvertierungen überprüfen/durchdenken kann.

using CoreAnimation; 
using CoreGraphics; 
using UIKit; 


namespace hackettyHack 
{ 
    public enum RotationDirection //int 
    { 
     // case Right = 0, Left 
     Right, 
     Left 
    } 
    public enum RotationType //int 
    { 
     // case Push = 0, Pop } 
     Push, 
     Pop 
    } 


    class FCBlackBackgroundView : UIView 
    { 

    } 

    class FCRotateLayer : CALayer 
    { 
    } 

    public class RotatingController : UINavigationController 
    { 
     public void PushViewController(UIViewController controller, RotationDirection rotateDirection) 
     { 
      Perform3DRotate(RotationType.Push, rotateDirection, controller); 
     } 
     public void PopViewController(UIViewController controller, RotationDirection rotateDirection) 
     { 
      Perform3DRotate(RotationType.Pop, rotateDirection, controller); 
     } 

     void Perform3DRotate(RotationType rotationType, RotationDirection rotateDirection, UIViewController v) 
     { 
      var layer = RotationLayer(); 

      var cube = CubeTransform(rotateDirection, layer); 

      switch (rotationType) 
      { 
       case RotationType.Pop: 
        this.PopViewController(animated: false); 
        break; 
       case RotationType.Push: 
        this.PushViewController(this, animated: false); //todo: make sure the SWIFT line below for controller! means THIS 
                    // self.pushViewController(controller!, animated: false) 
        break; 
       default: 
        break; 
      } 

      layer.AddSublayer(LayerFromView(this.View, cube)); 

      this.View.AddSubview(BackgroundView(UIColor.White)); 

      this.View.Layer.AddSublayer(layer); 

      layer.AddAnimation(RotationAnimation(rotateDirection), forkey: "rotate");//FIXME parameter 
     } 

     CATransform3D CubeTransform(RotationDirection rotateDirection, CALayer layer) 
     { 
      var cube = CATransform3D.MakeTranslation(0, 0, 0);//FIXME and all below 

      layer.AddSublayer(LayerFromView(this.View, transform: cube); 

      cube = CATransform3D.Rotate(cube, CGFloat(radians(90)), 0, 1, 0); 

      cube = CATransform3D.Translate(cube,CubeSize(), 0, 0); 
      if (rotateDirection == RotationDirection.Left) 
      { 
       cube = CATransform3D.Rotate(cube, CGFloat(radians(90)), 0, 1, 0); 

       cube = CATransform3D.Translate(cube, CubeSize(), 0, 0); 

       cube = CATransform3D.Rotate(cube, CGFloat(radians(90)), 0, 1, 0); 

       cube = CATransform3D.Translate(cube, CubeSize(), 0, 0); 

      } 
      return cube; 
     } 

     FCRotateLayer RotationLayer() 
     { 
      var layer = new FCRotateLayer(); 

      layer.Frame = this.View.Frame; 

      layer.AnchorPoint = new CoreGraphics.CGPoint(x: 0.5, y: 0.5); 

      CATransform3D transform = CATransform3D.Identity; 

      transform.m34 = 1/-750; 

      layer.SublayerTransform = transform; 

      return layer; 
     } 

     CAAnimation RotationAnimation(RotationDirection direction) 
     { 
      CATransaction.Flush(); 

      var animationGroup = new CAAnimationGroup(); 

      animationGroup.Duration = 0.4; 

      var rotation = new CABasicAnimation(); 
      var translationX = new CABasicAnimation(); 

      if (direction == RotationDirection.Right) 
      { 
       rotation = new CABasicAnimation() { KeyPath = "sublayerTransform.rotation.y" }; 

       //rotation.To = NSNumber(float: radians(-90))//FIXME 

       translationX = new CABasicAnimation() { KeyPath = "sublayerTransform.rotation.x" }; 

        translationX.To = NSNumber(float: Float(TranslationForAnimation()));//FIXME 
      } 
      else if (direction == RotationDirection.Left) 
      { 
       rotation = new CABasicAnimation() { KeyPath = "sublayerTransform.rotation.y" }; 

       //rotation.To = NSNumber(float: radians(90))//FIXME 

       translationX = new CABasicAnimation() { KeyPath = "sublayerTransform.rotation.x" }; 

       translationX.To = NSNumber(float: Float(TranslationForAnimation()));//FIXME 
      } 
      var translationZ = new CABasicAnimation() { KeyPath = "sublayerTransform.translation.z" }; 

      translationZ.To = NSNumber(float: Float(TranslationForAnimation()));//FIXME 

      animationGroup.Animations = new CAAnimation[3] { rotation, translationX, translationZ }; 

      animationGroup.FillMode = kCAFillModeForwards; /// //FIXME TBD what is the constant? where is it? 

      animationGroup.RemovedOnCompletion = false; 

      animationGroup.Delegate = this; // or should this be = to aiimationGroup? 

      animationGroup.TimingFunction = CAMediaTimingFunction.FromName("kCAMediaTimingFunctionEaseInEaseOut"); 

      return animationGroup; 
     } 

     CALayer LayerFromView(UIView view) 
     { 
      var rect = new CGRect(0, 0, this.View.Bounds.Size.Width, this.View.Bounds.Size.Height); 

      var imageLayer = new CALayer(); 

      imageLayer.AnchorPoint = new CGPoint(1, 1); 

      imageLayer.Frame = rect; 

      UIGraphics.BeginImageContextWithOptions(view.Frame.Size, false, UIScreen.MainScreen.Scale); 

      // No idea how to convert "if..let..??" from swift. 
      // 
      //if let context = UIGraphicsGetCurrentContext() {//FIXME 
      //view.layer.renderInContext(context) 
      //} 
      UIImage image = new UIImage(= UIGraphics.GetImageFromCurrentImageContext();//FIXME 

      UIGraphics.EndImageContext(); 

      imageLayer.Contents = image.CGImage; 


      return imageLayer; 
     } 

     CALayer LayerFromView(UIView view, CATransform3D transform) 
     { 
      var layer = LayerFromView(view); 
      layer.Transform = transform; 
      return layer; 
     } 

     System.nfloat Radians(System.nfloat degrees) 
     { 
      return degrees * float(M_PI)/180; //FIXME 
     } 

     System.nfloat TranslationForAnimation() 
     { 
      return CubeSize()/2; 
     } 

     System.nfloat CubeSize() 
     { 
      return UIScreen.MainScreen.Bounds.Width; 
     } 

     FCBlackBackgroundView BackgroundView(UIColor color) 
     { 
      var view = new FCBlackBackgroundView() { Frame = this.View.Frame }; 
      view.BackgroundColor = color; 

      return view; 
     } 

    } 
} 


/* 

public override func animationDidStop(anim: CAAnimation, finished flag: Bool)//FIXME no suitable overrride found 
{ 
if let layers = self.view.layer.sublayers { 
for layer in layers { 
if layer.isKindOfClass(FCRotateLayer.classForCoder()) { 
layer.removeFromSuperlayer() 

} 
} 
} 
for view in self.view.subviews { 
if view.isKindOfClass(FCBlackBackgroundView.classForCoder()) { 
view.removeFromSuperview() 

} 
} 
} 



* 
*/ 
+0

Ich habe meine Antwort mit der übersetzten Version aktualisiert. By the way, 'animationDidStop' ist eigentlich ein Ereignis in Xamarin (siehe [diese Dokumentation] (https://developer.xamarin.com/api/member/MonoTouch.CoreAnimation.CAAnimationDelegate.AnimationStopped/p/MonoTouch.CoreAnimation.CAAnimation/ System.Boolean /)). –

Verwandte Themen