In Xcode 5 I have created a universal app, with a UIScrollView containing an UIImageView (here fullscreen):
Since I've set all UI properties in the Interface Builder (the image to be displayed, the UIImageView dimensions of 1000 x 1000 pixels and the UIImageView Mode set to "Scale To Fill"), the actual source code in the ViewController.m is very short:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
/*
if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
_imageView.frame = CGRectMake(_imageView.frame.origin.x,
_imageView.frame.origin.y,
800, 800);
}
*/
_scrollView.contentSize = _imageView.bounds.size;
NSLog(#"%s: _scrollView %# %#",
__PRETTY_FUNCTION__,
NSStringFromCGPoint(_scrollView.frame.origin),
NSStringFromCGSize(_scrollView.frame.size));
NSLog(#"%s: _imageView %# %#",
__PRETTY_FUNCTION__,
NSStringFromCGPoint(_imageView.frame.origin),
NSStringFromCGSize(_imageView.frame.size));
}
This works surprisingly (for me as iOS newbie) well in iPhone and iPad - and the app can even be rotated.
However the image displayed for iPhone is a bit too large and needs to be scaled down for more comfortable playing:
I was hoping, that since the UIImageView Mode is "Scale To Fill", I would just need to change its frame (or bounds? I've tried both) - as in the commented code shown above.
But this doesn't work - the scrolling breaks (can't scroll to the image bottom anymore).
Any advice please?
(I also hope to add a pinch and double tap gesture recognisers later - and scale the UIImageView in them as well).
UPDATE:
I've tried following Andrei's suggestion (thanks!) by adding the following code to the viewDidLayoutSubviews, but the image hasn't scaled down:
if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
_scrollView.maximumZoomScale = 1.2;
_scrollView.minimumZoomScale = .8;
_scrollView.zoomScale = .8;
}
UIScrollView can handle the zooming for you, together with pinch gestures.
You just need to set the proper values in "minimumZoomScale" and "maximumZoomScale" properties, and it will let the user pinch between those limits.
You also need to implement the
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
method from UIScrollViewDelegate. It should just return the imageView.
You can also set the zoom level using the "zoomScale" property.
For double tapping you need to add your own double tap gesture recognizer to the scrollview and increase the zoom level when a double tap occurs.
Updated with delegate method and double tap gesture.
You must definitely read about AutoLayout. You cannot go changing frames and bounds if AutoLayout is turned on. You can of course turn it off for the whole Storyboard.
The solution to your problem are constraints. With them you define how your views are related, for example: how your UIScrollView is related to it's parent view and how UIImageView is related to your UIScrollView.
Read more about constraints on links below:
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/AutolayoutPG/Introduction/Introduction.html
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
While UIScrollView can handle zooming with pinching for you, you must implement correct delegate method: viewForZoomingInScrollView:. And of course you must set correct property values for minimumZoomScale and maximumZoomScale.
More information on the following links:
https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html
http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
Both sites have enough information and examples for you to be able to do this. First experiment with the code available on those sites and then post another more specific question, if you encounter a problem.
Related
I have a scrollview where I have added different views (like tutorial).
What I wanted to have is slider with below design where on scroll I will see previous tut on left side and next on right side.
For this what I have added is scrollview with paging enabled and adding UILabel (for now) in for loop. After adding label in scrollview below is what I had.
To see the data on the left & right, what I did is uncheck clip subviews from storyboard.
However what I noticed is I can scroll only in scrollview area and not outside.
Any idea how can I make UILabel make scrolling outside & inside scrollview.
As of now to make it working, what I have done is added swipe gesture on view and making scrolling programmatically. However what I was looking is if I scroll outside scrollview, it should scroll scrollview little too.
Phewww...
Finally I managed to make it done..
What I did is added one more scrollview (dummyScrollView) with full screen width above main scrollview (mainScrollView) (which I am using to show label).
Now I enabled paging for the dummyScrollView too and implement below where I am scrolling my mainScrollView based on the factor calculation for the dummyScrollView
#pragma mark - UIScrollView Delegate
- (void) scrollViewDidScroll:(UIScrollView *)sender
{
float myFactor = 0;
// 44232 is tag for new scrollview
if (sender.tag==44232) {
myFactor = mainScrollView.frame.size.width/duplicateSV.frame.size.width;
myFactor = duplicateSV.contentOffset.x*myFac;
CGRect mCC = CGRectMake(myFactor, 0, mainScrollView.frame.size.width, mainScrollView.frame.size.height);
[mainScrollView scrollRectToVisible:mCC animated:NO]; // NO is very important... YES will not work
}
// 44231 is main scrollview tag where I won't be doing anything...
if (sender.tag==44231) {
}
}
The scrollview shows a floorplan, and the UIView is a little green dot that shows the user's location on the floorplan. So I need to be able to zoom in, and have the green dot stay in the same spot on the floorplan. When I pan, the green dot moves correctly, but when I zoom, it moves away from where it should be.
Here is a screenshot of my storyboard. The small green square is the view that is a child of the Scrollview, and shows the user's location. I move it around programatically, but this is not causing the problem. http://i.imgur.com/TTRMXNS.png
Heres the code that puts the tilemap into the scrollview:
CCDirector* director = (CCDirector *)[self childViewControllers][0];
director.view.frame = CGRectMake(0, 0, floorplanWidth, floorplanHeight);
CGSize sizeOfScene = CGSizeMake(floorplanWidth, floorplanHeight);
float minimumScale = 1;//This is the minimum scale, set it to whatever you want. 1.0 = default
_sceneScrollView.maximumZoomScale = 4.0;
_sceneScrollView.minimumZoomScale = minimumScale;
_sceneScrollView.zoomScale = .1;
[_sceneScrollView setContentMode:UIViewContentModeScaleAspectFit];
[_sceneScrollView sizeToFit];
[_sceneScrollView setContentSize:sizeOfScene];
[_sceneScrollView addSubview:[director view]];
There's actually a lot of things wrong with what I see above that leads me to believe that you should probably look up more information regarding iOS and scrollviews. The first thing is that a scrollView has a contentSize that's either intrinsically determined via auto layout, or via code by setting the contentSize. In this case, your contentSize would be set via setting the image. The second thing to note is when you zoom in using a scrollView, you provide a view to zoom in on. This view and it's respective subviews will be zoomed in on. I see that your green dot is in the storyboard and is a direct subview inside the scrollview's contentView, this is incorrect. Your green dot will need to be either a subview of your own containerView with the UIImageView and your dot in it, or a subview of your UIImageView (which is sometimes wanky in the storyboard, you'll you'll want to add that in code). To note, UIImageViews have their own scale factor inside of them versus iOS's scale factor. So if you're attempting to dynamically mark anything in a UIImageView, keep that in mind.
My problem are:
I implement a UIScrollView (DrawView)to draw something on it(Task is ok).
I drag a ScrollView to ViewController using storyboard and assign DrawView class to it.
I using pink gesture to zoom one element in DrawView, it is correct, but when element out of size DrawView i cant scroll it to see part of element.
In file ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.drawingView setScrollEnabled:YES];
[self.drawingView setContentSize:CGSizeMake(100, 200)];
}
Can you give me way to solution problem or some tutorial same?
Thank for all
Sorry for bad grammar
Set content size of the scrollView as the size of the element which you are adding to it.
Say elementView is the view that you are adding to scroll view then,
[self.drawingView setContentSize:elementView.size];
According to your comment, drawingview size is 700x900 which is less than your content size 100 x 200. That's why, it couldn't get scroll. Content size should be greater than size, then only it will get scroll even scrolling enabled.
I have tried several different solutions to this problem with no success.
I have a UIImageView (created on the Storyboard) that has multiple Gesture Recognizers on it. I have trying to resize this UIImageView based on screen size to take advantage of the 4 inch display.
It appears that since the Imageview was built using the storyboard, I can't change it programmatically???
My current code looks like this:
//determine screen size, set scoring button width based on device size.
CGFloat lCurrentHeight = self.view.bounds.size.height;
if (lCurrentHeight == 568.0) {
CGRect _redHeadImageFrame = _redHeadImage.frame;
_redHeadImageFrame.size.width = 220;
[_redHeadImage setFrame:_redHeadImageFrame];
}
Any ideas??? Thanks.
If you are using autolayout you have to change withConstraint of the image, because manual changing of the frame will not work in this case.
EDIT
You can create IBOutlet for the width constraint as you do it for other controls - just select constraint in IB and move it with right button to your header file. Than in code change constraint:
[self.imageWidthConstraint setConstant:100.0];
yes you need to use like this,
CGFloat lCurrentHeight = [[UIScreen mainScreen] bounds].size.height; //it will give 568
CGFloat lCurrentHeight = self.view.bounds.size.height;//it will give 548,in your case that condition failed.
There's no difference in resizing UIViews created by code or by the storyboard. It's exactly the same: setting the frame of the view, as you are doing.
What might be happening:
Your if condition it's never true. Have you checked with a breakpoint if the code inside it is even called? Maybe there's some error in the float direct comparation. See this.
Also, see this for a better understanding on how to check if it's 4 inch display.
If the setFrame: code is actually called, check if you are using auto-layout in your view. Maybe there's a constraint in the UIImageView. In this case, you should play with this constraint, in order to resize the view correctly..
So a little explanations of what my view is doing before the problem, the page loads a bunch of buttons that are clickable into the contentView which is a subView of my scrollView.
i got a UIViewController, inside i have my
UIScrollView scrollView to handle the scrolling and zooming
UIView contentView which i add all the UIButtons to.
Alright i'll try to only put the code which i believe might need to be changed.
in viewDidLoad
scrollView.contentSize = CGSizeMake(320, (20+totalRows*OFFSET_Y) );
[scrollView setMaximumZoomScale:4];
[scrollView setMinimumZoomScale:1];
[scrollView setDelegate:self];
[contentView setFrame:CGRectMake(0, 0, 320, (20+totalRows*OFFSET_Y) )];
[self.scrollView addSubview:contentView];
Doing some calculation to see how big i need to content size to be to fit all the buttons, then i add the contentView as subView to my scrollView.
I then add all the UIButtons as subview of my contentView
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [self contentView];
}
Got my delegate method for zooming returning the contentView.
Ok so everything is scrollable and zoomable like it should be..all my UIButtons are still clickable and works how it should be.
The problem is after i zoom in/out when i scroll all the way to the bottom of my scrollView it's being cut off from the bottom, so the last row of buttons are being cut in half. even when i rezoom to 1:1 it's still cut off.
I've got a NavigationController in the app which is 44 pixels, not sure if that's screwing something up somehow.
I was checking the contentSize of the scrollView and contentView and before any zooming is done, the Height of my scrollView is 44 pixels bigger than the contentView, but after any zooming the ratio is 1:1 and that seems to be the problem.
I'm not changing the size anywhere in the code though.
Any help is appreciated!
Thanks
Like i thought before I added this piece of code
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale (float)scale
{
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, self.scrollView.contentSize.height + (44 * scale));
}
And now Zooming doesn't cut anything off and seems to be working correctly.
I still don't believe this is what I should have to do but I guess it works for now.
Still hoping someone has a better answer!
After playing more with my app I realized that the zooming was never the problem to begin with. The actual problem was with my UIView *contentView. After changing the background colour of my scrollView and my contentView (to 2 very diff colours) I noticed that my contentView wasn't long enough to cover all of the buttons.
So at first load the scrollView was big enough to see everything but once you zoom and it takes the size of the contentView it wasn't being adjusted properly!
All that to say, it finally works how it should!..haha no replies but hopefully someone might find this useful! Best tip was to change the background colours.
Good Day,
I realize very late to the game, but wanted to updated what i found on this, should anyone else come across this issue.
All did was set BOTH the UIImageView and the UIScrollView to "Aspect Fit" and this fixed the issue for me. This may be an Xcode 7 feature, but it works.