UIScrollView disable scrolling when removeFromSuperView - ios

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.

Related

In iOS App, how to scroll two UIView simultaneously

I am developing iOS App.
I add UITextView(100px height) on top of UIWebView and would like to make them scroll simultaneously.
I am writing down the following code. However, when I scroll my screen, only UIWebView is scrolled and UITextView isn't.(UITextView is fixed!)
I hope that when I scroll up my screen, both UIWebView and UITextView go up, and vice versa.
Could you tell me how to solve?
#interface DetailViewController ()<UIWebViewDelegate>{
UITextView *recommendText;
}
#property (weak, nonatomic) IBOutlet UIWebView *detailPage;
- (void)viewWillAppear:(BOOL)animated{
[self headerMake];
}
-(void)headerMake{
recommendText = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 320,100)];
recommendText.layer.borderWidth = 2;
recommendText.text = #"hogehoge";
[self.detailPage addSubview:recommendText];
[[self.detailPage scrollView] setContentInset:UIEdgeInsetsMake(100, 0, 0, 0)];
}
A text view is a scroll view subclass, and web views have a scrollView property.
Listen to both scroll views content offset change (using scrollViewDidScroll:) and update the content offset of the other scroll view accordingly. This will give you the effect of scrolling the two at the same time.
self.textview.delegate = self;
self.webview.scrollView.delegate = self;
...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(scrollView == self.textview)
{
self.webview.scrollView.contentOffset = self.textview.contentOffset;
}
else
{
self.textview.contentOffset = self.webview.scrollView.contentOffset;
}
}
If i understand your question correctly you should embed them both is a scroll view and disable scrolling in the UIWebview and the UITextView. then they will scroll as one. Although you may have to dynamically set the sizes of the Textview and webview if they have different content they have to support.

Scroll the text in UITextview when texts are less and height of UITextview is large

I have one UITextView whose height is 568 (means fit in screen size) and if i write 50 lines in it then it will definitely scroll vertically.
But i want to scroll (or just bounce) when there is only one line of text.
When user scroll Vertically then the text will just bounce in UITextView.
in my application the UITextView is not Editable.
Any idea, code,link will be great help...
EDIT:
The UITextView's height will be that 568 only.
it will not change (means without changing the height of UITextView, set this thing).
[txtView setContentOffset:CGPointMake(0, 1000)];
It is not working too...
If you want to scroll TextView text that not Larger then it height . then you can't do this. you wont getting scroll bar if your textView's Text not larger then its frame height.
Setting [txtView setContentOffset:CGPointMake(0, 1000)]; wont work anymore if that data in not longer then textView's height.
UPDATE:-
Here it is i got one trick. If textview not editable and you just want to scroll it try to add your Textview in to one scrollviw. Like Bellow i got this working.
in .h class
#property(nonatomic,retain)IBOutlet UITextView *textvie;
#property(nonatomic,retain)IBOutlet UIScrollView *sceoll;
in .m class
- (void)viewDidLoad
{
[sceoll setContentSize:CGSizeMake(0, 500)];
[textvie setTextAlignment:NSTextAlignmentCenter];
textvie.editable = FALSE;
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
textvie.contentInset = UIEdgeInsetsMake(10, 0, 10, 0);
} else {
textvie.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
}
[super viewDidLoad];
}
in xib
and the result is:-
Set the frame of UITextView
CGRect frame = textView.frame;
frame.size = textView.contentSize;
textView.frame = frame;
See: UITextView change height instead of scroll

Page scrolling not working with Autolayout enabled

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.

Creating UIScrollView Programmatically

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

UIButton does not work in uiscrollView

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.

Resources