Aнгел
Aнгел

Reputation: 1429

imageView centered inside scrollView

How can I vertically center an image inside a scrollView?

I'm using storyboards in Xcode 5. The main view is embedded inside a navigation controller, and "Adjust scroll view insets" option is enabled in main Storyboard. This main view has a scrollView which size is equal to the main view size.

The imageView is inside the scrollView and it's the same size as the scrollView. Content mode is set to AspectFit.

So, hierarchy is as follows:

- UINavigationController
- UIView
   - UIScrollView
       - UIImageView

The image may be landscape or portrait, and can be any size (it's loaded at runtime). This is why imageView is the same size as the scrollView.

How can I vertically center the image inside the scrollView?

EDIT: As commented before, I have set imageView's contentMode to AspectFit because the image may be too big, so I need it resized. The problem I have is that the image is not center of the scrollView.

You can check screenshot at link and download source code at link.

Upvotes: 2

Views: 7201

Answers (4)

Douglas
Douglas

Reputation: 2524

I made a comment, but then took a look at your project. You are almost there. I ran through the following steps and have gotten the result you are looking for.

First, make sure you have auto layout turned ON!!!

In your storyboard click on your scroll view. You had a scroll view that was the same size as the view. You are going to put on some constraints. Down at the bottom of the story board you will see some icons.

enter image description here

The fourth one over looks sort of like an I-beam on its side, it is the pin button. After selecting the scroll view, click on this and it will bring up a pop up menu.

enter image description here

For the scroll view click on all the bars around the middle block so you pin the scroll view to the sides of the main view.

enter image description here

You will notice they are all red now.

Then go and click on the imageview. Once again you had it set to the size of the view. Using the pin button again, you are going to pin just the Width at 320 and the Height at 568. When you are done you are then going to use the next button over.

enter image description here

This is the align button. Click on that after you have selected your image view. You are going to click on Horizontal Center in Container, and Vertical Center in Container.

Next you will need to add one method to your ViewController.m file.

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [_scrollView setContentSize:CGSizeMake(self.view.frame.size.width, self.view.frame.size.height)];
}

Start up the simulator and let her rip! You will get one warning though. It says the content size is ambiguous for the scroll view. But that's OK, because you will set it on viewDidLayoutSubviews.

Hope that helps, or helps someone out. Autolayout and scroll views are a bit tough!!

EDIT#1

if you want to then make the image view scalable, by pinch zooming you can do the following.

Make sure you made the .h file follow the UIScrollViewDelagate.

@interface ViewController : UIViewController <UIScrollViewDelegate>

This will allow the scroll view to be able to access the delegate methods of the scroll view. The method you are looking for is called..

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

Then in the viewDidLoad method of your .m file do the following.

_scrollView.minimumZoomScale = 0.5;
_scrollView.maximumZoomScale = 4.0;
_scrollView.delegate = self;

The underscore and the variable name is the same as self.variable. Either will work.

That should do it. Let me know if it works or if you have any other questions. ENJOY!

Upvotes: 1

ukim
ukim

Reputation: 2465

It will be good to use auto layout as mentioned by @Douglas. However, if you prefer the traditional way, you can also make it work.

I'll first give you the answer and then explain it to you. You should first delete the image view from the storyboard ( I'll explain it later), and then add the viewWillAppear method.

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 1. Add the image view programatically
        UIImageView * imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"portrait.jpg"]];
        [_scrollView addSubview:imageView];
        _imageView = imageView;

    }

    - (void)viewWillAppear:(BOOL)animated
    {
        // 2. calculate the size of the image view
        CGFloat scrollViewWidth = CGRectGetWidth(_scrollView.frame);
        CGFloat scrollViewHeight = CGRectGetHeight(_scrollView.frame);
        CGFloat imageViewWidth = CGRectGetWidth(_imageView.frame);
        CGFloat imageViewHeight = CGRectGetHeight(_imageView.frame);
        CGFloat widthRatio = scrollViewWidth / imageViewWidth;
        CGFloat heightRation = scrollViewHeight / imageViewHeight;
        CGFloat ratio = MIN(widthRatio, heightRation);
        CGRect newImageFrame = CGRectMake(0, 0, imageViewWidth * ratio, imageViewHeight * ratio);
        _imageView.frame = newImageFrame;

        // 3. find the position of the imageView.
        CGFloat scrollViewCenterX = CGRectGetMidX(_scrollView.bounds);
        CGFloat scrollViewCenterY = CGRectGetMidY(_scrollView.bounds) + _scrollView.contentInset.top / 2 ;
        _imageView.center = CGPointMake(scrollViewCenterX, scrollViewCenterY);
    }    

Here is the explanation:

  1. You should not put the imageView in the storyboard, otherwise the frame of the imageView will be fixed by the storyboard, and will not change with the size of the image. Even if you choose UIViewContentModeScaleAspectFill, the frame of the imageView is still not changed. It just add some white space around the image.

  2. Now the imageView has the same size as your image. If you want it to be fully displayed, you need to calculate the frame yourself.

  3. Pay attention to the _scrollView.contentInset.top / 2, this is why you need to put the codes in viewWillAppear instead of viewDidLoad. The _scrollView.contentInset.top is the height of the navigation bar and is calculated automatically for you before willViewAppear.

You put your image view in a scrollView, I guess you want to zoom in and out. If this is true, add self.imageView = imageView; and the bottom of viewDidLoad. Set the delegate of _scrollView to self and add the following method:

    - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
    {
        return _imageView;
    }

Upvotes: 1

sargeras
sargeras

Reputation: 179

If you want to center image in an imageview use

imageView.contentMode=UIViewContentModeCenter;

image retains it's size in this this content mode. Alternatively you can use other content modes as per your requirement.

UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,      // contents scaled to fit with fixed aspect. remainder is transparent
UIViewContentModeScaleAspectFill,     // contents scaled to fill with fixed aspect. some portion of content may be clipped.
UIViewContentModeRedraw,              // redraw on bounds change (calls -setNeedsDisplay)
UIViewContentModeCenter,              // contents remain same size. positioned adjusted.
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,

Upvotes: 0

Saheb Roy
Saheb Roy

Reputation: 5957

These are the ones u can use, the 3 modes of ImageView content display.You can do this by dynamically setting them or u can set them in storyboard too, click on the ImageView and go to properties tab-bar and choose from there, run them and select which output u want.

imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.contentMode = UIViewContentModeScaleAspectFill;

Hope this helps

Upvotes: 0

Related Questions