Trying to add subviews to UIScrollView, which is defined in XIB file. The code below is how I tried to add subviews in my view controller. But no subviews were added.
Any suggestions?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
CGRect frame = _tasksScrollView.frame;
frame.size.width /= 3.0;
NSArray *colors = [NSArray arrayWithObjects:[UIColor blueColor],
[UIColor redColor],
[UIColor yellowColor],
[UIColor greenColor],
[UIColor purpleColor],
nil];
for (int i = 0; i < [colors count]; i++, frame.origin.x += frame.size.width) {
UIView *subView = [[UIView alloc] initWithFrame:frame];
subView.backgroundColor = [colors objectAtIndex:i];
[_tasksScrollView addSubview:subView];
}
_tasksScrollView.contentSize = CGSizeMake(frame.size.width * [colors count], frame.size.height);
}
It may be that your subviews are offset relative to the view space in your scroll view since youre carrying over the x and y coordinates from the scrollview.frame itself which is actually a position relative to the full screen. Try setting the x and y position of the subview so that it starts from 0.
There are a few reasons why this could happen, most of the time, you just fail to link/connect the IBOutlet property (_tasksScrollView) in the XIB.
Related
I am trying to make a simple Paging with UIScrollview, But pages are getting out after the second screen. Here is my code.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSArray *colors =[NSArray arrayWithObjects:#"1. This is my first Page ",#"2. This is my Second Page",#"3. This is my third Page",#"4. This is my fourth Page",#"5. This is my fifth Page",nil];
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = (scroll_events.frame.size.width) * i;
frame.origin.y = 0;
frame.size = scroll_events.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[self.scroll_events addSubview:subview];
UITextView *myTextView = [[UITextView alloc] init];
myTextView.text = colors[i];
[subview addSubview:myTextView];
[myTextView setBackgroundColor: [UIColor redColor]];
[myTextView setTextColor: [UIColor blackColor]];
[myTextView setFont: [UIFont fontWithName:#"Lobster 1.4" size:30]];
myTextView.frame = CGRectMake(0.0,0.0,scroll_events.bounds.size.width,scroll_events.bounds.size.height);
myTextView.editable = NO;
myTextView.selectable = NO;
myTextView.scrollEnabled = NO;
}
self.scroll_events.contentSize = CGSizeMake(self.scroll_events.frame.size.width * colors.count, self.scroll_events.frame.size.height);
}
Here is the screen shot of my Scroll View
In ViewDidLoad maybe the frame of your scroll view was still not set.
Try that code in ViewDidAppear and check if it works.
Advice: You should subclass that UISCrollView and initialize the view there, not in the ViewController.
Let me know it that worked!
Regards.
I am creating a view with a subview for a tutorial screen.
I want the gray subview to be swipeable using the page control
I have implemented the example of http://www.appcoda.com/uipageviewcontroller-tutorial-intro/ but this works with whole ViewControllers and I want it to work with only the subview...
Does anyone have any idea how to implement the PageControl with the swipe gesture so that only the gray subview changes? Any good tutorial?
The grey area must be a UIScrollView with a content view containing each page of the tutorial. Set pagingEnabled to YES on your scroll view so that it will snap to each page when you scroll.
Then you need to attach an action to the page control using addTarget:action:forControlEvents: and pass UIControlEventValueChanged as the event. Then the action must be a method that tells the scroll view to move forward or back a page depending on whether the value of the page control increased or decreased. You can do this by changing the scroll view's content offset, or by telling it to scroll so that a particular rect is visible.
Finally, implement the delegate of the UIScrollView, and use the methods that tell when the scroll view stopped scrolling (you'll need a combination of the did end decelerating, did end dragging and possibly did end scrolling animation), and update the page control's value when the scroll view changes pages.
And that's all there is to it. If you need more details, read the documentation for UIScrollView, UIScrollViewDelegate and UIPageControl.
use UIView instead of ViewController
Here is a solution that works for me:
1) Create a scrollView and pageControl in your NIB or Storyboard
2) scrollView in ViewDidLoad
self.scrollView.backgroundColor = [UIColor clearColor];
self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack; //Scroll bar style
self.scrollView.showsHorizontalScrollIndicator = NO;
//dont forget to set delegate in .h file
[self.scrollView setDelegate:self];
self.scrollView.showsVerticalScrollIndicator = YES; //Close vertical scroll bar
self.scrollView.bounces = YES; //Cancel rebound effect
self.scrollView.pagingEnabled = YES; //Flat screen
self.scrollView.contentSize = CGSizeMake(640, 30);
3) create your views you want in the scrollView and add them in an Array
//For instance, you want 3 views
UIView *ViewOne = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
[ViewOne setBackgroundColor:[UIColor redColor]];
UIView *ViewTwo = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width+1, self.scrollView.frame.size.height)];
[ViewTwo setBackgroundColor:[UIColor greenColor]];
UIView *ViewThree = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width+2, self.scrollView.frame.size.height)];
[ViewThree setBackgroundColor:[UIColor blueColor]];
//add all views to array
NSMutableArray *viewsArray = [[NSMutableArray alloc] initWithObjects:ViewOne, ViewTwo, ViewThree, nil];
4) pageControl in ViewDidLoad
self.pageControl.numberOfPages = viewsArray.count;
self.pageControl.currentPage = 0;
self.pageControl.backgroundColor = [UIColor clearColor];
[self.pageControl setTintColor:[UIColor whiteColor]];
5) Add it all up
for(int i = 0; i < viewsArray.count; i++)
{
CGRect frame;
frame.origin.x = (self.scrollView.frame.size.width *i) + 10;
frame.origin.y = 0;
frame.size = CGSizeMake(self.scrollView.frame.size.width - 20, self.scrollView.frame.size.height);
NSLog(#"array: %#", [viewsArray objectAtIndex:i]);
UIView *view = [[UIView alloc] initWithFrame:frame];
view = [viewsArray objectAtIndex:i];
[self.scrollView addSubview:view];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width*viewsArray.count, self.scrollView.frame.size.height);
}
6) Track the scrollView and update the pageControl (DONT FORGET THE SCROLLVIEW DELEGATE)
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = scrollView.frame.size.width;
//int page = floor((scrollView.contentOffset.x - pageWidth*0.3) / pageWidth) + 1);
self.pageControl.currentPage = (int)scrollView.contentOffset.x / (int)pageWidth;
NSLog(#"CURRENT PAGE %d", self.pageControl.currentPage);
}
This should do the trick.
PS. Sorry for all the magic numbers.
I have three buttons and one view controller. I want to link three buttons to those three
different views (pages).
I've tried this by making three views and storing it in an mutable array.
ViewArray= [[NSMutableArray alloc]initWithCapacity:15];
CGRect viewRect = CGRectMake(10, 10, 100, 10);
//VIEW1
UIView* view1 = [[UIView alloc] initWithFrame:viewRect];
view1.backgroundColor = [UIColor redColor];
//VIEW2
UIView* view2 = [[UIView alloc] initWithFrame:viewRect];
view2.backgroundColor = [UIColor greenColor];
I added three buttons programmatically. After that for the action of each button I used this:
//action for each button
self.view = [ViewArray objectAtIndex:i];//where i={1,2,3} for different functions
but I am not getting what I want.
A better design would be to add all of the views invisibly, then change their opacity 0.0-1.1 to hide and show. (also, a key mistake in the OP is that the code replaces the view controller view with the subviews, instead of adding them)
CGRect viewRect = CGRectMake(10, 10, 100, 10);
//VIEW1
UIView* view1 = [[UIView alloc] initWithFrame:viewRect];
view1.backgroundColor = [UIColor redColor];
view1.tag = 1;
view1.alpha = 0.0;
[self.view addSubview:view1];
//VIEW2
UIView* view2 = [[UIView alloc] initWithFrame:viewRect];
view2.backgroundColor = [UIColor greenColor];
view1.tag = 2;
view1.alpha = 0.0;
[self.view addSubview:view2];
Add a property in your vc's interface that keeps track of the visible view:
#property(nonatomic, weak) UIView *visibleSubview;
Then the button action:
UIView *subview = [self.view viewWithTag:i];
//where i={1,2,3} for different functions
// i really needs to be 1,2,3 here, to correspond to the tags
[UIView animateWithDuration:0.5 animations:^{
subview.alpha = 1.0;
self.visibleSubview.alpha = 0.0;
} completion:^(BOOL finished) {
self.visibleSubview = subview;
}];
Well I'm not sure exactly what you want. But in general if you want to access any change multiple objects such as a UIView or UILabels, etc... You can just use and NSArray and a for loop to access and make all the changes without any extra code copies like so:
First of all, setup the NSArray with all your objects like so:
NSArray *_viewArray = #[view1, view2]; //etc....
And also setup an array with the different UIColors like so:
NSArray *_colourArray = #[[UIColor redColor], [UIColor greenColor]]; //etc....
And then when you want to access them and edit multiple UIViews or what ever objects, you can just use a for loop like so:
for (int loop = 0; loop < ([_viewArray count] - 1); loop++) {
((UIView*)_viewArray[loop]).backgroundColor = ((UIColor*)_colourArray[loop]);
}
I hope this helps you :)
I happened to find that setContentOffset to a UIScrollView will cause the scrollView append a new view to its subviews. here is the code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake((320 - 261) / 2, 50, 261, 67)];
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.bounces = NO;
scrollView.backgroundColor = [UIColor darkGrayColor];
for (int i = 0; i < 5; i ++) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(i * 87, 1, 87, 65)];
view.tag = i;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 50, 30)];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.text = [NSString stringWithFormat:#"%d", i];
[view addSubview:label];
view.backgroundColor = [UIColor greenColor];
[scrollView addSubview:view];
}
scrollView.contentSize = CGSizeMake(87 * 5, 67);
NSLog(#"before scroll: count of subview is %d", scrollView.subviews.count);
CGPoint offset = CGPointMake(87, 0);
[scrollView setContentOffset:offset animated:YES];
NSLog(#"after scroll: count of subview is %d", scrollView.subviews.count);
[self.view addSubview:scrollView];
}
Before calling setContentOffset:offset, the number of subviews of the scrollView is 5. This is what I expect. After that, the number turns to be 6.
Is it working as designed? How to avoid the new subview appended?
The extra subview is the scroll indicator. If you check again in a later method, it will have gone away. Don't worry.
You can confirm this by hiding the scroll indicators (showsVerticalScrollIndicator and showsHorizontalScrollIndicator properties).
Don't try to assume things about the view hierarchy of UIKit classes. UIKit can, and does, add its own views to several things - see tableviews and their cells, a navigation controller's view and so on.
I have created a UIViewController with a UIScrollView. On the scrollView I have a page control. When I was testing it I was able to scroll horizontally through four different color pages. Now I need to add the actual views I need. In a different part of the project I created a line graph using coreplot. Now I have added made a new UIview and added the code for the line graph. I am now trying to replace the first page of the scrollView with the linegraph UIView. I am getting no errors however nothing is appearing on the screen either. It is just the default background of the scrollView. The scrollView still scrolls through the other pages correctly. I added a button programatically to the UIView to see if it had something to do with coreplot but I cannot see that either. Here is some of my code. I would appreciate any advice. Thanks.
The viewDidLoad method for my main viewController:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], nil];
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
self.alertsSubView = [[AlertsView alloc] initWithFrame:frame];
[self.scrollView addSubview:_alertsSubView];
for (int i = 1; i < numberOfGraphs; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
self.alertsSubView.delegate = self;
_scrollView.delegate = (id)self;
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
}
Here is the code for the initWithFrame method from my UIView. All of the NSLog statements get run so I know everything is being called:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSLog(#"AlertsView initWithFrame");
///button for testing
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect buttonFrame = CGRectMake(0,0, frame.size.width, frame.size.height);
self.button.frame = buttonFrame;
[self.button addTarget:self
action:#selector(buttonTouched)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.button];
[self initPlot];
}
return self;
}
I am also adding the methods initPlot and ConfigureHost in case they are relevant:
-(void)initPlot {
NSLog(#"into init plot");
[self configureHost];
[self configureGraph];
[self configurePlots];
[self configureAxes];
NSLog(#"endo of init plot");
}
-(void)configureHost {
NSLog(#"into configure host");
self.hostView = [(CPTGraphHostingView *) [CPTGraphHostingView alloc] initWithFrame:self.bounds];
self.hostView.allowPinchScaling = YES;
[self addSubview:self.hostView];
}
I finally figured this out. Thanks for your suggestion #Eric Skroch. It actually led me down the path to the right answer even though it was not the problem. Basically to fix this problem I had to move all of the logic into the view controller and change the order of alot of the code. I am posting the relevant parts of my revised view controller here in case anyone runs across anything similar.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[_alertsSubView initPlot];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor], nil];
alertFrame.origin.x = self.scrollView.frame.size.width;
alertFrame.origin.y = 0;
alertFrame.size = self.scrollView.frame.size;
_panel = [[UIView alloc]initWithFrame:alertFrame];
for (int i = 1; i < numberOfGraphs; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
_scrollView.delegate = (id)self;
self.alertsSubView.delegate = self;
}
-(AlertsView *)alertsSubView
{
if(!_alertsSubView)
{
CGRect alertsViewFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
_alertsSubView = [[AlertsView alloc] initWithFrame:alertsViewFrame];
_alertsSubView.backgroundColor = [UIColor purpleColor];
[self.scrollView addSubview:self.alertsSubView];
}
return _alertsSubView;
}