I am running into a problem with the uiscrollview. When I have it as a regular scroll view all the UIButtons work as expected. When I add paging to it the buttons no longer respond. I have a top edge sticking out and they do accept the press from there. They are definitely behind the scroll view but they will scroll on and off the page when it is moved like I want them to. I have read a lot of different responses but most will not provide the answer unless you use gesture controllers. I am attaching the piece of code that creates the paging. can you let me know what I might be missing?
-(void)scollPagingSetup:(float)frameSize {
float numberOfPages;
int maxheight;
[self.view setPagingEnabled:YES];
[self.view setBounces:YES];
UIView *first = [[UIView alloc]initWithFrame:self.view.frame];
[self.view addSubview:first];
maxheight = [UIScreen mainScreen].bounds.size.height;
numberOfPages = ceil(frameSize/maxheight);
for (int i = 1; i < numberOfPages; i++) {
CGRect frame;
frame.origin.x = 0;
frame.origin.y = self.view.frame.size.height * i;
frame.size = self.view.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[self.view addSubview:subview];
}
self.view.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height *numberOfPages);
}
Thank you in advance for taking a look. I found something that would answer this problem but I was unable to grasp what the real solutions was to the problem. here is the link to that question:
IPhone UIButton doesn't respond in a UIScrollView
The problem is that the content size is not set properly so the "clickable area" (content area's size) is also not set... on your last line of code (line before the last "}") you are setting the scrollView's contentSize's frame to itself which will just be 0... try this instead (I use "first" (the nested view) instead of "self" (the scroll-view itself).
self.view.contentSize = CGSizeMake(firstframe.origin.x, (firstframe.origin.y - 20) * numberOfPages);
Note from question-poster on edited answer:
I made a change to the answer. After I worked with the app some more i was not scrolling fully. I made the change to reflect what I did to fix this and cause a full page scroll. the -20 offset was needed due to the offset of the uiscrollview. This offset can be seen in interface builder.
Related
I recently switched from flash/flex development to IOS apps. The one thing I'm still struggling with is getting my UI components arranged the way I want them. I've tried using AutoLayout with constraints, but it feels really cumbersome, especially when there are a large number of components to arrange. What I want is something like the flex 'Form' and FormItem' components that provide a clean arrangement of labeled inputs. Can anyone point me to an equivalent solution for IOS?
I think I found what I was looking for here: XLForm
It isn't a perfect solution but I suspect it is as close as I'm going to get.
I'm not sure what you exactly want, since I do not have any experience with Flex.
If you want a UIView to clip to its subviews you can use:
[view sizeToFit];
Or if you want to control your frame via code, you have to disable auto layout in the storyboard. After that you can alter any UIView's properties e.g.:
UIView * view = [[UIView alloc] init];
CGRect newFrame = view.frame;
newFrame.size.height = 100;
newFrame.size.width = 100;
newFrame.origin.x = 50;
newFrame.origin.y = 100;
view.frame = newFrame;
or:
UIView * view = [[UIView alloc] init];
CGRect newFrame = view.frame;
newFrame.size = CGSeize(100,100)
newFrame.origin = CGPoint(0,0)
view.frame = newFrame;
I have a pageable UIScrollView which contains different kind of informations like UITables but also zoomable images. Therefore I set up a pageable main-ScrollView and as subviews I added zoomable image-ScrollViews with the images as content.
Works everything fine, just I fail to set the smaller current zoom scale of the imageScrollViews.
UIImageView *imageView = [[UIImageView alloc] initWithImage:Image];
//storing a link to the imageView
[imagelinkArray addObject:imageView];
CGRect ScrollViewImageRect;
ScrollViewImageRect = CGRectMake((self.scrollView.frame.size.width) * i, 0, 320, self.scrollView.frame.size.height);
float widthfactor = ScrollViewImageRect.size.width / imageView.frame.size.width;
float heightfactor = ScrollViewImageRect.size.height / imageView.frame.size.height;
float zoomscale = MIN(widthfactor, heightfactor);
UIScrollView *imageScrollView = [[UIScrollView alloc] initWithFrame:ScrollViewImageRect];
imageScrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
imageScrollView.delegate = self;
[imageScrollView setMinimumZoomScale:zoomscale];
[imageScrollView setMaximumZoomScale:1.5];
[imageScrollView addSubview:imageView];
//doesn't work:
[imageScrollView setZoomScale:0.5 animated:YES];
[self.scrollView addSubview:imageScrollView];
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [imagelinkArray objectAtIndex:page];
}
The main-ScrollView and the image-ScrollViews are drawn perfectly and it's possible to zoom and page properly. The minimum zoom factor is calculated also correct. When I zoom out I can zoom until the image limits are reached. However the first time I page to the image-ScrollView it's current zoom scale is always 1.0 while it should be the minimum scale.
Wherever I set the zoom scale in the code above it doesn't work:
[changeScrollView setZoomScale:changeScrollView.minimumZoomScale animated:YES];
If I log the current zoom scale i always get 1.0;
The only thing which works is changing the zoom scale in the - (void)scrollViewDidScroll: method, which of course doesn't help a lot since zooming also calls it which resets the zoom immediately. But at least I could figure out, that the code somehow works. I have the feeling a UIScrollView doesn't zoom when it's not visible on the screen right now. How can I fix this?
Update:
Okay. In the meantime I figured out that the problem most likely comes from my base layout of "sub-viewing" ScrollViews into another ScrollView. When I zoom one of the images and log the current zoom factor of the ScrollViews they are all the same (main ScrollView as well as ALL sub-ScrollViews).
What could be the reason for it or how could I solve it with a different layout?
I think viewForZoomingInScrollView: may not be getting called by the scrollview. Try to add a breakpoint and check what you're returning there.
Your code doesn't work because you havent set minimumZoomScale ,which has default value of 1.0 . Since you are trying to set 0.5 which is below the default value, it wouldn't work.
Add following line just after the line which sets maximumZoomScale.
[imageScrollView setMinimumZoomScale:0.25];
As user Rivera pointed out the return value of viewForZoomingInScrollView: was off course not right.
I always returned the current visible page shown in the scrollView. Which means setting the zoom in viewDidAppear doesn't change anything.
Here is the correct code: I made a function which will always resets both images left and right of the current visible scroll page:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self updateImageSize];
}
- (void)updateImageSize
{
updatePage = updatePage + 1;
if (updatePage < imagescrolllinkArray.count) {
UIScrollView *changeScrollView = (UIScrollView*)[imagescrolllinkArray objectAtIndex:updatePage];
[changeScrollView setZoomScale:changeScrollView.minimumZoomScale];
}
updatePage = updatePage - 2;
if (updatePage > -1) {
UIScrollView *changeScrollView = (UIScrollView*)[imagescrolllinkArray objectAtIndex:updatePage];
[changeScrollView setZoomScale:changeScrollView.minimumZoomScale];
}
//reset to current view
updatePage = updatePage + 1;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return [imagelinkArray objectAtIndex:updatePage];
}
and in viewDidAppear I added the following to update the first image before any dragging.
if (i == 1) {
updatePage = 0;
[imageScrollView setZoomScale:imageScrollView.minimumZoomScale];
}
In the meantime I figured out that the code below can under certain circumstances make problems. Sometimes when I zoom in and out from an image the main ScrollView can't be scrolled anymore, so there is no way to get to the next image, except of triggering the pageControl or except of zooming into the image and then scrolling to its borders so the main ScrollView jumps to the next page.
Means the problem only occurs when the image is fully zoomed out (.scale = .minimumscale). I don't understand exactly when and why it happens. Logging viewDidScroll returns nothing in this situations.
Anybody experienced similar problems?
I design the scrollview in interface builder like this
It looks good here. But unfortunately when I run it on emulator or device
it becomes
The content in scrollview is expand outside scrollview itself and even though outside UIView that contains this scrollView.
In my viewDidLoad (panel is the container of scrollView )
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat adjustPanelHeight = [PTTScreenScaleUtil getAdjustHeight:self.panel.frame.size.height];
CGRect panelRect = self.panel.frame;
panelRect.size.height = adjustPanelHeight;
self.panel.frame = panelRect;
UIImage *image = [UIImage imageNamed:#"panel-background"];
UIGraphicsBeginImageContext(self.panel.frame.size);
[image drawInRect:CGRectMake(0, 0, self.panel.frame.size.width, adjustPanelHeight)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.panel setBackgroundColor:[UIColor colorWithPatternImage:newImage]];
NSLog(#"scrollView Height : %f", self.scrollView.frame.size.height);
NSLog(#"scrollView contentSize Height : %f", self.scrollView.contentSize.height);
// CGRect scrollViewRect = self.scrollView.frame;
// CGRect scrollViewContentRect = self.scrollView.frame;
// NSLog(#"ScrollView Height Before : %f , After : %f", self.scrollView.frame.size.height, [PTTScreenScaleUtil getAdjustHeight:self.scrollView.frame.size.height]);
// scrollViewRect.size.width = 280;
// scrollViewRect.size.height = [PTTScreenScaleUtil getAdjustHeight:270];
// self.scrollView.frame = scrollViewRect;
// [self.detailsLabel sizeToFit];
UIView *view = [[self.scrollView subviews] objectAtIndex:0];
// [view sizeToFit];
// [self.scrollView setContentMode:UIViewContentModeScaleAspectFit];
// NSLog(#"ContentSize Height : %f", view.frame.size.height);
// scrollViewContentRect.size.height = view.frame.size.height;
NSLog(#"Bounds : %f", view.bounds.size.height);
self.scrollView.frame = CGRectMake(10, 10, 280, 270);
self.scrollView.contentSize = CGSizeMake(280, 500);
NSLog(#"Frame Height %f", self.scrollView.frame.size.height);
//[self.scrollView setContentSize: CGSizeMake(280, 1000)];
CGRect termBtnRect = self.termBtn.frame;
CGRect mailBtnRect = self.mailBtn.frame;
CGRect twitterBtnRect = self.twitterBtn.frame;
CGRect fbBtnRect = self.fbBtn.frame;
termBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
mailBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
twitterBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
fbBtnRect.origin.y = adjustPanelHeight - 10 - termBtnRect.size.height;
self.termBtn.frame = termBtnRect;
self.mailBtn.frame = mailBtnRect;
self.twitterBtn.frame = twitterBtnRect;
self.fbBtn.frame = fbBtnRect;
}
All the log return 270.0
PS. the scroll bar is correct even though the content goes outside but the scroll bar is working correctly (stay in the scrollview's frame as arrange in interface builder)
I have no idea how can I solve this.
Anyone help me please.
Thanks you.
Solve it by creating new view controller in interface builder and redo the same process with careful and bingo. It works.
When I compare both two view controller I realise that the wrong one UIScrollView Clip Subviews is unchecked. When check it the problem solve.
I just struggled with this for an hour and had a head smack moment.
In my case, I had a UIView on the scene in the Storyboard. At some point I decided I needed it to be a UIScrollView instead (as opposed to the original plan which was to embed the UIScrollView in a UIView)
I went ahead and changed the class on the UIView to UIScrollView. IB changed it to Scroll View in the Document Outline, I figure I'm good, right?
And then I see the behavior you describe.
At some point it hits me that this isn't sufficient. Apparently adding a UIScrollView via IB does some things differently than adding a UIView and just changing class isn't enough. And this is probably the reason re-doing it from scratch fixed it for you.
So for anyone who runs into this in the future, make sure you added the UIScrollView via IB instead of a UIView
I was having the same problem as described in this post. I tried multiple combinations of solutions that did not work, including:
putting the scroll view inside a view with Clip To Bounds = YES
putting a view inside the scroll view with Clip To Bounds = YES, that then contained my child view
putting a Container View inside the scroll view, and then embedding my subview
rebuilding the Interface Builder files completely
every combination of autosizing mask options systematcially for both the scroll view and container view
clip to bounds enabled or disabled for every single element systematically
The child view in question had previously worked inside a scroll view, but wouldn't in this one case where the content blew outside the bounds of the scroll view.
In the end, I implemented the solution in code as I could find no way to get Interface Builder to co-operate:
// There are two scroll areas on the screen, the left view and the right view.
// We want the right view to contain a scrollable area with another child view controller
// we designed in Interface Builder.
// create a scroll view to fill the right view with a scrollable area
CGSize rightFrameSize = self.rightView.bounds.size;
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake (0, 0, rightFrameSize.width, rightFrameSize.height)];
scrollView.contentSize = CGSizeMake(640, 1352);
[self.rightView addSubview:scrollView];
// now create our child view controller from Interface Builder and add it to the scroll view
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"CustomerAddress" bundle:[NSBundle mainBundle]];
detailsView = [sb instantiateViewControllerWithIdentifier:#"CustomerDetailsView"];
detailsView.delegate = self;
detailsView.customer = _customer;
[scrollView addSubview:detailsView.view];
You could of course get the scrollView.contentSize from the child view controller you constructed in Interface Builder using scrollView.contentSize = detailsView.view.frame.size.
I have a love/hate relationship with Interface Builder... most days I love it, but some days we argue and I wish we'd never met... :)
only make cliptobound=YES in storyboard if you changed UIView to UIScrollView
So I have a UIScrollView and within that, I'd like to add some subviews, currently I have around 5 or 6, they are about 90px in height, so obviously when it gets to the bottom of the screen, I'd like it to scroll so you can see more, if that makes sense.
Below is what I have already, parentView being the UIScrollView, newResult being a row I'd like to append. GSResultBlock is a class that extends UIView.
for (NSObject * person in resultsCollection) {
CGRect resultBlockFrame = CGRectMake(0, resultCount, parentView.bounds.size.width, 90);
GSResultBlock * newResult = [[GSResultBlock alloc] initWithFrame:resultBlockFrame];
[parentView addSubview:[newResult getResultBlock]];
[newResult release];
resultCount = resultCount + 95;
}
Keep in mind that foreach newResult there will be additional subviews in there also, for example, a UIImageView ect.. (They are not included in the code above though)
Any ideas? Thanks in advance.
You need to update the contentSize of the UIScrollView using something like:
[parentView setContentSize:CGSizeMake(CGRectGetWidth(parentView.frame), resultCount)];
after the end of your for loop.
have a look at this answer
float maxHeight = 0;
for(UIView *v in [scrollView subviews]){
if(v.frame.origin.x + v.frame.size.height > maxHeight)
maxHeight = v.frame.origin.x + v.frame.size.height;
}
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, maxHeight+5);
once you have put all your views into the scroll view, run this and it will make your scrollview scroll the right amount
I want to use a UIScrollView as my main container in the app, enabling me to swipe back and forth between subviews. To achieve this, I created a UIViewController subclass with a UIScrollView IBOutlet:
In the viewDidLoad method I construct the sub-pages:
for (int i= 0; i< pageCount; i++)
{
CGRect frame = self.scrollView.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
UIWebView* aWebView= [[UIWebView alloc] initWithFrame:frame];
[self.scrollView addSubview:aWebView];
}
When launching the app (portrait mode), everything works. That is, the UIWebViews are layed out side by side with the correct dimensions, and I can swipe back and forth between them.
When I rotate to landscape, it seems that neither the scrollview size nor the subviews are resized.
I don't know what I should do in order to resize the subviews and the scrollview itself, or at what point in code I should do anything, and I cant seem to find any examples for this.
Anyone know what to do?
[edit] Attempt to adjust sizes as suggested by mahboudz:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * pageCount, self.scrollView.frame.size.height);
for (int i= 0; i< pageCount; i++)
{
CGRect frame = self.scrollView.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
UIWebView* view= [[self.scrollView subviews] objectAtIndex:i];
view.frame= frame;
}
}
This kind of does what I want, but has the following issues:
1) one can see the subviews grow to correct screen size upon changing orientation
2) when the current page is, for example, page 2 of 5 pages, the page is not fully visible after orientation was changed, but is off-screen by like 40 pixels
3) I get strange effects depending on whether the app is launched in portrait or landscape mode (simulator), ill try to explain:
When the app is launched in portrait mode:
The shape/border of the subviews looks messed up/offscreen, see screenshots:
http://i53.tinypic.com/21jr76x.png
when I rotate to landscape, everything looks okay, scrolling works superb. even when I rotate back to portrait, everything is great now:
http://i55.tinypic.com/if3iiw.png
When the app is launchend in landscape mode:
I get the same messed up/offscreen glitches as in portrait mode
Switching back and forth between portrait and landscape fixes this for landscape mode
BUT: Portrait mode will have the subviews with the width of the landscape mode, thus subviews are too wide
I tried to fix 1) doing the code above in willRotateToInterfaceOrientation however it completely messed up the layout.
I fixed 2) by adding the following code to didRotateFromInterfaceOrientation:
// update the scroll view to the appropriate page
CGRect frame = self.scrollView.frame;
frame.origin.x = frame.size.width * self.currentPage;
frame.origin.y = 0;
[self.scrollView scrollRectToVisible:frame animated:NO];
Note: current page is determined in scrollViewDidScroll
I dont have any idea how to fix 3)
You would need to reset the frame size, content size and the content offset in order to get the subviews in a proper position.
CGFloat screenHeight =[UIScreen mainScreen].bounds.size.height;
CGFloat screenWidth =[UIScreen mainScreen].bounds.size.width;
self.scrollView.frame = CGRectMake(0, 0, screenWidth, screenHeight);
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * numberOfPages, self.scrollView.frame.size.height);
self.scrollView.contentOffset = CGPointMake(visiblePageBeforeRotation * self.scrollView.bounds.size.width, 0);
This code should be placed in the method
-(void)willRotateToInterfaceOrientation: (UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
Check as well the answer on this question:
Clean autorotation transitions in a paging UIScrollView
It has good example named Rotolling for rotating UIScrollView with paging enabled.
Hope this helps.
P.S: I am facing a problem on repositioning the center of the UIWebView on the rotation.
You need to implement viewWillRotate/viewDidRotate and make adjustments to our content size and orientation as needed.