I have an iOS app which boils down to the following:
A view controller which implements all the UIScrollViewDelegate methods.
A customised UIImageView which is the view returned by viewForZoomingInScrollView in the first view controller.
In the drawRect method of the customised UIImageView I overlay some text at various positions on the image, the text can be at various sizes and angles, constrained by a rectangle defined by points on the image. So the co-ordinate system is all relative to the image associated with the UIImageView.
Sometimes the text is having to be rendered into areas that are far too small to allow the text to be readable at the default zoom level.
When I zoom in, however, this doesn't make the text any more readable as the text was rendered on the original UIImageView at the font size appropriate for the bounds it was given.
What I'd like is some way to redraw this text, in the correct location still, at a proportionally larger font size when zoomed in. Is this possible, and how would I do it?
I've been working on a zoomable floorplan myself and dealt with it in a rather simple way.
I put my text in labels and put those labels on top of the ImageView.
While zooming the labels scale with the UIImageView and thus the text within scale as well.
When zooming in too much however text becomes vague and blurry so you might want to update those text labels in the:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
For me this was sufficient, I hope this might be so for you as well.
Instead of trying to fix this, I'd say your design is a bit wrong. I'd reengineer this so that you're rendering the entire contents that you're displaying in the highest zoom that you want, and then allow the scrollview to zoom in/out of the finished content by specifying the zoom parameters. Otherwise you'll go insane trying to fix text. Just draw the entire image / document as big as you want it to be, then add THOSE contents to the scroll view, at some lower zoom, allowing the user to zoom in/out as they desire. Then you're done.
You can write your overlay text on UILabels, attached to the UIViewController view.
Then you need to make your own custom class from UIScrollView and override
- (void)setContentOffset:(CGPoint)anOffset
here, using the anOffset and self.zoomScale you can place your labels at the places you want, with apropriate font size and all. So, they will change their positions every time your scrollview moves or zooms.
Related
Is there a way that I can control which subviews of a UIScrollView are scaled and which are not?
For example, I have a map as the bottom layer (not MapKit, just a flat image) which can be zoomed and panned. Depending on user selections, markers are dropped on the map to indicate specific buildings/places etc. These markers are are also UIImageView, using pixel co-ordinates of the map image (eq Building X is at (934, 842), marker is placed here). Zoomed out however these markers are somewhat difficult to see as they also scale/zoom out to the same level as the map.
So is there a way that I can tell the UIScrollView NOT to scale the marker images, but still allow it to pan/reposition them when the map image is zoomed?
I think the method you may be looking for is the UIScrollViewDelegate's
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
This lets you return the view which you want the zoom to be applied to, in your case this will be the background map image.
If you don't want the markers to be scaled at the same time, you will need to add the markers directly as subviews of the UIScrollView, instead of adding them as subviews of your background map UIImageView.
As you mentioned, the markers are placed relatively to the map background UIImageView, this means if you add the markers to the UIScrollView instead, they won't be placed in the same position on the map once you change the scroll.
To solve this, you will need to calculate the equivalent coordinates relative to the UIScrollView.
While this may seem rather daunting, it is actually quite trivial to do once you know the zoom factor.
To get the zoom factor, use the UIScrollViewDelegate method
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
Then you can get the zoom factor by calling :
scrollView.zoomScale
and recalculate the marker coordinates by applying this zoomScale to the original values, and reposition your markers accordingly.
Reference:
UIScrollView Class Reference
UIScrollViewDelegate Protocol Reference
Hope this helps :)
I am currently using a uiscrollview to zoom views in and out. If I have a textview, the font becomes blurred after it is zoomed in. Can I force the content to refresh? i.e setneedsdislay ?
you need to modify this behavior in scrollView delegate method -
- (void)scrollViewDidZoom:(UIScrollView *)aScrollView
or
- (void)scrollViewDidEndZooming:(UIScrollView*)scrollView withView:(UIView*)view atScale:(float)relScale
Check out the CATiledLayer example provided by the ScrollViewSuite sample code.
The TapToZoom example illustrates a way to get the view to redraw its content when one zooms in. I.e. you need to somehow set your view's frame to be larger than the screen, or maybe you can also use transforms - however, I never used transforms before.
I have an image that I would like to display in a UITableViewCell using the UITableViewCellStyleSubtitle style that provides a UIImageView, and two lines of text, plus an optional accessory view.
However, when I set the content mode of the UIImageView to either of UIViewContentModeScaleAspectFit or UIViewContentModeScaleAspectFill, it appears to make no difference. Both of these content modes simply display the entire image, shifting the text to the right to make room for the image.
Does anyone have any examples of how these actually differ in practice? The docs say:
UIViewContentModeScaleAspectFit:
Scales the content to fit the size of the view by maintaining the aspect ratio. Any remaining area of the view’s bounds is transparent.
UIViewContentModeScaleAspectFill:
Scales the content to fill the size of the view. Some portion of the content may be clipped to fill the view’s bounds.
But these content modes don't appear to be behaving as advertised.
EDIT: I'm running SDK iOS 4.
I had the same problem.
Seems like the Apple documentation is a bit lacking.
I found the answer by searching around the internet.
http://www.iphonedevsdk.com/forum/iphone-sdk-development/2973-crop-image.html
Basically,
img1.contentMode = UIViewContentModeScaleAspectFill;
img1.clipsToBounds = YES;
If you want it to be a bit more fancy, check out this post:
UIImageView change Width and Height
The reason you don't see a difference between those modes is that the UITableViewCell automatically sizes its image view to fit the aspect ratio of the image. The content modes only come into play when the view's aspect ratio is different from the image's.
Either override layoutSubviews in your custom UITableViewCell class or create an image view yourself (don't use the one that the table view cell provides).
I am currently working on an application for a client, and they have made an odd request. The request involves putting a custom image as the indicator for the scrollview. I am not even sure if this is possible but if it is can you please let me know how one would go about doing that.
Thanks
UIScrollView streches a small, semi-transparent circle image to generate its scrollbars. You can find this image as the first subview of a UIScrollView:
UIImageView *circle = [scrollView.subviews objectAtIndex:0];
However, as I said this image is stretched, and as far as I can tell, only the alpha values are considered when drawing the scroll bars.
So for example if you're only interested in changing the top/bottom ends of the scroll bar, you can try to change this image. However, I doubt you'll be able to do anything interesting.
A possible solution that comes to mind, and this is only a theory, is to add a custom, transparent UIView on top of a UIScrollView. Then you can hide the default scroll bar (by using showsHorizontalScrollIndicator and showsVerticalScrollIndicator), pass the necessary touch events to the UIScrollView to scroll the content, and draw the scrollbars in your custom view.
I have a subview inside a uiscrollview. Then I zoom it out. So it becomes bigger and allows me to scroll through it.
So what is actually changing here? ContentSize of UIScrollView?
If you are not manually responding to changes in the zoom scale (like I describe in this answer), the view that you return from the -viewForZoomingInScrollView: delegate method is simply having a scaling transform applied to it by the UIScrollView. The frame size of the view is not changing, it is just being graphically transformed (which is why you see blurriness at higher scale factors).
The content size of the scrollview remains logically the same. If you check the frame of the scroll view it remains the same.
I think all that is changing is the scaling of the CGLayers. When you zoom in, it shrinks the clipping region frame smaller but then scales the CGLayer transform upwards. In other words, all the logical elements are still present it is simply choosing to draw and display a different part of it.
In the iPhone Application Programming Guide they have a good explanation about the relationship between frames, clipping regions and various transforms on views.