Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 77050

Custom Renderer not being called on iOS

$
0
0

Hello,

I`m trying to take a photo from library and then send it to a crop view.

To take the photo from library I use a custom renderer and it is working fine, here is the code:

using System;
using Xamarin.Forms;


namespace App
{
    public class CropperPage : ContentPage
    {
        public CropperPage ()
        {       
            #if __IOS__
            MessagingCenter.Subscribe<App.iOS.CropperPageRenderer, UIKit.UIImage >(this, "cropiOS",  async (sender, arg) =>
            {

            await Navigation.PopAsync();            
            var pag = new CropperPageiOS(arg);
            await Navigation.PushAsync(pag);


            });
            #endif
        }

        protected override void OnDisappearing()
        {   
            base.OnDisappearing();

            #if __IOS__ 
            MessagingCenter.Unsubscribe<App.iOS.CropperPageRenderer, UIKit.UIImage >(this, "cropiOS");
            #endif
        }
    }
}

custom renderer:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;

[assembly:ExportRenderer(typeof(App.CropperPage), typeof(App.iOS.CropperPageRenderer))]
namespace App.iOS
{
    public class CropperPageRenderer : PageRenderer
    {

        UIImagePickerController imagePicker;
        UIWindow window;
        UIViewController viewController;

        public CropperPageRenderer ()
        {
            Console.WriteLine("*****iOS Crop Page*****");
        }

        protected override void OnElementChanged (VisualElementChangedEventArgs e)
        {
            base.OnElementChanged (e);

        }

        public override async void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // create a new picker controller
            imagePicker = new UIImagePickerController ();

            // set our source to the photo library
            imagePicker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;

            // set what media types
            imagePicker.MediaTypes = new string[]{"public.image"};

            imagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia;
            imagePicker.Canceled += Handle_Canceled;

            // show the picker

            window = UIApplication.SharedApplication.KeyWindow;
            viewController = window.RootViewController;

            if (viewController == null) {
                while (viewController.PresentedViewController != null)
                    viewController = viewController.PresentedViewController;
                await viewController.PresentViewControllerAsync(imagePicker, true);
            }
            else
                await viewController.PresentViewControllerAsync(imagePicker, true);

        }

        // Do something when cancelled
        void Handle_Canceled (object sender, EventArgs e) {
            Console.WriteLine ("picker cancelled");
            imagePicker.DismissModalViewController(true);
        }

        // This is a sample method that handles the FinishedPickingMediaEvent
        protected async void Handle_FinishedPickingMedia (object sender, UIImagePickerMediaPickedEventArgs e)
        {
            await imagePicker.DismissViewControllerAsync (true);

            // get the original image
            UIImage originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage;
            if(originalImage != null) {

                           //send a message to pop the CropperPage and send the image
                Xamarin.Forms.MessagingCenter.Send<CropperPageRenderer, UIImage>(this, "cropiOS", originalImage);
                // do something with the image
                Console.WriteLine ("got the original image");
            }
        }
    }
}

After the Image is picked the Handle_FinishedPickingMedia is triggered and send a message to pop the CropperPage from forms and Push another Page
that is also a custom renderer. And here is my problem!

in the CropperPage we have this Message from MessageCenter:

                  #if __IOS__
            MessagingCenter.Subscribe<App.iOS.CropperPageRenderer, UIKit.UIImage >(this, "cropiOS",  async (sender, arg) =>
            {

            await Navigation.PopAsync();            
            var pag = new CropperPageiOS(arg);
            await Navigation.PushAsync(pag);


            });
            #endif

The CropperPage is popped... but the CropperPageiOS is not pushed.
This page is based in the code from this post

I tried to adapt it but could not test because the custom renderer is not working.
Here is the code:

using System;
using Xamarin.Forms;

namespace App
{
    public class CropperPageiOS : ContentPage
    {
        public CropperPageiOS (UIKit.UIImage photo)
        {

        }
    }
}

And the custom renderer:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using System.Drawing;
using CoreGraphics;


[assembly: ExportRenderer(typeof(App.CropperPageiOS), typeof(App.iOS.CropperPageiOSRenderer))]
namespace App.iOS
{

    public class CropperPageiOSRenderer : PageRenderer
    {

        UIImageView imageView;
        CropperView cropperView;
        UIPanGestureRecognizer pan;
        UIPinchGestureRecognizer pinch;
        UITapGestureRecognizer doubleTap;
        UIImage photo;

        UIWindow window;
        UIViewController viewController;

        //public static void Init() { }

        public CropperPageiOSRenderer (UIImage originalImage)
        {
            photo = originalImage;
        }



        protected override void OnElementChanged (VisualElementChangedEventArgs e)
        {
            base.OnElementChanged (e);

            var page = e.NewElement as CropperPageiOS;
            var view = NativeView;

        }

        public override async void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            using (photo) {
                imageView = new UIImageView (new CGRect (0, 0, photo.Size.Width, photo.Size.Height));
                imageView.Image = photo;
            }

            cropperView = new CropperView { Frame = View.Frame };
            View.AddSubviews (imageView, cropperView);

            float dx = 0;
            float dy = 0;

            pan = new UIPanGestureRecognizer  (() => {
                if ((pan.State == UIGestureRecognizerState.Began || pan.State == UIGestureRecognizerState.Changed) && (pan.NumberOfTouches == 1)) {

                    var p0 = pan.LocationInView (View);

                    if (dx == 0)
                        dx = (float)p0.X - cropperView.Origin.X;

                    if (dy == 0)
                        dy = (float)p0.Y - cropperView.Origin.Y;

                    var p1 = new PointF ((float)p0.X - dx, (float)p0.Y - dy);

                    cropperView.Origin = p1;
                } else if (pan.State == UIGestureRecognizerState.Ended) {
                    dx = 0;
                    dy = 0;
                }
            });

            float s0 = 1;

            pinch = new UIPinchGestureRecognizer ( () => {
                float s = (float)pinch.Scale;
                float ds = Math.Abs (s - s0);
                float sf = 0;
                const float rate = 0.5f;

                if (s >= s0) {
                    sf = 1 + ds * rate;
                } else if (s < s0) {
                    sf = 1 - ds * rate;
                }
                s0 = s;

                cropperView.CropSize = new SizeF (cropperView.CropSize.Width * sf, cropperView.CropSize.Height * sf);  

                if (pinch.State == UIGestureRecognizerState.Ended) {
                    s0 = 1;
                }
            });

            doubleTap = new UITapGestureRecognizer ((gesture) => {
                Crop();

            }) { 
                NumberOfTapsRequired = 2, NumberOfTouchesRequired = 1 
            };

            cropperView.AddGestureRecognizer (pan);
            cropperView.AddGestureRecognizer (pinch);
            cropperView.AddGestureRecognizer (doubleTap); 

        }

        async void Crop()
        {
            var inputCGImage = photo.CGImage;

            var image = inputCGImage.WithImageInRect (cropperView.CropRect);
            using (var croppedImage = UIImage.FromImage (image)) {

                imageView.Image = croppedImage;
                imageView.Frame = cropperView.CropRect;
                imageView.Center = View.Center;

                cropperView.Origin = new PointF ((float)imageView.Frame.Left, (float)imageView.Frame.Top);
                cropperView.Hidden = true;
            }

            await viewController.DismissViewControllerAsync (true);
        }
    }
}

Am I doing anything wrong??

Or there are any way to "navigate" between the iOS PageRenderes directly without have to use a new custom renderer?

The CropperPageiOSRenderer is never getting called! But the CropperPageiOS constructor is hit!


Viewing all articles
Browse latest Browse all 77050

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>