iOS 7 Auto Layout - UIImageView inside UIScrollView - uiscrollview

I have a simple view in an iOS application which is causing me some problems.
In this view I have a UIScrollView (full width/height of main view), which is pinned to the top/bottom/leading/trailing of the main view (in IB).
Inside the UIScrollView I have a UIImageView which is pinned top/bottom/leading/trailing to the UIScrollView.
Now, the image inside the UIImageView is almost double the size of the main view, therefore the content mode of the UIImageView is set to Aspect Fit. My problem is that when I run the project, the image is being displayed at its actual size.
The reason the UIImageView is inside the UIScrollView is due to the fact that I want the user to be able to zoom in to the image (hence the reason it is double the size).
I also want the user to be able to rotate the screen as the image may be in portrait or landscape format depending on which image they choose to view in the previous view.
Surely this should be easy enough to do (in IB as well), however I cannot for the life of me figure it out.

You also have to add width and height constraints for UIImageView. It is caused by the fact that by default UIImageView has an intrinsic content size derived from the size of the image.
Following is code snippet for defining those constraints:
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0]];
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0]];
Even you can do this in IB.

If I understand your question, you want the content to be zoomed out at the start. Assuming that your content does not have the same aspect ratio as the phone (a safe assumption), you can either "letter box" / "curtain" the content, or only zoom out until either the height or width of the image would show on the phone (before aforementioned letter boxing). I chose this latter approach, and set my min zoom to be the greater of min zooms for either dimension.
The code is thus:
// configure image and scroll view for scrolling to extents of actual image
double widthScale = self.view.frame.size.width / image.size.width;
double heightScale = self.view.frame.size.height / image.size.height;
self.scrollView.minimumZoomScale = MAX(widthScale, heightScale);
self.scrollView.maximumZoomScale = MIN(1 / widthScale, 1 / heightScale) / [[UIScreen mainScreen] scale]; // scale to pixel resolution
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
It assumes that you are using full screen.
If you want the min of either dimension, use this:
self.scrollView.minimumZoomScale = MIN(widthScale, heightScale);

Related

How to prevent Safe Area from resizing according to image view?

In Interface Builder I have a simple view that contains a UIImageView and am trying to constrain the image view's width and height. I have added constraints several ways but whenever I run in the Simulator the image view does not display correctly but always adopts the dimensions of the PNG image, whose dimensions are smaller than the simulator's device. The Content Mode for the image view is Scale to Fill. I am loading the xib like this:
VCMain *vc = [[VCMain alloc] initWithNibName:#"Main" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc];
navController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
navControllermodalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:navController animated:YES completion:nil];
I have tried constraining the image view to the superview, and constraining it to the Safe Area, but nothing changes. Regardless of which I choose console printing reveals that the Safe Area always takes on the dimensions of the image view (which oddly takes on the dimensions of the png file, even though the setting is Scale to Fill).
I also tested assigning an image larger than the Simulator's dimensions (using iPhone Xs btw) and smaller. You can see in the pics below that the image view does not conform to the constraints.
What am I doing wrong? And why is the Safe Area conforming rather to the image size? Below are pics of IB that show settings, and then pics showing how the Simulator renders things.
When I use an image smaller than the Simulator device dimensions I get this:
and though you can't see, the Safe Area dimensions are {{0, 0}, {320, 480}}, exactly the size of the PNG.
When I use a version of the image much larger than the Simulator device's dims I get:
and again the Safe Area dimensions are exactly the size of the PNG, in this case {{0, 0}, {2133, 2789}}, even though the main view there has dims of {{0, 0}, {375, 812}}

Swift Xcode aspect-fit behaviour using AutoLayout on a UIImageView inside a containerView

I have a embedded containerview inside my viewcontroller that leads to a UIPageController. Then the UIPageController loads images from a 3rd VC controller.
So it just a simple image swipe / image carousel.
What I cant get to work is autolayout on the UIImage. My containerview has a maring top 0 right 0 left 0 and a height of 200pt with aspect ratio set.
Bellow it some other information shows eg title / text etc.
But all images appears zoomed in/croped in the containerview.
So how can I make the images scale and fit inside the container view?
Thanks,
set the image view's contentmode to scale aspect fit to see as much of the image as possible.
imageView.contentMode = .ScaleAspectFit

NSView free-angle rotation

I have NSView container (with NSImageView and some other custom subviews). How to set its rotation properly? I tried to set angle through setFrameRotation: and set rotation matrix in views layer. But in these cases subview image becomes downscaled and clipped.
Update:
If I set rotation via [myView setFrameRotation: angle]:
almost fine, except text frame (drawing via [NSString drawAtPoint:...] and rotation anchor is at left-bottom corner (I want at bottom-center, [myView setFrameOrigin:...] does nothing)
If I set rotation via myView.layer.transform = CATransform3DMakeRotation (angle, 0, 0, 1):
frame bound remains unrotated and clips subviews (but this approach is more suitable for view container)

Adding Custom Retina Image To TabBar In iOS5

I am trying unsuccessfully to get my custom retina images to display in my custom iOS5 TabBar.
I have 4 items in my TabBar, I have set the selected/unselected image to contact#2x.png which has a resolution of 160px x 75px. I figured 4 of these 160px width images would accommodate the 640px retina width nicely.
You can view my contact#2x.png here
https://lh4.googleusercontent.com/-afHulbEcxNE/TuPe-YIj91I/AAAAAAAAAII/lCojphAxF9w/s160/contact%2525402x.png
I have set all the items programtically as seen below.
UIImage *selectedContact = [UIImage imageNamed:#"contact#2x.png"];
UIImage *unselectedContact = [UIImage imageNamed:#"contact#2x.png"];
UITabBar *tabBar = self.tabBarController.tabBar;
UITabBarItem *item0 = [tabBar.items objectAtIndex:0];
UITabBarItem *item1 = [tabBar.items objectAtIndex:1];
UITabBarItem *item2 = [tabBar.items objectAtIndex:2];
UITabBarItem *item3 = [tabBar.items objectAtIndex:3];
[item0 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
[item1 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
[item2 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
[item3 setFinishedSelectedImage:selectedContact withFinishedUnselectedImage:unselectedContact];
At runtime I can see that the scale is set to 1
Why isn’t the 2 being picked up off the image suffix? The tab bar is huge, and isnt scaled.
Please see the simulator screenshot below…
https://lh5.googleusercontent.com/-A5oxZprlDhU/TuPfAlG_HQI/AAAAAAAAAIc/mIwHXOPZSrE/s735/simulator.png
My other retina images for my app icon and default icon are working.
Thoughts? I am driving myself nuts ☺ Thanks in advance.
JoePasq is wrong, he obviously is not up to date with the latest iOS5 appearance customisation API. Your problem could be that you specified the #2x in the filename, just pass "contact.png" to imagedNamed...
[UIImage imageNamed:# "contact.png"]
Have you looked at the documentation for customizing the appearance of UITabBar?
You should consult this tutorial by Ray Wenderlich about using the UIAppearance APIs.
His code is this:
UIImage *tabBackground = [[UIImage imageNamed:#"tab_bg"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UITabBar appearance] setBackgroundImage:tabBackground];
[[UITabBar appearance] setSelectionIndicatorImage: [UIImage imageNamed:#"tab_select_indicator"]];`
Note that the customization happens on the Tab bar, not the tab bar items—assuming it’s the same customization for each one.
As nbransby said you do not use #2x in the filename.
Prior unedited answer:
From the documentation:
The images displayed on the tab bar are derived from this image. If this image is too large to fit on the tab bar, it is scaled to fit. The size of an tab bar image is typically 30 x 30 points. The alpha values in the source image are used to create the unselected and selected images—opaque values are ignored.
Your icons should be 30x30 px for normal resolution and 60x60 px for retina resolution. They should also be a solid color, the tab bar adds the coloring.

How can I get NSScrollView to respect a clipping path

I am trying to make a NSScrollView with clipped corners, similar to the Twitter app:
I have a NSScrollView subclass which I added the following code:
- (void)drawRect:(NSRect)dirtyRect {
NSBezierPath *pcath = [NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:kDefaultCornerRadius yRadius:kDefaultCornerRadius];
[path setClip];
[super drawRect:dirtyRect];
}
I expected the content of the NSScrollView to have rounded corners, but it is not respecting the clipped path. How can I do this?
UPDATE & CLARIFICATION
I know how to make a custom NSScroller, I know how to make it transparent overlay. All I am asking is how to make the NSSCrollView clip its corners, including everything it contains. The NSScrollView is inside a NSView which has a background that could change, meaning a view overlay to fake the rounded corners is not an option.
After much fiddling, I just discovered that NSScrollView's can be made to have rounded corners by simply giving it a backing layer and setting that layer's corner radius provided you also do the same to it's internal NSClipView. Both are required, which now makes sense, since it's the clip view that actually provides the viewable window into the NSScrollView's document view.
NSScrollView * scrollView = ...;
// Give the NSScrollView a backing layer and set it's corner radius.
[scrollView setWantsLayer:YES];
[scrollView.layer setCornerRadius:10.0f];
// Give the NSScrollView's internal clip view a backing layer and set it's corner radius.
[scrollView.contentView setWantsLayer:YES];
[scrollView.contentView.layer setCornerRadius:10.0f];
You can apply a mask to a view's layer:
[myScrollView setWantsLayer: YES];
[myScrollView layer].mask = ...;
The mask is another CALayer. So in this case you'd create a CALayer, set its background colour to opaque, set its bounds to match the scrollview, and give it a cornerRadius of, say, 8.0.
The result would be that the scroll view and all its contents would appear to be masked to a roundrect with a corner radius of 8px.
Have you tried overriding
- (BOOL)isOpaque {
return NO;
}
And setting the scroll view's -setDrawsBackground: to NO and just leave the view without clipping and just draw the corners with [NSColor clearColor] since this will also clear the underlying color and simulate a round effect.

Resources