I'm new to iPhone dev and Obj-C and I have several problems with ScrollView/ImageView while getting close to deadline. I used IB to create interface so I access most parameters via builder.
1) I was using touch events (begin/moved/ended) on imageView to switch images. When I put ImageView to ScrollView the old gestures stopped working and I can only zoom. If scrollView of both have focus I can't use my gestures even when zoomed out. How can I use both?
2) How do I zoom only image part of view? Unfortunately I also see background area around :/ What's worse - after rotating the view keeps it's old dimensions and I have even more black areas around image. For some reason image is in top-left corner.
Code snippets I found doesn't really help me much in this case. I have various images of different sizes in imageView to switch and zoom in/out.
EDIT: Ok, a little different. How do I override scrollview touch mode so that when image is zoomed out (to screen size) "normal" gestures would work. Currenly I have either scroll view scrolling or gestures, can't use both. Anyone?
Solved by dynamically changing imageview to imagesize and switching like:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
if (scrollView.zoomScale==1.0) {
scrollView.userInteractionEnabled = NO;
imageView.userInteractionEnabled = YES;
}
Not the best solution but works good enough.
Related
I have a image in UIScrollView, I wants user cannot scroll image in zoom time, I read many property of UIScrollView, but I am confused.
How we stop scrolling image(horizontally or vertically) when user zoom the image in scrollView.
I already test
scroll.scrollEnabled=NO;
scroll.directionalLockEnabled = YES;
scroll.bounces=NO;
scroll.scrollEnabled = N0; stop scrolling but the task is that the user cannot scroll the image ,when user zoom the image , I need help
Thanks
You have to set your viewcontroller as scrollviews delegate. Assuming you have UIImageView that you are zooming in scrollView. What you want to do is to center it in the middle of scrollviews bounds while zooming. If you only want to disable scrolling in vertical or horizontal direction then change only x or y center of imageView
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
self.imageView.center=CGPointMake(CGRectGetMidX(self.scrollView.bounds), CGRectGetMidY(self.scrollView.bounds));
}
I highly recommend having a look at apple video session on advanced scrollview techniques 2010, 2011 and 2012 they really explain quite well what a powerful beast UIScrollView really is. Hope this was helpful
This is a general question to a specific problem.
I am using a UIScrollView in an app that displays photographs. on iOS < 4.0, zooming works great. the same app running on iOS 4.0.x has problems zooming. specifically, if the image does not fill the view (and black bands appear at top/bottom), the first zoom is jerky and garbage data is shown on the bottom of the screen.
the source code to analyze is way to complex and spread out to adequately share here. Can anyone suggest any areas to look at that might cause this strange behavior?
thanks!
Mark
edit: here's the code from the double tap handler (borrowed from the tapDetectingImageView sample code):
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotDoubleTapAtPoint:(CGPoint)tapPoint {
// double tap zooms in
float newScale = [self zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[self zoomToRect:zoomRect animated:YES];
}
I can force the weirdness if I change the animated parameter in the call to zoomToRect. when animated is NO, my image becomes 2 images superimposed one on top of the other. the bottom image is the original zoom level, the top image is the new zoom level. if I swipe the screen to pan, the image is refreshed. It's almost as if a call to layoutSubviews or DrawRect is not getting called.
This may or may not be related, but the way that UIScrollView dealt with scale factors changed in an undocumented way in iPhone OS 3.2+.
Previously, if you used -scrollViewDidEndZooming:withView:atScale: to re-render your content by applying the identity transform to the view and then redrawing your image sharply at the new scale factor, UIScrollView would ignore this and keep handing you absolute scale factors based on the initial size of the view.
On iPhone OS 3.2+, UIScrollView now gives you a relative scale factor based on the last time you reset the transform of the content view to be the identity transform. This can lead to significant scaling differences between the various OS versions.
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.
I am trying to create an app with horizontal scrolling, so that one would be able to scroll horizontally through a series of images. I watched the WWDC Session 104 video on this, and while they made an interesting app, they flew through the basics of it very quickly.
I understand using the UIScrollView, and that I have to enable paging. After that they say that I should add more views as subviews of the scrollview, but I am not clear on how to do that. I am also not clear on how I add my images to those views.
As you can probably tell I am pretty new at this so any help would be appreciated.
You want to look into UIImageView. It's a view specifically for holding images.
When you add your images, you want to set their rects (probably using initWithFrame: for each UIImageView) so that:
the first image is at 0,0
the second image is at 320,0
third is at 640,0 (etc)
I.e. each image is 320 pixels right of the previous.
The final step is to set the contentSize for your UIScrollView -- this is a CGSize which describes the total size of the scroll view.
If you have 3 images, you would then set it to (320*3) * 480 using e.g.
myScrollView.contentSize = CGSizeMake(320*3, 480);
A lot of people, when they initialize the scroll view, have a for loop or similar which steps through the images they want to display. These for loops tend to look something like this:
CGFloat scrollWidth = 0.f;
for (UIImage *someImage in someNSArrayWithImages) {
UIImageView *theView = [[UIImageView alloc] initWithFrame:
CGRectMake(scrollWidth, 0, 320.f, 480.f)];
theView.image = someImage;
[myScrollView addSubview:theView];
[theView release];
scrollWidth += 320.f;
}
myScrollView.contentSize = CGSizeMake(scrollWidth, 480.f);
This way you'll get things lined up and you'll get the content size for you at the same time.
If you want to make it so that the scroll view "intelligently" scrolls to each image and stops when people slide left/right, you can do myScrollView.pagingEnabled = YES.
Hope that helps get you going.
Assuming you have "infinite" images, putting them all there at or before launch time in a huge UIScrollView will not be an option. (there is a limit to the size of a UIView)
The way I solved it: Make a UIScrollView covering the whole screen. It's content should be a UIView of 3*320 width and 480 height, extending 320px left and 320px right.
Put 3 UIImageView's in it, left, middle and right. Set paging=YES, so the uiscrollview clips to the 3 "pages" you've created.
Make sure your class is the delegate of the uiscrollview, and listen for
-(void)scrollViewDidEndDragging:(UIScrollView*)sv willDecelerate:(BOOL)notFinished
-(void)scrollViewDidEndDecelerating:(UIScrollView*)sv
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView*)sv
and make the appropriate transitions on hitting paging boundaries; shift images and set ContentOffset so you're looking at the center image again.
I suggest you make this first, and only then read on...
Then you will hit on a bug, documented here UIScrollView - (bounces = NO) seems to override (pagingEnabled = YES) and here http://www.iphonedevsdk.com/forum/iphone-sdk-development/935-paging-uiscrollview.html, which makes that you cannot disable bouncing and have paging enabled at the same time. So enable bouncing, and subclass UIScrollView, overruling setContentOffset in there to prevent bouncing. (having bouncing really enabled will make for a rather unusual user experience)
Have a look at Apple's PageControl sample code. It's fairly short and easy to follow so you'll get the gist of setting up a project where multiple view controllers are loaded as you swipe horizontally.
Once you have this setup then it's the view controller's responsibility to load its own content (in your case, an image). You should make sure you understand how to load images first (using threads, etc) before you tackle paging, etc.
Think of it as two independent tasks. The view control is responsible for loading and displaying an image. The scroll view with paging just tells the appropriate view controller when to load itself (it doesn't care what the view controller does once its loaded)
Good luck!
I have a UIScrollView contained within a custom UIView with a content size larger than the ScrollView's frame.
I am able to drag scroll as I expect, but the thing doesn't give me the rubber banding effect that you get with the UITableView or UIWebView. It just stops when you get to one of the extremes.
I have set bounce = YES, is there something else I'm supposed to do?
I read the docs, and they say I have to implement the delegate. I did that.
They also say I should change the zoom levels, but I don't want the user to actually be able to zoom so I haven't set these.
For anyone that finds this thread later, if you are subclassing UIView and re-setting the UIScrollView's frame on every layoutSubviews, that is the problem - it cancels the bounce:
http://openradar.appspot.com/8045239
You should do something similar to this:
- (void)layoutSubviews;
{
[super layoutSubviews];
CGRect frame = [self calculateScrollViewFrame];
if (!CGRectEqualToRect(frame, self.scrollView.frame))
self.scrollView.frame = frame;
}
I had the same problem, on a UIScrollView that wasn't all filled up (but I still wanted it to bounce). Just setted:
scroll.alwaysBounceVertical/Horizontal = YES;
And it worked as expected
It turns out that keeping the UIScrollView within my custom UIView was causing the trouble.
Once I switched my custom UIView to instead inherit from UIScrollView, then the bouncing started working.
That is interesting... Is there a lot going on while the user scrolls the scroll view? Maybe that could cause the problem. The iPhone can multitask, but not too much. Can I see your entire code having to do with the scroll view?