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.
Related
How to make parallax demo with three tab like image given below in iOS make scrolling vertically.and click on tab multiple table scrolling Horizental.
Try using a UIScrollView with paging enabled. Then connect an IBAction to the buttons with a tag value to it. The tag value indicates which page the UIScrollView has to show. Make sure the UIScrollView direction is set to horizontal. In this example I'm only adding UIViews but this could be anything. UITableView, UIScrollView or UICollectionView you name it.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Set number of pages
int numberOfPages = 3;
//Set properties scrollView
self.scrollView.pagingEnabled = true;
self.scrollView.contentSize = CGSizeMake((numberOfPages * self.scrollView.frame.size.width), self.scrollView.frame.size.height);
//Add pages
UIView *pageOne = [[UIView alloc] initWithFrame:CGRectMake((0 * self.scrollView.frame.size.width), 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
[pageOne setBackgroundColor:[UIColor yellowColor]];
[self.scrollView addSubview:pageOne];
UIView *pageTwo = [[UIView alloc] initWithFrame:CGRectMake((1 * self.scrollView.frame.size.width), 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
[pageTwo setBackgroundColor:[UIColor blueColor]];
[self.scrollView addSubview:pageTwo];
UIView *pageThree = [[UIView alloc] initWithFrame:CGRectMake((2 * self.scrollView.frame.size.width), 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
[pageThree setBackgroundColor:[UIColor redColor]];
[self.scrollView addSubview:pageThree];
}
- (IBAction)btnSelectPage:(id)sender; {
UIButton *btn = (UIButton *)sender;
[self.scrollView setContentOffset:CGPointMake((self.scrollView.frame.size.width * btn.tag), 0) animated:true];
}
And for the storyboard do something like this:
Don't forget to set the tag value of the button indicating what page you would like to show.
I am trying to increase the width of the scrollbar and add a circular scroller. Shall I use an image for the circle? I do not see any property or method of UIScrollView to change the width of the scroller
I tried the following:
UIScrollView *myScroll = [[UIScrollView alloc] init];
myScroll.frame = self.view.bounds; //scroll view occupies full parent view!
//specify CGRect bounds in place of self.view.bounds to make it as a portion of parent view!
myScroll.contentSize = CGSizeMake(400, 800); //scroll view size
myScroll.backgroundColor = [UIColor grayColor];
myScroll.showsVerticalScrollIndicator = YES; // to hide scroll indicators!
myScroll.showsHorizontalScrollIndicator = YES; //by default, it shows!
myScroll.scrollEnabled = YES; //say "NO" to disable scroll
[myScroll setBackgroundColor:[UIColor redColor]];
myScroll.indicatorStyle = UIScrollViewIndicatorStyleWhite;
[self.view addSubview:myScroll];
This custom ScrollView Solved all my problems https://github.com/BasheerSience/BRScrollBar
I am looking for a way to implement the following:
Have one 'master' scrollView that contains both a full-screen UIView on top and a full-screen UIScrollView below this
When the user scrolls past the top UIView, the bottom scrollView is visible and becomes the responder for scroll events
When the user attempts to scroll up from the bottom UIScrollView, the touches are redirected so they control the 'master' scrollView and bring the UIView into view again.
To give an idea of how this is set out, here is my current implementation:
// Initialise components:
mainScreen = [[UIScreen mainScreen] bounds];
CGFloat screenHeight = mainScreen.size.height-20;
// Scroll View Controller
_scrollControl = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, screenHeight)];
_scrollControl.contentSize = CGSizeMake(320, 2*screenHeight); // Twice as big as the screen size for both views to fit
_scrollControl.backgroundColor = [UIColor clearColor];
_scrollControl.delegate = self;
// Top View
_topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, screenHeight)];
_topView.backgroundColor = [UIColor redColor];
[_scrollControl addSubview:_topView];
// Bottom View
_bottomView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, screenHeight, 320, screenHeight)];
_bottomView.backgroundColor = [UIColor yellowColor];
_bottomView.contentSize = CGSizeMake(320, 2*screenHeight);
_bottomView.delegate = self;
UILabel *imageLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 40, 120, 700)];
imageLabel.backgroundColor = [UIColor greenColor];
[_bottomView addSubview:imageLabel];
[_scrollControl addSubview:_bottomView];
// Add to main view
[self.view addSubview:_scrollControl];
I have tried to achieve the desired effect using delegate methods, however I can't seem to stop the 'master' scrollView from scrolling before it switches to the bottom scrollView.
Apple provides this functionality for free, so the good news is you don't need to actually directly code anything here (unless you want something a little funky). The effect is achieved through paging
scrollView.pagingEnabled = YES;
Before this will take any real effect, you will need embed your subviews (both the UIView and the UIScrollView) in the master scroll view. Each of them should be the same size, or size of a single page. So let's say the master scroll view is 100, 100 points, we could set it up like so:
CGRect pageRect = CGRectMake(0, 0, 100, 100);
NSInteger pageCount = 2;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:pageRect];
scrollView.pagingEnabled = YES;
UIView *page1View = [[UIView alloc] initWithFrame:pageRect];
page1View.backgroundColor = [UIColor redColor];
[scrollView addSubview:page1View];
pageRect.origin.x += pageRect.size.width;
UIView *page2View = [[UIView alloc] initWithFrame:pageRect];
page2View.backgroundColor = [UIColor blueColor];
[scrollView addSubview:page2View];
scrollView.contentSize = CGSizeMake(pageRect.size.width * pageCount,
pageRect.size.height);
That should give you the basics. As you can see we position the subviews one after another horizontally in this example. We set the content size to cover both subviews and enable paging. UIScrollView should take care of the rest.
A good place to look is at the WWDC session views, specifically from WWDC 2010 at: Session 104 - Designing Apps with Scroll Views. This has a lot of information on how to setup scroll views and really get the most out of them.
Hope this helps!
so if you want to detect it using swift, use these:
override func scrollViewDidScroll(scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
//reach bottom
}
if (scrollView.contentOffset.y < 0){
//reach top
}
if (scrollView.contentOffset.y >= 0 && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)){
//not top and not bottom
}
}
I have a UIViewController, and I want to add a UIScrollView to it (enable scroll support), is it possible?
I know it is possible, if you have a UIScrollView to add a UIViewController to it, but I'm interested also if reverse was true, if I cann add a UIScrollView to an existing UIViewController, such that I get scrolling feature.
Edit
I think I have found an answer: Adding a UIViewController to UIScrollView
An UIViewController has a view property. So, you can add a UIScrollView to its view. In other words, you can add the scroll view to the view hierarchy.
This is can achieved by code or through XIB. In addition, you can register the view controller as the delegate for your scroll view. In this way, you can implement methods for performing different functionalities. See UIScrollViewDelegate protocol.
// create the scroll view, for example in viewDidLoad method
// and add it as a subview for the controller view
[self.view addSubview:yourScrollView];
You could also override loadView method for UIViewController class and set the scroll view as the main view for the controller you are considering.
Edit
I created a little sample for you. Here, you have a scroll view as a child of the view of a UIViewController. The scroll view has two views as children: view1 (blue color) and view2 (green color).
Here, I suppose you can scroll in only one direction: horizontally or vertically. In the following, if you scroll horizontally, you can see that the scroll view works as expected.
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
scrollView.backgroundColor = [UIColor redColor];
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
scrollView.showsVerticalScrollIndicator = YES;
scrollView.showsHorizontalScrollIndicator = YES;
scrollView.contentSize = CGSizeMake(self.view.bounds.size.width * 2, self.view.bounds.size.height);
[self.view addSubview:scrollView];
float width = 50;
float height = 50;
float xPos = 10;
float yPos = 10;
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(xPos, yPos, width, height)];
view1.backgroundColor = [UIColor blueColor];
[scrollView addSubview:view1];
UIView* view2 = [[UIView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width + xPos, yPos, width, height)];
view2.backgroundColor = [UIColor greenColor];
[scrollView addSubview:view2];
}
If you need to scroll only vertically you can change as follows:
scrollView.contentSize = CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height * 2);
Obviously, you need to rearrange the position of view1 and view2.
P.S. Here I'm using ARC. If you don't use ARC, you need to explicitly release alloc-init objects.
I'm trying to create a horizontally scrollable menu similar to that in this video.
For some reason the UIView doesn't appear after adding a bunch of UIButtons to it and adding it to the UIScrollView. Here's my code (it's called in -viewDidLoad of a subclass of UIViewController):
//set up scrollview
UIScrollView *designPicker = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 431, 320, 49)];
//set up a view to drop into the scroll view
UIView * buttonsView = [[UIView alloc] initWithFrame:CGRectMake(0, 431, 640, 49)];
//add buttons to scrollview
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
float runningX = designPicker.frame.origin.x;
for (i = 1; i <= 10; i++)
{
UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[tempBtn setBackgroundImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal];
CGRect rect = CGRectMake(runningX, designPicker.frame.origin.y, 30.0, 30.0);
tempBtn.frame = rect;
[buttonsView addSubview:tempBtn];
runningX = runningX + 35;
[tempBtn release];
}
[designPicker setContentSize:buttonsView.frame.size];
[designPicker addSubview:buttonsView];
[self.view addSubview:designPicker];
You should not add the buttons using the frame of the UIScrollView. The origin of the frame is in the superview's (superview of the UIScrollView) coordinates. You should make the buttons' frame relative to the UIView. So if you want the buttons to appear at the top of the view that you should start at (0,0).
Instead of adding scrollview as subview to your view, add view as subview of scrollview. As-
[self.scrollView addSubview:self.view];
// release scrollView as self.view retains it
self.view=self.scrollView;
[self.scrollView release];
And make sure your view should have large content size than content size of your scrollview.It worked for me.