I am trying to display 3 UIScrollViewControllers in the same window as 3 horizontal stripes 3 times the screen wide scrolling indipendently. The code to achieve this is below but for some reason it doesn't work, showing only the upper stripe.
With the help of the additional white background view I placed on the window I can see the other 2 regions of the screen are scrollable as well, but for some reason their background color is not showing up...I can't figure out why.
Here is the code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Creating the window programmatically
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CGRect bounds = [self window].bounds;
float x = bounds.origin.x;
float y = bounds.origin.y;
float w = bounds.size.width;
float h = bounds.size.height;
CGRect upperFrame = CGRectMake(x,y,w,h/3);
CGRect middleFrame = CGRectMake(x,y + h/3,w,h/3);
CGRect lowerFrame = CGRectMake(x, y + 2 * h/3, w, h/3);
// Creating the scroll view which will contain the 3 views
UIScrollView *upperScrollView = [[UIScrollView alloc] initWithFrame:upperFrame];
UIScrollView *middleScrollView = [[UIScrollView alloc] initWithFrame:middleFrame];
UIScrollView *lowerScrollView = [[UIScrollView alloc] initWithFrame:lowerFrame];
// ContentSize should be wide enough for 3 pages
[upperScrollView setContentSize:CGSizeMake(3 * w, h/3)];
[middleScrollView setContentSize:CGSizeMake(3 * w, h/3)];
[lowerScrollView setContentSize:CGSizeMake(3 * w, h/3)];
// Enforce the display of only one page at a time
[upperScrollView setPagingEnabled:YES];
[middleScrollView setPagingEnabled:YES];
[lowerScrollView setPagingEnabled:YES];
// UPPER SCROLLVIEW
// This will be the first view (red)
UIView *redViewU = [[UIView alloc] initWithFrame:upperFrame];
[redViewU setBackgroundColor:[UIColor redColor]];
// The second view will start horizontally when the first view ends
upperFrame.origin.x += w;
// This will be the second view (green)
UIView *greenViewU = [[UIView alloc] initWithFrame:upperFrame];
[greenViewU setBackgroundColor:[UIColor greenColor]];
// The third view will start horizontally when the second view ends
upperFrame.origin.x += w;
// This will be the third view (blue)
UIView *blueViewU = [[UIView alloc] initWithFrame:upperFrame];
[blueViewU setBackgroundColor:[UIColor blueColor]];
// Adding the 3 views to the scroll view
[upperScrollView addSubview:redViewU];
[upperScrollView addSubview:greenViewU];
[upperScrollView addSubview:blueViewU];
// Now creating the view controller, father of the scrollview
UIViewController *upperViewController = [[UIViewController alloc] init];
[upperViewController setView:upperScrollView];
// MIDDLE SCROLLVIEW
// This will be the first view (red)
UIView *redViewM = [[UIView alloc] initWithFrame:middleFrame];
[redViewM setBackgroundColor:[UIColor redColor]];
// The second view will start horizontally when the first view ends
middleFrame.origin.x += w;
// This will be the second view (green)
UIView *greenViewM = [[UIView alloc] initWithFrame:middleFrame];
[greenViewM setBackgroundColor:[UIColor greenColor]];
// The third view will start horizontally when the second view ends
middleFrame.origin.x += w;
// This will be the third view (blue)
UIView *blueViewM = [[UIView alloc] initWithFrame:middleFrame];
[blueViewM setBackgroundColor:[UIColor blueColor]];
// Adding the 3 views to the scroll view
[middleScrollView addSubview:redViewM];
[middleScrollView addSubview:greenViewM];
[middleScrollView addSubview:blueViewM];
// Now creating the view controller, father of the scrollview
UIViewController *middleViewController = [[UIViewController alloc] init];
[middleViewController setView:middleScrollView];
// LOWER SCROLLVIEW
// This will be the first view (red)
UIView *redViewL = [[UIView alloc] initWithFrame:lowerFrame];
[redViewL setBackgroundColor:[UIColor redColor]];
// The second view will start horizontally when the first view ends
lowerFrame.origin.x += w;
// This will be the second view (green)
UIView *greenViewL = [[UIView alloc] initWithFrame:lowerFrame];
[greenViewL setBackgroundColor:[UIColor greenColor]];
// The third view will start horizontally when the second view ends
lowerFrame.origin.x += w;
// This will be the third view (blue)
UIView *blueViewL = [[UIView alloc] initWithFrame:lowerFrame];
[blueViewL setBackgroundColor:[UIColor blueColor]];
// Adding the 3 views to the scroll view
[lowerScrollView addSubview:redViewL];
[lowerScrollView addSubview:greenViewL];
[lowerScrollView addSubview:blueViewL];
// Now creating the view controller, father of the scrollview
UIViewController *lowerViewController = [[UIViewController alloc] init];
[lowerViewController setView:lowerScrollView];
// A white background view to see at least the scroll indicators
UIView *whiteView = [[UIView alloc] initWithFrame:bounds];
[whiteView setBackgroundColor:[UIColor whiteColor]];
// Finally the window will hold the view controllers' views
[[self window] addSubview:whiteView];
[[self window] addSubview:upperViewController.view];
[[self window] addSubview:middleViewController.view];
[[self window] addSubview:lowerViewController.view];
// Displaying the window
[self.window makeKeyAndVisible];
return YES;
}
Solved: after succeeding doing the same thing with IB I realized that for some reason the views inside the UIScrollView want RELATIVE x,y coordinates for their frames, not ABSOLUTE.
Changing the frames of the views in the above code with the following (the same for every UIScrollView):
CGRect redViewFrame = CGRectMake(x,y,w,h/3);
CGRect greenViewFrame = CGRectMake(w,y,w,h/3);
CGRect blueViewFrame = CGRectMake(2 * w,y,w,h/3);
solved the issue, and now I can see the 3 scrolling backgrounds.
Hope it helps someone else :) I am done, for now.
Related
I've got a UIScrollView (A) parent on the screen, inside it's content I have two controls -
another UIScrollView (B) at the Top an an UIView (C) at the bottom,
A is full screen (460px)
B 460px but content is longer then the screen (600px) so it has it's scrolling inside
C 460px fixed
also paging is enabled so B is the 1st page and C is the 2nd,
When I pan down B is scrolling and when it reaches the bottom it's bounces instead of pulling view C, if I set the bounce to NO then it's stuck at the bottom and only if I raise the finger and pan again it pulls the view C..
I saw some related questions but non of them helped me (How to steal touches from UIScrollView?)
a code sample to recreate the situation
(or download from my dropbox https://www.dropbox.com/s/f9j0vkg902214ab/Test2.zip)
- (void)viewDidLoad{
[super viewDidLoad];
// create main scroll
UIScrollView *scrollA = [[UIScrollView alloc] initWithFrame:self.view.frame];
scrollA.pagingEnabled = YES;
scrollA.bounces = YES;
[self.view addSubview:scrollA];
// create top scroll B
UIScrollView *scrollB = [[UIScrollView alloc] initWithFrame:self.view.frame];
scrollB.backgroundColor = [UIColor greenColor];
scrollB.bounces = YES;
[scrollA addSubview:scrollB];
// create something to put in B
CGRect frameViewB = scrollB.frame;
frameViewB.origin.x = 30;
frameViewB.size.width = 260;
frameViewB.size.height = 600;
UIView *viewInsideB = [[UIView alloc] initWithFrame:frameViewB];
viewInsideB.backgroundColor = [UIColor blueColor];
[scrollB addSubview:viewInsideB];
[scrollB setContentSize:viewInsideB.frame.size];
// create bottom view
CGRect frameC = self.view.frame;
frameC.origin.y = 460;
UIView *viewC = [[UIView alloc] initWithFrame:frameC];
viewC.backgroundColor = [UIColor yellowColor];
[scrollA addSubview:viewC];
// set content for 2 pages
[scrollA setContentSize:CGSizeMake(320, 920)];}
Thanks
I have a UIViewController and a UIScrollView. Since I have to add multiple views to the view controller, and the scroll view is just one of them, I tried to set the view of the controller to an dummy UIView and the scroll as child, like this:
[self setView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]];
[[self view] setUserInteractionEnabled:NO];
// TDHexMapScrollView inherits from UIViewController
[self setHexMapScrollView:[[TDHexMapScrollView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]];
[[self view] addSubview:[self hexMapScrollView]];
This way the scrolling doesn't work. Adding it as the main view makes scrolling and panning work correctly:
[self setHexMapScrollView:[[TDHexMapScrollView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)]];
[self setView:[self hexMapScrollView]];
Any help? Thanks
Don't do this:
[[self view] setUserInteractionEnabled:NO];
That disables interaction for the view and all subviews. That means it ignores touch events and does not propagate them to its subviews, which means your scrollview doesn't get any events.
I didn't get reply on my comment, but I figured I would show you an example of how I go about doing this.
Declare
CGSize scrollSize;
In your implementation. Then create your scrollView, views, labels, etc.
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, screenFrame.size.width, screenFrame.size.height - self.tabBarController.tabBar.frame.size.height - self.navigationController.navigationBar.frame.size.height)];
self.scrollView.scrollEnabled = YES;
scrollSize.height = self.View1.frame.size.height + self.Label1.frame.size.height + self.Label2.frame.size.height + self.Label3.frame.size.height + self.Label4.frame.size.height + self.Label5.frame.size.height + self.Label6.frame.size.height;
scrollSize.width = screenFrame.size.width;
[self.scrollView setContentSize:scrollSize];
Add to the scrollView
[self.scrollView addSubview:self.View1];
//Repeat for all views / labels / etc
Add the scrollView to the ViewController
[self.view addSubview:self.scrollView];
I'm trying to modify Apple's PhotoScroller example to make the scrollview that is created into a subview instead of it being a view that takes up the entire screen. Any ideas on how this can be accomplished?
- (void)loadView
{
// Step 1: make the outer paging scroll view
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.showsVerticalScrollIndicator = NO;
pagingScrollView.showsHorizontalScrollIndicator = NO;
pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
pagingScrollView.delegate = self;
// When I do this it fails
[self.view addSubview:pagingScrollView];
// Step 2: prepare to tile content
recycledPages = [[NSMutableSet alloc] init];
visiblePages = [[NSMutableSet alloc] init];
[self tilePages];
}
You just need to modify the frame of the scrollview to be positioned and sized how you want:
This is the line in the view controller that sets it up in the example
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
As an example here is a sample frame with some hardcoded values:
CGRect scrollFrame = CGRectMake(100,100,100,100);
pagingScrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
So, I found out that I was able to add the scrollView as a subview by changing the method from loadView to viewDidLoad.
I have no clue why that works, but it does. I'd love to know why that's the case however...
Disclaimer: I'm something of an iOS n00b. I have a navigation-based app -- i.e., in my AppDelegate, I create the nav frame:
self.navigation_controller = [[UINavigationController alloc] initWithRootViewController:home_view_controller];
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
self.window.rootViewController = navigation_controller;
self.window.makeKeyAndVisible;
Inside the frame of my home view, I want a search bar, then the scrollable table view. So, I wrote this:
- viewDidLoad{
(HomeView*)home_view = [[HomeView alloc] init];
self.view = home_view
self.view.backgroundColor = [UIColor whiteColor]
(UITableView*)self.table_view = [UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
self.table_view.bounds.origin.y += 44;
self.table_view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.table_view.dataSource = self;
self.table_view.delegate = self;
[self.view addSubview:self.table_view];
search_frame = self.view.bounds;
search_frame.origin.y = 48.0;
search_frame.size.height = 48.0;
self.search_bar = [[UISearchBar alloc] initWithFrame:search_frame)];
[self.view addSubview:self.search_bar];
}
The table view displays fine, but occupies all the space below the navigation bar. I want to have the navigation bar, then immediately below it the search bar, followed by the table view. At the point of viewDidLoad, the UITableView does not yet have a non-zero bounding rect and I expect that's part of the problem. Additionally, I've specified UIViewAutoresizingFlexibleHeight in my autoresizingMask when I really want it glued against the search bar -- again, I believe this may be part of the problem.
What have I misunderstood here?
Thanks
Steve,
Try following changes:
1) Set tableview's frame using:
CGRect targetRect = CGRectMake(0, 48, self.view.frame.size.width, self.view.frame.size.heigth);
(UITableView*)self.table_view = [UITableView alloc] initWithFrame:targetRect style:UITableViewStylePlain];
2) Add following autosize mask also:
// This value will anchor your table view with top margin
UIViewAutoresizingFlexibleBottomMargin
3) Set searchbar's frame to following rect frame:
CGRecttMake(0, 0, self.view.frame.size.width, 48);
What I would do, is just add the UISearchBar as the first UITableView header.
(method: tableView:viewForHeaderInSection:)
Check this blog post:
http://jainmarket.blogspot.com/2009/08/add-searchbar-as-uitableviews-header.html
In my app, I have a split screen in which the detail view is a scrollview. I have 5 tables which are subviews of my scrollview in which 3 table views are side by side on top and 2 table views are side by side on bottom
I have already implemented a way in which when I click any of the rows of any of the table in the scrollview, that view disappears and another view zooms into its position.
I write the following code in the didSelectRowAtIndexPath in the middle table subview,
CGFloat xpos = self.view.frame.origin.x;
CGFloat ypos = self.view.frame.origin.y;
self.view.frame = CGRectMake(xpos+100,ypos+150,5,5);
[UIView beginAnimations:#"Zoom" context:NULL];
[UIView setAnimationDuration:2];
self.view.frame = CGRectMake(xpos,ypos,220,310);
[UIView commitAnimations];
[self.view addSubview:popContents.view];
popContents is the view I need to zoom into to the view previously occupied by that particular table view and that happens correctly.
However the problem that I am facing is that since there is another table subview in the side, if I increase the frame size to say 250 or so, the part of the zoomed in view gets hidden by the tableview on the side ( as its as if a part of the zoomed in view goes under the tableview on the side).
Is there anyway to correct this so that my zoomed in view would not get hidden by the tableviews on its sides?
I hope I have explained my problem correctly...
UPDATE:
Here is the code I am using for adding the subviews for the scrollview
// Scroll view
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 30, 1000, 740)];
scrollView.contentSize = CGSizeMake(1000, 700);
scrollView.delegate = self;
scrollView.scrollEnabled = YES;
scrollView.showsHorizontalScrollIndicator = YES;
scrollView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
[self.view addSubview:scrollView];
aView = [[aViewController alloc] initWithNibName:#"aViewController" bundle:nil];
aView.view.frame = CGRectMake(10, 25, 220, 310);
[aView loadList:objPatients];
[scrollView addSubview:aView.view];
bView = [[bViewController alloc] initWithNibName:#"bViewController" bundle:nil];
bView.view.frame = CGRectMake(10, 350, 220, 310);
[bView loadList:objPatients];
[scrollView addSubview:bView.view];
cView = [[cViewController alloc] initWithNibName:#"cViewController" bundle:nil];
cView.view.frame = CGRectMake(240, 25, 220, 310);
[cView loadList:objPatients];
[scrollView addSubview:cView.view];
dView = [[dViewController alloc] initWithNibName:#"dViewController" bundle:nil];
enView.view.frame = CGRectMake(240, 350, 220, 310);
[enView loadList:objPatients];
[scrollView addSubview:dView.view];
eView = [[eViewController alloc] initWithNibName:#"eViewController" bundle:nil];
eView.view.frame = CGRectMake(470, 25, 220, 310);
[eView loadList:objPatients];
[scrollView addSubview:eView.view];
say for example, I add the code for didSelectRowAtIndexPath in cViewController subview...
This is a guess since I would need to know how your table views are added to the scroll view, but the middle table view was probably added before the one on the side. Views are "stacked" in the order they're added with the last one on top. You'll need to get the scroll view to move the middle view to the front with this method
- (void)bringSubviewToFront:(UIView *)view
The best way to do that would be to create a protocol for the table views and make the scroll view the delegate. The method would be something like this
- (void) moveAViewToFront: (MyTableView *) aTableView
{
[self.view bringSubviewToFront: aTableView.view];
}
You would then call the delegate method before setting up the animation.
Edited
After a little more thought I realized that the subviews have a reference to their superview so this bit of code should provide an idea on how to solve the problem. I created a test app which has a view controller which adds two sub views. The view controller header file is MoveSubviewViewController.h
#import <UIKit/UIKit.h>
#interface MoveSubviewViewController : UIViewController
{
}
#end
and it's implementation is
#import "MoveSubviewViewController.h"
#import "MoveableSubview.h"
#implementation MoveSubviewViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Create two overlapping subviews. The blue subview will start at the top of
// the frame and extend down two thirds of the frame.
CGRect superviewFrame = self.view.frame;
CGRect view1Frame = CGRectMake( superviewFrame.origin.x, superviewFrame.origin.y,
superviewFrame.size.width, superviewFrame.size.height * 2 / 3);
MoveableSubview *view1 = [[MoveableSubview alloc] initWithFrame: view1Frame];
view1.backgroundColor = [UIColor blueColor];
[self.view addSubview: view1];
[view1 release];
// The green subview will start one third of the way down the frame and
// extend all the to the bottom.
CGRect view2Frame = CGRectMake( superviewFrame.origin.x,
superviewFrame.origin.y + superviewFrame.size.height / 3,
superviewFrame.size.width, superviewFrame.size.height * 2 / 3);
MoveableSubview *view2 = [[MoveableSubview alloc] initWithFrame: view2Frame];
view2.backgroundColor = [UIColor greenColor];
[self.view addSubview: view2];
[view2 release];
}
#end
The subview class is MoveableSubview with another simple header
#import <UIKit/UIKit.h>
#interface MoveableSubview : UIView
{
}
#end
and implementation
#import "MoveableSubview.h"
#implementation MoveableSubview
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Move this view to the front in the superview.
[self.superview bringSubviewToFront: self];
}
#end
The thing to do is to add the
[self.superview bringSubviewToFront: self];
line before setting up the animation.