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.
Related
I have a UIScrollView. Inside this UIScrollView is a UIView which contains every other child views (including a UIButton). It has the same bounds as the UIScrollView.
I want:
The bottom of the UIScrollView is not scroll-able (where the UIButton is placed).
The UIButton is responsive.
So I set the bottom of the UIScrollView a little higher than the UIVIew as below image:
This will make the UIButton not responsive (it's responsive in the left layout). Any suggestion? Thanks!
Some part of my code:
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[self addSubview:self.scrollView];
self.scrollContent = [[UIView alloc] initWithFrame:CGRectZero];
[self.scrollView addSubview:self.scrollContent];
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.scrollContent addSubview:self.button];
[self.button addTarget:self
action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
Update:
Looks like the right way is to keep the bottom of the scroll view and set its contentSize, but since I'm using autolayout, I found that the height of the contentSize is always zero???
You need to place the button in a view that is outside of the scroll views view hierarchy.
Currently the hit testing is failing because the button is outside of the scroll views bounds but within its hierarchy.
Add the button into scroll view after that try the below code:
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
[self addSubview:self.scrollView];
self.scrollContent = [[UIView alloc] initWithFrame:CGRectZero];
[self.scrollView addSubview:self.scrollContent];
self.scrollView.delaysContentTouches = NO; //Add this line
self.button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.scrollContent addSubview:self.button];
[self.button addTarget:self
action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
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 got a problem about UIScrollView. I am making a custom view which inherits UIView. The view has a UIScrollView on which there are lots of buttons which should scroll left and right. The UIScrollView and buttons can show normally. But I cannot scroll the buttons. Could someone give me some suggestions? Thanks a lot!
MZMPhotoCalenderSwitcher.h
#import <UIKit/UIKit.h>
#interface MZMPhotoCalenderSwitcher : UIView <UIScrollViewDelegate>
#property (strong, nonatomic) UIScrollView *topSwitcher;
#end
MZMPhotoCalenderSwitcher.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.topSwitcher = [[UIScrollView alloc] initWithFrame:CGRectMake(0, LABEL_HEIGHT + VIEW_Y, self.view.bounds.size.width, TOP_SWITCHER_HEIGHT)];
self.topSwitcher.backgroundColor = [UIColor greenColor];
self.topSwitcher.pagingEnabled = YES;
self.topSwitcher.showsHorizontalScrollIndicator = NO;
self.topSwitcher.showsVerticalScrollIndicator = NO;
[self add:3 ButtonsOnView:self.topSwitcher withButtonWidth:44.8f andHeight:20.0f];
}
- (void)add:(int)num ButtonsOnView:(UIScrollView *)view withButtonWidth:(CGFloat)width andHeight:(CGFloat)height
{
CGFloat totalTopSwitcherWidth = num * width;
[view setContentSize:CGSizeMake(totalTopSwitcherWidth, view.bounds.size.height)];
CGFloat xOffset = 0.0f;
for (int i=1; i<=num; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(xOffset, 0, width, height)];
xOffset += width;
[button setTitle:[NSString stringWithFormat:#"%d", i] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:10];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateSelected];
[button setTag:i];
[button addTarget:self action:#selector(buttonEvent) forControlEvents:UIControlEventTouchUpInside];
if (i % 2 == 0)
[button setBackgroundColor:[UIColor yellowColor]];
else
[button setBackgroundColor:[UIColor redColor]];
[view addSubview:button];
}
}
Below following line
[view addSubview:button];
add
view.contentSize = CGSizeMake(view.contentSize.width, button.frame.origin.y + button.frame.size.height);
This will set content size of scroll view to the bottom of your button.
It should be issue of content size, also check that scrollEnabled property of UIScrollView object is set to TRUE,
Check solution of UIScrollView won't scroll!
Just disable "Auto Layout" in your project and it will start working!
I'm using Xcode 6/iOS 8+ now with auto-layout turned on, and I had the same problem in the first place, removing auto-layout doesn't work at all, so in order to make scroll view scrollable vertically, I made sure the following:
The scroll view content size height MUST be bigger than the screen
height, this almost goes without saying...
The top/bottom/left/right constraint of the scroll view HAS TO BE
pinned, I did this using storyboard so no code showing up here
If you want to make the scroll view scrollable horizontally, then make sure its content size width is bigger than the screen width, the other rule applies the same.
This worked for me, hope it can help someone.
Combining all of this advise into one simple answer:
// In viewDidLoad
// set the size of the scrollview (in this case I made it the size of its container
self.scrollView.frame = self.view.frame;
// now set the size of the content to be scrolled within the scrollview
// the content to be displayed must be bigger than the scrollView
// in this case I added 100 to make the content size, so that it is taller than the height of the scrollView
// now it scrolls
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, self.scrollView.frame.size.height + 100);
Your problem is that you haven't set your contentSize, therefore, the contentSize is the same than the frame view.
You need to do this in your viewDidLoad
- (void)viewDidLoad {
........
self.scrollView.contentSize = CGSizeMake(/*yourWidth*/, /*yourHeight/*);
........
}
Try do adjust your contentSize to the last position of your object plus its size plus a padding.
You have to set scrollview frame size and content size.
Where are you add ScrollView on SuperVIew? And where are you recalculate Content size property of scrollView?
[view setContentSize:CGSizeMake(<summYourViews.width>,<summYourViews.height>)];
try this . . . .
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.topSwitcher = [[UIScrollView alloc] initWithFrame:CGRectMake(0, LABEL_HEIGHT + VIEW_Y, self.view.bounds.size.width, TOP_SWITCHER_HEIGHT)];
self.topSwitcher.backgroundColor = [UIColor greenColor];
self.topSwitcher.pagingEnabled = YES;
self.topSwitcher.showsHorizontalScrollIndicator = NO;
self.topSwitcher.showsVerticalScrollIndicator = NO;
[topSwitcher setContentSize:CGPointMake(self.view.bounds.size.width,TOP_SWITCHER_HEIGHT+400)];
[self add:3 ButtonsOnView:self.topSwitcher withButtonWidth:44.8f andHeight:20.0f];
}
It's amazing.
I just move the codes which was in viewDidLoad to initWithFrame:, then it works. I do not know why it is?
I have a button at the 1000 height pixel mark and I need a uiscrollview in order to access that button. I implemented the scrollview code below and it shows the scroll view ,but doesn't allow me to scroll down. I might be missing a key function. Any tips or advice is appreciated.
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 680)];
scrollView.contentSize = CGSizeMake(320, 1000);
scrollView.clipsToBounds = YES;
super.view.backgroundColor = [UIColor whiteColor];
[scrollView setUserInteractionEnabled:YES];
[[self view] addSubview:scrollView];
The problem is that your button's y coordinate is 1000 pixels, as you have stated. And the y-coordinate of scrollview's contentZize is maximum upto 1000 pixels as well. So the scrollview can jus scroll up to exactly where the button starts.
UIButton *btn =[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(50, 1000, 100,45);
[scrollView addSubview:btn];
set the content size of scrollview like this
scrollView.contentSize = CGSizeMake(320, 1100);
This will surely solve it.
Within my UIView, I have a UIScrollView which fills the first view, so than when the content is bigger than the iPhone screen size, the user can scroll the page down. It works well, but when the user finishes the scroll movement - i.e. removes his fingers, the page snaps back into it's original position. Obviously that is not what I want, how can it be avoided?
Here is the relevant code in the UIView class which declares and uses the UIScrollView class.
#implementation TestView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
}
CGRect scrollViewFrame = CGRectMake(0, 0, 320, 460);
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame];
scrollView.canCancelContentTouches=NO;
[self addSubview:scrollView];
CGSize scrollViewContentSize = CGSizeMake(320, 500);
[scrollView setContentSize:scrollViewContentSize];
CGRect rectForBigRedSquare = CGRectMake(50, 50, 200, 200);
UILabel *redSquare = [[UILabel alloc] initWithFrame:rectForBigRedSquare];
[redSquare setBackgroundColor:[UIColor redColor]];
[scrollView addSubview:redSquare];
return self;
}
An additional question is this: how is it possible to make it such that the user can only scroll down, that is to see content at the bottom which was out of view, but not to scroll up so that there is space before the start of the content. In
Basically you just have to set contentSize of your scrollview according to the contents.
CGSize scrollViewSize = CGSizeMake(newWidth, newHeight);
[self.myScrollView setContentSize:scrollViewSize];
Okay, the easiest way to get this scrollview working as you desire is to ensure that content size of the scrollview is identical to the frame size of the content you wish to scroll.
You can achieve this by having a content view into which you add all the views you wish to be visible and then add that content view to the scrollview while ensuring that the content size of the scrollview is set to the content view's frame size.
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
UIView* contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1280, 460)];
UIView* redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
[redView setBackgroundColor:[UIColor redColor]];
[contentView addSubview:redView];
[redView release];
UIView* blueView = [[UIView alloc] initWithFrame:CGRectMake(960, 0, 320, 460)];
[redView setBackgroundColor:[UIColor blueColor]];
[contentView addSubview:blueView];
[blueView release];
CGSize contentViewSize = contentView.frame.size;
[scrollView addSubview:contentView];
[scrollView setContentSize:contentViewSize];
[contentView release];
[self addSubview:scrollView];
The app I was working on had similar symptoms. The user could scroll down but on release the view would snap back to the initial position. The page was set up as follow:
[VIEW]
[SAFE AREA]
[SCROLL VIEW]
[CONTENT VIEW]
I strongly suspect that a combination of Auto-Layout and manual constraints caused by several adjustment iterations was causing the issue. To resolve this all constraints where removed from the View.
The Scroll View was assigned the following constraints:
Scroll View.leading = Safe Area.leading
Scroll View.top = Safe Area.top
Scroll View.trailing= Safe Area.trailing
Scroll View.bottom = Safe Area.bottom
The Content View was then assign the following constraints
ContentView.Leading = Scroll View.Leading
ContentView.top = Scroll View.top
ContentView.centerX = ScrollView.centerX
The Content View was also given the following self constraint
height = 1000