I have a UIScrollView with a single UIImageView child. The scrollView is pinned on all sides to the (root) parent container with autolayout, and the child imageview is also pinned to all sides with content mode set to AspectFill.
UIImage *image = [UIImage imageNamed:#"photo1.jpeg"];
_imageView.image = image;
_imageView.contentMode = UIViewContentModeScaleAspectFill;
_scrollView.contentOffset = CGPointZero;
_scrollView.contentSize = _imageView.image.size;
_scrollView.zoomScale = 1;
The image in this case is wider than my screen. When I launch my app, the imageview is correctly displaying the image filling up the screen. However, I can't seem to pan the image left or right. When i zoom in, I can pan, however, I'm unable to pan to the corners of the image.
I feel like my content size is not being computed properly thanks to auto-layout, but I'm not sure which parameters I can play which would allow me to scroll the image to its edges.
I've attached an image below, where you can see that the image can't be scrolled in a way that displays the beginning of 'happiness'. I also uploaded the sample here
the child imageview is also pinned to all sides
Instead, turn off auto layout for the child image view (set its translates... to YES). You are already setting the scroll view's contentSize to the image size, so now scrollability will leap into life and will interface correctly with zooming.
Related
I have a UIImageView that display a UIImage with the content mode set with UIContentModeScaleAspectFit. The imageview is as width as the screen. I want to resize the imageview without changing image position and scale. So, after resizing, the UIImage would be still virtually at the same position and still virtually as width as the screen, but not entirely visible because of the imageview resizing.
I try using UIContentModeLeft, while resizing from the right, to fix UIImage position, but my image wasn't at full resolution like when I'm using UIContentModeScaleAspectFit.
I'm clueless about this. I might need to use CGImage or CIImage, but I don't know where to start.
Set the image you want to display as the background of the view, instead of the source image.
You can use:
yourImageView.background = [UIColor colorWithPatternImage:[UIImage imageNamed:#"nameOfTheImageYouWantToDisplay"]];
I manage to solve my problem. Here's what I did :
Create a UIView in which I add a UIImageView subview
Set the imageview content mode to UIContentModeScaleAspectFit
Defining imageview frame to the screen with [[UIScreen mainScreen] bounds]
setClipsToBounds = YES to the UIView
Now, when resizing, the imageview is not scaling because its frame is define to be as big as the screen, setClipsToBounds: make sure I don't see part of the image that is outside of the UIView frame.
I have a UIImageView with Auto-layout to the container margins. I set a UIImage to it in the ViewController. If I use UIViewContentModeScaleAspectFit then the image is centred in the middle of the screen as I wanted and everything looks great, but when I give the UIImageView a background color, I can see it still spreads all the way to the container margins, and doesn't get the image's proportions and dimensions. This is my code:
UIImage *passedImage = [UIImage imageNamed:self.photoTitle];
CGRect imageBounds = CGRectMake(0, 0, passedImage.size.width, passedImage.size.height);
[self.imageView setImage:passedImage];
self.imageView.bounds = imageBounds;
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
I have tried everything to fix it and looked everywhere for answers, please help me, you are my only hope.
Instead of pinning the image view's edges to the container margins, pin its center X and center Y to the container's center X and center Y.
This gives the same visual result — the image is centered — but leaves the image view free to resize itself according to its contents.
UIImageView does not resize itself according to image size it renders. If you need to size it accordingly, you need to do it yourself. Matt's answer is reasonable, but you still need to update your image view size at some point. I'd suggest doing it in layoutSubviews or updateConstraints method of your view or in view controller's viewDidLayoutSubviews.
I have a screen-sized UIScrollView holding an identically sized UIImageView.
I have an image set inside of the UIImageView with AspectFit, so with a wider image, there are black bars on the top and bottom. This is as expected when zoomed out.
Double tapping the screen forces a [self.scrollView setZoomScale:self.scrollView.maximumZoomScale animated:YES]; The problem with this is that on images like the one mentioned above, I'm able to pan far beyond the edges of the photo.
I assume this is because I return imageView; in (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView and the imageView height is taller than the image, so I'm able to pan to the top and bottom of the imageView, ignoring its contents.
So, how do I limit panning the scrollview to the bounds of the image?
U need to use this: Emulating aspect-fit behaviour using AutoLayout constraints in Xcode 6
Aspect fit on Autolayout. Then You need add aspect ration constraint when loading image, if images are different size. U can get one error, image after zoom sticks to right edge. Still can't solve it.
Just set the content size of scrollview to the size of image just by this code:
scrollView.contentSize = [scrollView imageView].image.size;
Note that you should do this at the time you set image for your scrollview imageView.
I have a UIImageView which is set to mode Aspect Fit. Now I want to place an edit button on top right corner of that image view. I am using auto layout and have a constraint of (Button->Trailing Space to superview) and the layout is connected via IBOutlet.
Once the image is set in UIImageView, I want to resize the ImageView Frame, so I can place the UIButton on top right. But UIImageView is not resizing as per image. Look at the gray part in the attached image (It is the background of ImageView)
imageView.clipsToBounds = YES;
imageView.image = image;
[imageView sizeToFit];
buttonLeadingSpace.constant = imageView.frame.origin.x+imageView.frame.size.width-44;
First of all, you should align your button with ImageView top & trailing. you can add constant=padding you need for your button.
UIImage is displaying as per your properties set for UIImageView (ie. contentMode = AspectFit). Here are the few options you might be interested in
If you want to fill the complete width just remove the height constraint from the UIImageView. It will fill the width and increase the UIImageView height as per image aspect ratio.
If you want same height and width of UIImageView set contentMode = aspectFit. this will fill the complete UIImageView but might clip the image.
Remove leading and trailing constraints from UIImageView. Align horizontal center and add image width constraint.
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.
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:
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.
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.
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;
}
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.
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.
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.
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.
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!
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
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,