How to stop UIScrollView when leave touch - objective-c

I made UIScrollView with some UIButton inside. The problem is that when I scroll down at the end of view, it return on start. What can i do? I use this in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad]; // step 3
scroll.scrollEnabled=YES;
scroll.contentSize = [self.view sizeThatFits:CGSizeZero];
}

According to Apple Documentation: sizeThatFits returns the size portion of the view’s bounds rectangle.
So your scroll view content size is of the same size of the UIView, thats why the scroll view returns to its original position. You need to set the height of the content size to the total height of your entire content in the scroll view. Normally this is bigger, because otherwise it won't make sense to use a UIViewController.
So, use something like this and it should work:
- (void)viewDidLoad
{
[super viewDidLoad]; // step 3
scroll.scrollEnabled=YES;
CGSize scrollViewSize = [self.view sizeThatFits:CGSizeZero];
scrollViewSize.height = 800.0; // Set here the height of the total area of your ScrollView. Should be bigger than the visible area.
scroll.contentSize = scrollViewSize;
}

Related

ScrollView with multiple pages

Normally, tutorials of UIScrollView talk about multiple pages with the size of the screen.
Beginning with the first page in the screen and the second page appearing a little in the right side:
And when scrolled, the same thing occurs with the second page: the first and the third page appears in the left/right side.
This scrollView is "implementable"? There's a way to use pages but with not entire screen width?
Yes you can do that, just change the size of your scroll view to your desired size,
Content Size as (numberOfPages * width) of your scrollview
Also enable pagination
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGSizeMake(numberOfPages * scrollView.frame.size.width, 1);
For more idea, refer to this sample project, just change scrollview size in xib :)
Hope it helps :)
try setting your scroll view content size
scrollView.contentSize = CGSizeMake(W, 1);
remember that "W" has to be a number greater then your scroll view's width in order to scroll horizontal. 1 is where you set the hight of your content size, if you'd like it to scroll vertically you'd make the "1" greater then your scrollview's hight.
You need to implement a scroll view container (e.g. ScrollViewContainer) to handle -hitTest:withEvent: method:
ScrollViewContainer.h:
#interface BookAlbumScrollViewContainer : UIView {
UIScrollView * theScrollView_;
}
#property (nonatomic, retain) UIScrollView * theScrollView;
#end
ScrollViewContainer.m:
#implementation BookAlbumScrollViewContainer
#synthesize theScrollView = theScrollView_;
//...
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView * child = [super hitTest:point withEvent:event];
if (child == self)
return self.theScrollView;
return child;
}
#end
HERE is a related QA on -hitTest:withEvent: method.
When you set your scroll view, set it like:
CGFloat yourScrollViewPageWidth = 280.f;
CGRect yourScrollViewFrame = CGRectMake((320.f - yourScrollViewPageWidth) / 2.f, 0.f, yourScrollViewPageWidth, 200.f);
CGRect theScrollViewContainerFrame = CGRectMake(0.f, 0.f, 320.f, 200.f);
// Your scroll view
yourScrollView_ = [[UIScrollView alloc] initWithFrame:yourScrollViewFrame];
//...
[self.view addSubview:bookScrollView_];
// Your scroll view container to handle touches, it should be over |yourScrollView_|
theScrollViewContainer_ = [ScrollViewContainer alloc];
[theScrollViewContainer_ initWithFrame:theScrollViewContainerFrame];
[theScrollViewContainer_ setBookAlbumScrollView:yourScrollView_];
[self.view theScrollViewContainer_];

setting view boundaries

I have a scrollview with an image as a subview. I would like to set the boundaries of the scrollview to be the size of the image view, so that you wouldn't be able to see any of the background.
I don't want this happening anymore.
The weird part is, that after you zoom in or out on the image, then the boundaries seem to fix themselves, and you can no longer move the image out of the way and see the background.
This is what I have going for code:
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView
{
// return which subview we want to zoom
return self.imageView;
}
-(void)viewDidLoad{
[super viewDidLoad];
[self sendLogMessage:#"Second View Controller Loaded"];
//sets the initial view to scale to fit the screen
self.imageView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));
//sets the content size to be the size our our whole frame
self.scrollView.contentSize = self.imageView.image.size;
//setes the scrollview's delegate to itself
self.scrollView.delegate = self;
//sets the maximum zoom to 2.0, meaning that the picture can only become a maximum of twice as big
[self.scrollView setMaximumZoomScale : 2.5];
//sets the minimum zoom to 1.0 so that the scrollview can never be smaller than the image (no matter how far in/out we're zoomed)
[self.scrollView setMinimumZoomScale : 1.0];
[imageView addSubview:button];
}
I thought that this line would solve my problem
//sets the content size to be the size our our whole frame
self.scrollView.contentSize = self.imageView.image.size;
But like I said, it only works after I zoom in or out.
EDIT: When I switch
self.scrollView.contentSize = self.imageView.image.size;
to
self.scrollView.frame = self.imageView.frame;
It works like I want it to (you can't see the background), except the toolbar on the top is covered by the image.
imageView.image.size isn't necessarily the frame of the imageView itself, try setting the
scrollview.frame = imageView.frame
and then
scrollView.contentSize = imageView.image.size
Then you won't see any border. If you want the image to be the maximum size to start with,
do
imageView.frame = image.size;
[imageView setImage:image];
scrollView.frame = self.view.frame; //or desired size
[scrollView addSubView:imageView];
[scrollView setContentSize:image.size]; //or imageView.frame.size
To fix this, I ended up declaring a new CGRect , setting its origin to my scrollView's origin, setting its size with the bounds of my view, and then assigning this CGRect back to my scrollview frame
CGRect scrollFrame;
scrollFrame.origin = self.scrollView.frame.origin;
scrollFrame.size = CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));
self.scrollView.frame = scrollFrame;

iPhone ScrollView in Tab Bar Controller - ScrollView doesn't scroll. Can someone help?

I'm trying to add a ScrollView to a Tab Bar Controller. Problem is the ScrollView won't scroll, and I can't for the life of me find out why on Google. If I replace the ScrollView with a TextView, that one scrolls, and so does a TableView.
You can get the code demonstrating this from here: git://gitorious.org/scrollview-in-tabbar-project/scrollview-in-tabbar-project.git
Can anyone tell me what I'm doing wrong? Please notice that, annoyingly, the TextView that is inside the ScrollView scrolls. Not sure if this is related, but I don't get a viewWillAppear call when I select the ScrollView's tab.
You haven't set the contentSize of your scrollview. You are responsible to set the contentSize property. In your case, you can add this to viewDidLoad in your SecondViewController:
-(void)viewDidLoad {
[super viewDidLoad];
UIScrollView *scrollView = (UIScrollView *)self.view;
scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 1024);
}
Set the height of the contentSize to what ever fits your needs (possibly you have to calculate the height to fit what you are putting in the scrollview).
Here's an example from the Apple documentation: Creating Scroll Views in Interface Builder
Based on Erik Tjernlund's answer, my code now looks like this:
- (void) viewDidLoad
{
[super viewDidLoad];
CGFloat maxDepth = 0;
for (int i = 0; i < scrollView.subviews.count; i++)
{
UIView *aSubview = (UIView *) [scrollView.subviews objectAtIndex:i];
CGFloat depth = aSubview.frame.origin.y + aSubview.frame.size.height;
if (depth > maxDepth)
maxDepth = depth;
}
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, maxDepth);
}
and right now it looks like it satisfies my needs. It's also probably not 100% correct, and I'll find that out as I go deeper.

Custom NSWindow content margin causes mess up with autoresizing mask

I'm currently using the method shown in this Cocoa with Love article to create a custom NSWindow subclass. As in the example, I needed to have a roughly 10px margin around the content of the window in order to draw an arrow (I'm creating a popover style window). I had to have the margin around the entire window instead of just the side with the arrow on it because I wanted to be able to change the arrow position without having to reposition the content.
To summarize, the method I'm using to do this is (relevant code is at the bottom):
Override the contentRectForFrameRect: and frameRectForContentRect:styleMask: methods of NSWindow to add the padding around the content:
Sets the custom drawn frame view of the window as the contentView and then overrides the setter and getter for the contentView so that the view that is passed in is added as a subview of the frame view.
The problem is that the autoresizing masks of views inside the actual content view of the window are completely messed up. Here is how I'm setting up the content in interface builder:
Here's how the autoresizing mask of the table view scroll view is set up:
And here's how the text label's autoresizing mask is set:
And here's what the result looks like in-app:
Relevant code (derived from the aforementioned article)
#define CONTENT_MARGIN 10.0
- (NSRect)contentRectForFrameRect:(NSRect)windowFrame
{
windowFrame.origin = NSZeroPoint;
return NSInsetRect(windowFrame, CONTENT_MARGIN, ICONTENT_MARGIN);
}
- (NSRect)frameRectForContentRect:(NSRect)contentRect
{
return NSInsetRect(contentRect, -CONTENT_MARGINT, -CONTENT_MARGIN);
}
+ (NSRect)frameRectForContentRect:(NSRect)contentRect
styleMask:(NSUInteger)windowStyle
{
return NSInsetRect(contentRect, -CONTENT_MARGIN, -CONTENT_MARGIN);
}
- (NSView*)contentView
{
return _popoverContentView;
}
- (void)setContentView:(NSView *)aView
{
if ([_popoverContentView isEqualTo:aView]) { return; }
NSRect bounds = [self frame];
bounds.origin = NSZeroPoint;
SearchPopoverWindowFrame *frameView = [super contentView];
if (!frameView) {
frameView = [[[SearchPopoverWindowFrame alloc] initWithFrame:bounds] autorelease];
[super setContentView:frameView];
}
if (_popoverContentView) {
[_popoverContentView removeFromSuperview];
}
_popoverContentView = aView;
[_popoverContentView setFrame:[self contentRectForFrameRect:bounds]];
[_popoverContentView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[frameView addSubview:_popoverContentView];
}
I thought that maybe the popover content was going over the margins somehow, so I drew a border around the content view, but no, everything is as should be. The only issue is that the autoresizing masks of the label and table view inside the content view do not work as they should. Any advice is greatly appreciated.
EDIT: If anyone's interested, I've open-sourced the complete code for this popover window/controller on github as INPopoverController. Includes a sample project in case you want to try and reproduce the issue.
-( void )scaleWindowForHeight:( float )height
{
if (height > 22)
{
NSWindow* window = [self window];
NSRect old_window_frame = [window frame];
NSRect old_content_rect = [window contentRectForFrameRect: old_window_frame];
NSSize new_content_size = NSMakeSize( old_window_frame.size.width, height );
// need to move window by Y-axis because NSWindow origin point is at lower side:
NSRect new_content_rect = NSMakeRect( NSMinX( old_content_rect ), NSMaxY( old_content_rect ) - new_content_size.height, new_content_size.width, new_content_size.height );
NSRect new_window_frame = [window frameRectForContentRect: new_content_rect];
[window setFrame: new_window_frame display:YES animate: [window isVisible] ];
}
else
NSLog(#"window size too small");
}

UIScrollView setZoomScale not working?

I am struggeling with my UIScrollview to get it to zoom-in the underlying UIImageView. In my view controller I set
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return myImageView;
}
In the viewDidLoad method I try to set the zoomScale to 2 as follows (note the UIImageView and Image is set in Interface Builder):
- (void)viewDidLoad {
[super viewDidLoad];
myScrollView.contentSize = CGSizeMake(myImageView.frame.size.width, myImageView.frame.size.height);
myScrollView.contentOffset = CGPointMake(941.0, 990.0);
myScrollView.minimumZoomScale = 0.1;
myScrollView.maximumZoomScale = 10.0;
myScrollView.zoomScale = 0.7;
myScrollView.clipsToBounds = YES;
myScrollView.delegate = self;
NSLog(#"zoomScale: %.1f, minZoolScale: %.3f", myScrollView.zoomScale, myScrollView.minimumZoomScale);
}
I tried a few variations of this, but the NSLog always shows a zoomScale of 1.0.
Any ideas where I screw this one up?
I finally got this to work. what caused the problem was the delegate call being at the end. I now moved it up and .... here we go.
New code looks like this:
- (void)viewDidLoad {
[super viewDidLoad];
myScrollView.delegate = self;
myScrollView.contentSize = CGSizeMake(myImageView.frame.size.width, myImageView.frame.size.height);
myScrollView.contentOffset = CGPointMake(941.0, 990.0);
myScrollView.minimumZoomScale = 0.1;
myScrollView.maximumZoomScale = 10.0;
myScrollView.zoomScale = 0.7;
myScrollView.clipsToBounds = YES;
}
Here is another example I made. This one is using an image that is included in the resource folder. Compared to the one you have this one adds the UIImageView to the view as a subview and then changes the zoom to the whole view.
-(void)viewDidLoad{
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"random.jpg"];
imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
[(UIScrollView *) self.view setContentSize:[image size]];
[(UIScrollView *) self.view setMaximumZoomScale:2.0];
[(UIScrollView *) self.view setMinimumZoomScale:0.5];
}
I know this is quite late as answers go, but the problem is that your code calls zoomScale before it sets the delegate. You are right the other things in there don't require the delegate, but zoomScale does because it has to be able to call back when the zoom is complete. At least that's how I think it works.
My code must be completely crazy because the scale that I use is completely opposite to what tutorials and others are doing. For me, minScale = 1 which indicates that the image is fully zoomed out and fits the UIImageView that contains it.
Here's my code:
[self.imageView setImage:image];
// Makes the content size the same size as the imageView size.
// Since the image size and the scroll view size should be the same, the scroll view shouldn't scroll, only bounce.
self.scrollView.contentSize = self.imageView.frame.size;
// despite what tutorials say, the scale actually goes from one (image sized to fit screen) to max (image at actual resolution)
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat minScale = 1;
// max is calculated by finding the max ratio factor of the image size to the scroll view size (which will change based on the device)
CGFloat scaleWidth = image.size.width / scrollViewFrame.size.width;
CGFloat scaleHeight = image.size.height / scrollViewFrame.size.height;
self.scrollView.maximumZoomScale = MAX(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
// ensure we are zoomed out fully
self.scrollView.zoomScale = minScale;
This works as I expect. When I load the image into the UIImageView, it is fully zoomed out. I can then zoom in and then I can pan the image.