UIScrollview zoom refresh content - iphone

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.

Related

How to set UITextView's content inset like Notes App

I am working in an app in which I need to give feature like Notes App in iphone. as shown in first screen shot , initially , notes leaves a tab before the content starts, I also wanted to do the same and for that when I set Left Content inset (of UITextView) by 25 , it shows like in screenshot 2, here you may see the image also gets shifted. I have set image as background. I don't know how to solve this problem.
I also tried by adding image as subview of UITextview but it won't repeat the lines, while scrolling (image of lines) like notes app.
I'm setting the background of Textview by following code.
[textView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"line_image.png"]]];
Please tell me if I am going wrong or any extra effort needed to get desired output.
Thanks
UITextView is UIScrollView subclass so all relevant delegate method are available for you (e.g. scrollViewDidScroll:) - you can adjust your custom background in that method.
There's very nice post on Dr.Touch blog about recreating Notes app interface - you can get general idea about how it is done from it. Basically what is done there is adding custom view that draws background behind the text view and adjust it in text view's delegate methods and also using KVO on its 'contentSize' property.
#Dinesh gave nice solution but it doesn't sound to be generic as I want to use image of lines instead of drawing them. Image has some special effects that can not be achieved by drawing. So to solve it I created a table view below the textview keeping textview's background transparent. Now just added the image of line to my tableview's custom cell and set content offset of UItableview same as of the scrollview (subview of text view ,refering to the answer of #Vladimir ) .
And used the following code to scroll my tableview with scrolling the textview and got the desired output.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
tableView.contentOffset =scrollView.contentOffset;
}
Keeping my tableview's number of rows at a very large number.
PS: instead of setting the content inset of textview, i set its frame's X position and decreased the width relaively.

Redraw text on zoomed UIImageView after zooming

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.

How do I properly handle rotation of a UIScrollView containing UIImageViews?

I'm developing an image viewer, much like the Photos App.
It's a UIScrollView with paging enabled with images loaded from the internet, so I've adapted portions of the LazyTableImages sample. The Scroll View and each ImageView inside of it have all of their autoresize mask flags set.
When I first observed how resizes were happening during rotation, it looked good, but once I started trying to interact with the scroll view, I realized that I also had to programmatically change the size of the contentView. I did that by implementing didRotateFromInterfaceOrientation: in my view controller.
[self.scrollView setContentSize:CGSizeMake(numberOfImages * portraitWidth, [scrollView bounds].size.height)];
With interaction behaving properly, I then discovered that, if I was viewing the second photo and rotated, portions of both the 1st and 2nd photos would be shown on the screen. I needed to change the contentOffset as well.
I've tried to fix this two ways - both by using the scrollRectToVisible:animated: method of UIScrollView, as well as trying to set the contentOffset property directly. And I've experimented by putting this code in implementations of both the "one-step" and "two-step" responses to changes in Orientation. For example:
-(void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
[self.scrollView setContentOffset:CGPointMake(currentlyViewedPhotoIndex * largeImageHeight,0) animated:YES];
In all cases though, it just looks janky as hell. Either I clearly see the scroll happen, or it just jumps. Uuuuuuuuuuugly! Is there a way to do this so that it behaves exactly like the Photos app does?
What I wound up doing instead - just before rotation starts, hide the UIScrollView and create a UIImageView that contains the currently viewed image. Rotate, that image will rotate all nice and pretty, and when rotation completes remove the ImageView and unhide the Scroll View.
Update - if you're reading this today (anytime after iOS 6), use a UIPageViewController and set transitionStyle to UIPageViewControllerTransitionStyleScroll, for crissakes.
I did something slightly different when faced with the same problem. In willRotateToInterfaceOrientation:duration:, I hide all of the UIScrollView's subviews except for the currently displayed subview, and in didRotateFromInterfaceOrientation: I unhide the subviews.

How to dynamically restore the UIScrollView's zoom level and position when my app relaunches?

My application consists of a UIImageView inside a UIScrollView, and I display a big image inside of it. The scroll view allows the user to pinch to zoom in/out in the image, and that all seems to work just fine.
However, when my application is terminated and then re-launched, the UIScrollView displays the image again in the original zoom level (which is currently set to display the whole image, by scaling it in a "aspect fit" mode).
I would really like to be able to re-launch my app and have the UIScrollView reopen with the same parameters as it was set when the app terminated. So if my image is currently zoomed in to the max, and scrolled all the way to the bottom left of it, that should be the view when I open the app again.
How can I do this?
Check the .transform property of the view. If you are zoomed in, this should be modified. Save and restore it on the next launch.
I have found a way to programmatically zoom UIScrollView. This may help you set the desired zoom level upon startup.
The sample code, together with ZoomScrollView class that encapsulates the required zooming magic and a detailed discussion of how (and why) UIScrollView zooming works is available at github.com/andreyvit/ScrollingMadness/.
Someone asked this a while ago, but I don't think you'll like the answer. Hopefully you'll get a better one.
I do it like this:
When you quit save the zoomlevel (myScrollview.zoomScale) and the contentview frame origin.
When you reopen you can set the zoomscale. You also have to set the content size to the new zoomlevel, because otherwise the boundaries are not correct.
[myScrollview setZoomScale:savedZoomScale];
CGSize newsize = CGSizeMake(origsize.width * savedZoomScale,
origsize.height * savedZoomScale);
myScrollview.contentSize = newsize;
To set the offset:
[myScrollView setContentOffset:savedFrameOrigin animated:YES];

How do I reset (i.e. un-zoom) a UIScrollView?

I have a UIScrollView that contains an image and a segmented control that allows the user to switch the image inside of the ScrollView. If I just swap the image out inside of the UIImageView, it will display the new image in the zoomed-in state. How do I reset the UIScrollView back to its un-zoomed-in state?
I have a detailed discussion of how (and why) UIScrollView zooming works at github.com/andreyvit/ScrollingMadness/.
(The link also contains a description of how to programmatically zoom UIScrollView, how to emulate Photo Library-style paging+zooming+scrolling, an example project and ZoomScrollView class that encapsulates some of the zooming magic.)
Quote:
UIScrollView does not have a notion of a “current zoom level”, because each subview it contains may have its own current zoom level. Note that there is no field in UIScrollView to keep the current zoom level. However we know that someone stores that zoom level, because if you pinch-zoom a subview, then reset its transform to CGAffineTransformIdentity, and then pinch again, you will notice that the previous zoom level of the subview has been restored.
Indeed, if you look at the disassembly, it is UIView that stores its own zoom level (inside UIGestureInfo object pointed to by the _gestureInfo field). It also has a set of nice undocumented methods like zoomScale and setZoomScale:animated:. (Mind you, it also has a bunch of rotation-related methods, maybe we're getting rotation gesture support some day soon.)
However, if we create a new UIView just for zooming and add our real zoomable view as its child, we will always start with zoom level 1.0. My implementation of programmatic zooming is based on this trick.
If you're not redrawing your view on the completion of the pinch zooming event, then the zoom factor is being set by the transform property of the view you return from the viewForZoomingInScrollView: delegate method. To reset this zoom, set the value of the view's transform property to CGAffineTransformIdentity.
Beware, though, that your next pinch-zooming operation will start where the previous pinch-zoom left off (that is, your new scale will be ignored). To work around this, you may need to implement some of what I describe here.