0
votes

I have an issue with an image view I'm adding dynamically to my scrollview. I'm using iOS 8 and Size Classes and Auto Layout. The scrollview has been added via the storyboard and I have also added constraints to match the size of the View.

The challenge is, the dynamically added imageview starts centered, but after an orientation change, it gets displaced within the scrollview.

There are tons of solutions here, and most of them pointed to overriding the ViewWillLayoutSubviews() function and then setting the UIImageView's center to the scrollview's there. None of the suggestions have worked for me. Whenever I rotate the device, the imageview gets displaced.

Some suggestions I've tried

UIScrollView with centered UIImageView, like Photos app

Center UIImageView inside UIScrollView without contentInset?

Here's how I'm adding the UIImageView. This function is called in the ViewDidLoad().

public void AddImageInScrollView(int index)
    {
        try
        {
            //Setting up the imageView

            var imageUrl = Items.fetchImages[index]; 

            //Setting up the imageView
            imageView = new UIImageView(); 
       //call method to load the images
            imageView.SetImage(
                url: new NSUrl(imageUrl.AbsoluteUri),
                placeholder: UIImage.FromFile("sample.png"),
                completedBlock: (image, error, type, url) =>
                {
                    imageResizer = new ImageResizer(image);

                    imageResizer.RatioResize(100,100);

                    UIImage resizedImage = imageResizer.ModifiedImage;
                    //when download completes add it to the list
                    Car.images.Add(resizedImage);

                });
            //end method call

            imageView.UserInteractionEnabled = true;
            imageView.ContentMode = UIViewContentMode.ScaleAspectFit;
            imageView.Center = ScrollViewMain.Center;


            //Adding the imageView to the scrollView as subView
            ScrollViewMain.AddSubview(imageView);

          //ScrollViewMain.ContentSize = imageView.Image.Size;
            ScrollViewMain.ContentSize = new CGSize(ScrollViewMain.Frame.Size.Width,ScrollViewMain.Frame.Size.Height);
           catch (Exception ex)
        {

            Console.WriteLine(ex.Message + ex.StackTrace);
        }
    }

The ViewWillLayoutSubviews function

    public override void ViewWillLayoutSubviews ()
    {
        base.ViewWillLayoutSubviews ();

        imageView.Frame = new CGRect(0,0,ScrollViewMain.Frame.Size.Width,ScrollViewMain.Frame.Size.Height);

        CenterScrollViewContents ();
    }

The CenterScrollViewContents function

   public void CenterScrollViewContents()
    {
        try
        {

        var boundsSize = ScrollViewMain.Bounds.Size;

        var contentsFrame = imageView.Frame;

        if (contentsFrame.Size.Width < boundsSize.Width) {

            contentsFrame.X = ((float)boundsSize.Width - (float)contentsFrame.Size.Width) / 2.0f;

        } else {
            contentsFrame.X = 0.0f;
        }

        if (contentsFrame.Size.Height < boundsSize.Height) {

            contentsFrame.Y = ((float)boundsSize.Height - (float)contentsFrame.Size.Height) / 2.0f;

        } else {
            contentsFrame.Y = 0.0f;
        }

        imageView.Frame = contentsFrame;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

A sample screen shot of what it looks like after rotation

Screen shot of displaced image in land scape mode

2
You are not updating the ContentSize of the ScrollView. I'd assume, that this is the problem.Sven-Michael Stübe
I am already doing that in the AddImageToScrollView function which is called in the ViewDidLoad(). //ScrollViewMain.ContentSize = imageView.Image.Size; ScrollViewMain.ContentSize = new CGSize(ScrollViewMain.Frame.Size.Width,ScrollViewMain.Frame.Size.Height);naffie
Yes but not in the Update ViewWillLayoutSubviews. Just try to copy ScrollViewMain.ContentSize = new CGSize(ScrollViewMain.Frame.Size.Width,ScrollViewMain.Frame.Size.Height); to this function.Sven-Michael Stübe
Nothing changes. I added it above the other two lines inside that function. The image is still not centered whenever I rotate the device.naffie
Hmm, ok. Have you got a small example project somewhere?Sven-Michael Stübe

2 Answers

1
votes

Move your code from ViewWillLayoutSubviews to ViewDidLayoutSubviews. The difference is that ViewWillLayoutSubviews is "Called to notify the view controller that its view is about to layout its subviews." and ViewDidLayoutSubviews is "Called to notify the view controller that its view has just laid out its subviews."

The problem is, that ScrollViewMain.Frame is

{X=0,Y=0,Width=375,Height=667} in ViewWillLayoutSubviews

but

{X=0,Y=0,Width=667,Height=375} in ViewDidLayoutSubviews

The Function looks like

public override void ViewDidLayoutSubviews()
{
    base.ViewDidLayoutSubviews();
    ScrollViewMain.ContentSize = new CGSize(ScrollViewMain.Frame.Size.Width, ScrollViewMain.Frame.Size.Height);
    imageView.Frame = new CGRect(0, 0, ScrollViewMain.Frame.Size.Width, ScrollViewMain.Frame.Size.Height);
    CenterScrollViewContents();
}

Bonus Protip:

You can use imageView.Center = ScrollViewMain.Center; to center views.

And if you have some more time, have a look at Autolayout constraints. They save you Frame calculation pains.

0
votes

I managed to solve this using a simple solution. I realized that while initializing the imageView, I didn't pass the frame size into it's constructor. There are multiple ways to do it, but for my case, after a screen rotation,it seems the size was not being updated.

Before:

        imageView = new UIImageView(); 
        imageView.Frame = new CGRect(0,0,ScrollViewMain.Frame.Size.Width,ScrollViewMain.Frame.Size.Height);

Solution:

        var frame = new CGRect(0,0,ScrollViewMain.Frame.Size.Width,ScrollViewMain.Frame.Size.Height);
   //Setting up the imageView
        imageView = new UIImageView(frame); 

The image inside the scrollView now is always centered even after orientation changes.