I have a scrollView that has a UIView as subview. This has as UIView subview a UIButton. Only the scrollView is connected to the outlet, the rest is all in code. The button does not respond to touches, not turns blue when touched. What can I do to make it work?
This is the code:
- (void)viewDidLoad
{
[super viewDidLoad];
//......
self.buttonHome = [UIButton buttonWithType:UIButtonTypeCustom];
[self.buttonHome addTarget:self action:#selector(pressedHome:)
forControlEvents:UIControlEventTouchUpInside];
//....
self.containerView =[[UIView alloc]initWithFrame:self.scrollView.frame];
self.containerView.userInteractionEnabled=YES;
[self.scrollView addSubview:self.containerView];
[self.containerView addSubview:self.buttonHome];
}
-(void) pressedHome:(id)sender{
//....
}
You must set content size of your view. That must be greater than or equal to the content size of scrollView.
Because default size of your view is 320*480 (3.5" retina) and 320*568 (4" retina). So increasing height of view as-
self.view.frame=CGRectMake(0, 0, 320, 700);
Then adding this as the subview of your scrollView.
will get you to the solution.
I resolve it
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
return ![view isKindOfClass:[UIButton class]];
}
Since the problem is to put a button UIButton
Make sure your scrollview isn't swallowing the touches:
Check this other SO question
Make containerView view height same as scrollView Height.
Related
I have a .xib file who have one view, one tab bar and other 3 scrollViews, when the user select a new tab bar item I execute this code:
//Views e Scrolls
IBOutlet UIView *myView;
IBOutlet UIScrollView *myScroll;
IBOutlet UIScrollView *myScroll2;
IBOutlet UIScrollView *myScroll3;
#property (nonatomic) UIScrollView *scroll;
-(void)tabBar:(UITabBar *)tabBar
didSelectItem:(UITabBarItem *)item{
NSArray *viewsToRemove = [myView subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
if(item.tag == 1){
self.title = #"scroll 1";
scroll = myScroll;
}
if(item.tag == 2){
self.title = #"scroll 2";
scroll = myScroll2;
}
if(item.tag == 3){
self.title = #"scroll 3";
scroll = myScroll3;
}
scroll.contentSize = scroll.frame.size;
scroll.frame = myView.frame;
scroll.scrollEnabled = YES;
[myView addSubview:scroll];
[myView setBackgroundColor:[UIColor clearColor]];
}
This code works great, but when I select one of the scrolls that had previously been removed from view, they lose their scrolling (which had not happened before), why this is happening and how to solve?
It's this line here:
scroll.contentSize = scroll.frame.size;
When your UIScrollView's contentSize matches its frame.size, it doesn't need to scroll (by definition). You need to figure out the actual size of its content and use that. You can at least demonstrate the correct functionality (even if it isn't with correct values) by doing this:
scroll.contentSize = CGSizeMake(scroll.frame.size.width*2, scroll.frame.size.height*2);
You'll have to find the real content size for yourself, though.
Assuming I understand your intention correct: Removing a scollview from it superview will also remove it from the responderchain. It cant no longer respond to touch event - thus wont scroll.
The question itself and your purpose of code is not very clear. You may try to explain further. And check this line -
scroll.contentSize = scroll.frame.size;
A UIScrollView whose contentSize <= frame.size, will not scroll. To make it scroll, contentSize should be bigger than frame.size
You should usually set the contentSize depending on the amount of content (subviews) for the scrollView.
In the next line you changed the frame.size, but I do not think that makes the frame size smaller than contentSize in your case.
I have the following ViewController:
It contains two UILabels at top, an UIImageView, below it a UITextView and below this a UIButton. I have arranged them using the Interface Builder following the blue line. All of this controls are inside a UIScrollView:
[self.scrollView setContentSize:CGSizeMake(320, 660)];
[self.scrollView addSubview:self.descriptionText];
[self.scrollView addSubview:self.descriptionImage];
[self.scrollView addSubview:self.titleLabel];
[self.scrollView addSubview:self.feedNameLabel];
[self.scrollView addSubview:self.load];
So when enabling Autolayout option, I just selected the ViewControler and then "Reset to Suggested Constraints in Description View Controller". But when I run the app, the scroll still appears for the entire page, but the only control scrolling is the UIButton. When scrolling up it will scroll below the UITextView.
I have made the UITextView to resize depending on the text, so I want my UIButton to always have the same distance to the UITextView. For that I have also set Vertical Spacing to the UIButton, but like this I don't have any scroll to my page.
Using the Autolayout for the first time, can I get some suggestions on what am I doing wrong ?
edit:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *contentView = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,660)];
[contentView addSubview:self.descriptionText];
[contentView addSubview:self.descriptionImage];
[contentView addSubview:self.titleLabel];
[contentView addSubview:self.feedNameLabel];
[contentView addSubview:self.load];
contentView.translatesAutoresizingMaskIntoConstraints = YES;
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 660)];
//[scrollView setContentSize:CGSizeMake(320, 660)];
[scrollView addSubview:contentView];
[self.view addSubview:scrollView];
// to resize UITextField
[self.descriptionText sizeToFit];
[self.descriptionText layoutIfNeeded];
self.descriptionText.scrollEnabled = NO;
}
Autolayout is a bit tricky when it comes to UIScrollView subviews. I would recommend:
1-Embed all your controls (descriptionText + descriptionImage + titleLabel + feedNameLabel + load) into a UIView first, say contentView:
UIView *contentView = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,660)];
//add all controls as subviews to contenView
2-Add contentView as subview of self.scrollView.
3-Keep the translatesAutoresizingMaskIntoConstraints property of contentView to YES.
I recommend you read this technical note from Apple here.
If you are using AutoLayout you don't have to set the content size of your scroll view. In fact, I believe it has no effect at all. It is set automatically from the constraints you are setting up. The trick is that you have to have at least one constraint related to every side of the scroll view, otherwise the content size will be wrong and it won't scroll. So for example, if you would have a really large image in it you would need 4 constraints connecting the sides of the UIImageView to the sides of the UIScrollView. You can read about this more here.
UIView *parentView = [[UIView alloc]initWithFrame:[CGRectMake(0,0,100,100)]];
UIView *childView = [[UIView alloc]initWithFrame:[CGRectMake(0,120,100,100)]];
[parentView addSubview:childView];
The code above stating childView is added into parentView at a location outside of parentView bound. Is there anyway i can resize parentView so that the childView is no longer out of bound? I want to do this dynamically. Is there any auto function available, or I have to do it manually by calculating the overall size.
Another question is, before the resizing of parentView to fit in childView, it seems that the childView is added at (0,100) instead of (0,120) of parentView, even though I set [parentView setClipsToBounds:NO];
you can resize the parent view according to the child view frame
UIView *parentView = [[UIView alloc]initWithFrame:[CGRectMake(0,0,100,100)]];
UIView *childView = [[UIView alloc]initWithFrame:[CGRectMake(0,0,0,120)]];
[parentView addSubview:childView];
parentView.frame = CGRectMake(0,0,childView.frame.size.width,childView.frame.size.height);
If AutoLayout is an option for you I would recommend looking into intrinsic content size. You can set the constraints so that the parent view will resize according to the content (childView) in Interface Builder. There is a very good tutorial on AutoLayout on Ray Wenderlich
You can create a custom UIView and override the addSubView method, in your addSubView override implementation you can check the size of the subview being added if needed and resize the current view.
#implementation CustomView
- (void)addSubview:(UIView *)view {
if(!CGSizeEqualToSize(self.view.size, view.size)) { // Sizes don't match
// resize self.view here
}
}
#end
I am trying to create a UIScrollView programatically. I set a property and synthesize it.
#property (weak, nonatomic) IBOutlet UIScrollView *topScrollView;
#synthesize topScrollView;
I then have a method that does this.
[topScrollView setFrame:CGRectMake(320, 0, 320, 65)];
[topScrollView setContentSize:CGSizeMake(500, 100)];
[topScrollView setBackgroundColor:[UIColor greenColor]];
[topScrollView setScrollEnabled:YES];
[topScrollView setShowsHorizontalScrollIndicator:YES];
[topScrollView setShowsVerticalScrollIndicator:NO];
[[self view] addSubview:topScrollView];
I put this in viewDidLoad.
This does not create the scroll view. I think it is because the scroll view has not been initialized. I can do the allocation and initialization in the above method but then when I want to use it in another method it wont work. I looked at Programmatically added UIScrollView used in multiple methods but did not help too much. There is probably a simple solution that I am not aware of. What can I do to programmatically create this scroll view and be able to use it in another method(mainly to conduct animations with it).
Thanks,
Ivan
I think it is because the scroll view has not been initialized.
Right.
I can do the allocation and initialization in the above method but then when I want to use it in another method it wont work.
It will if you assign your newly minted scroll view to a property or instance variable. That's what they're for.
Oh, one other thing. You'll need to make sure that your scroll view is retained somehow. That means changing your topScrollView property to strong, or adding it to a view (which will then retain it), or both.
Simple Method:
You can created multiple times if you need means
- (void)scrollView
{
int x = 0;
int y = 10;
for(int i=0; i<5; i++)
{
UIScrollView *scrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(x, y, 50, 50)];
scrollview.showsVerticalScrollIndicator=YES;
scrollview.scrollEnabled=YES;
scrollview.userInteractionEnabled=YES;
scrollview.backgroundColor = [UIColor greenColor];
[self.view addSubview:scrollview];
//scrollview.contentSize = CGSizeMake(50,50);
x=x+55;
}
}
You can use below code to add UIScrollView on yourView :-
Step 1:
Delegate "UIScrollViewDelegate" to your ViewController.h
for example:
#interface yourViewController:UIViewController<UIScrollViewDelegate>
Step 2:
//create you UIScrollView
UIScrollView *MyScrollVw= [[UIScrollView alloc]initWithFrame:CGRectMake(0 ,0 ,320 ,480)];
MyScrollVw.delegate= self;
[MyScrollVw setShowsHorizontalScrollIndicator:NO];
[MyScrollVw setShowsVerticalScrollIndicator:YES];
MyScrollVw.scrollEnabled= YES;
MyScrollVw.userInteractionEnabled= YES;
[yourView addSubview:MyScrollVw];
MyScrollVw.contentSize= CGSizeMake(320 ,1500);//(width,height)
Step 3:
you want to implement the scrollView Delegates in ViewController.m
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return imgView;
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSLog(#"Did end decelerating");
//do your code here
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(#"Did scroll");
//do your code here
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
NSLog(#"Did end dragging");
//do your code here
}
-(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{
NSLog(#"Did begin decelerating");
//do your code here
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
NSLog(#"Did begin dragging");
//do your code here
}
The straightforward programmatically way in SWIFT
To wrap it up
Create a UIScrollView
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
Use a Single Child View to Hold All of Your Content Subviews
let contentView = UIView()
contentView..translatesAutoresizingMaskIntoConstraints = false
Usually, you only want your content to scroll in one direction. In most cases to scroll vertically. Therefore set the width of the content view to be the width of the scroll view.
NSLayoutConstraint.activate([
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
Attach four constraints (top, bottom, left, right) from our single content view to the scroll view.
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
Make sure you have constraints attached to all four sides of the content view so that it will expand to the size of your content.
// After Adding your subviews to the contentView make sure you've those two constraints set:
firstSubView.topAnchor.constraint(equalTo: contentView.topAnchor),
.
.
.
lastSubView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
Reference: Using UIScrollView with Auto Layout in iOS
I have a view controller with a button. When the button is pressed, I want to add a subview which contains a scrollview. Right now my code displays the subview and scrolls fine as long as I don't add the xib. When I add the xib to the scrollview, the xib appears in the subview but there is no longer any scrolling.
The main View Controller:
-(IBAction)startNewSearch:(id)sender {
UIScrollView *myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 600)];
UIView *myView = [[[NSBundle mainBundle] loadNibNamed:#"NewSearch" owner:self options:nil] objectAtIndex:0];
[myScrollView setScrollEnabled:YES];
[myScrollView setContentSize:CGSizeMake(320, 600)];
[myScrollView setShowsVerticalScrollIndicator:YES];
[myScrollView setShowsHorizontalScrollIndicator:YES];
[myScrollView setPagingEnabled:NO];
[myScrollView addSubview:myView];
[self.view addSubview:myScrollView];
}
The NewSearch class is a UIView. It's xib is 320 wide by 600 high.
I'm not sure if I understood your question exactly, but it may or may not be similar to something I did.
See if adding this will work:
-(void)viewWillAppear:(BOOL)animated {
[self.myScrollView setFrame:CGRectMake(0, 0, 320, 600)];
}
Sorry if this isn't what you're looking for... I too am having issues with scrollview stuff. Good luck!
This happens because you have same content size height as a frame height.
Try to use same frame size as your main view on your screen and content size of the scroll view should be bigger then height (in your case) or width (this depends on which scroll you need horizontally or vertically).
For example
CGRect scrollFrame = CGRectMake(0, 0, [self.view bounds].size.height, self.view bounds].size.width);
UIScrollView *myScrollView = [[UIScrollView alloc]initWithFrame: scrollFrame];
...
[myScrollView setContentSize:CGSizeMake(320, **800**)];
As you see there is height of content size bigger then frame height of the your scroll view. So it can scroll horizontally.
Also see the UIScrollView documentation.
I encountered a similar problem when I started using ios8. It turns out that touches were being trapped by something in the chain of view controllers. When I started using presentView Controller for the view controller containing the scrollview, then touches (and scrolling)started working again.