UIScrollView unwanted scrolling after addSubview or changing frame - ios

I have a UIScrollView filled with subviews, all is well when creating it and initially filling it.
But when I add a new subview that is positionned outside of the visible screen portion, or when I just resize an existing subview that is also outside of the visible screen portion, there is a subsequent 0.3s-long scroll animation (I can see it happening from my delegate) that seems to match the newly added/resized element.
Attempts:
pagingEnabled is always NO.
Setting scrollEnabled to NO during subview manipulations doesn't help.
Doing a setContentOffset:animated:NO after subview manipulations doesn't prevent the animation.
One single giant subview with all my subviews in it doesn't help.
My current workaround is to initially set the frame to fit inside the visible screen portion, or doing resizing work inside another superview, but it feels dirty, and won't handle all situations...
Is there a way to prevent this automatic scrolling animation when programmatically manipulating subviews?
Xcode 4.3, iOS SDK for 5.1.

I too discovered this problem and found this solution http://www.iphonedevsdk.com/forum/iphone-sdk-development/94288-disabling-uiscrollview-autoscroll.html
It involves subclassing the UIScrollView and entering no code in the following method.
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
}
Like the guy says on the link I've found it works and no problems so far. Hope it works for you.

I had this problem because I set the content size of the scroll view prior to adding the subview.
As soon as I change the code so that the content size of the scroll view was set after adding the subview the problem went away.

Related

UIScrollView includes extra space at bottom

I have a UIScrollView which continually adds extra space at the bottom of its scroll area on iOS 7. If I rotate the device, the problem fixes itself, however, before rotating after first navigating to the view controller, the extra space always appears. I've included an image below:
What I've tried:
Set automaticallyAdjustScrollViewInsets to NO
Checked contentSize, contentOffset and contentInset. All appear fine.
I'm not sure what else to try to solve this issue, and would greatly appreciate any help or direction here!
Edit: As another layer of complexity to this issue... I call a method, updateScrollViewContentSize in my viewDidAppear: method. When I rotate, and it somehow fixes itself, this same method is called. So my contentSize is being set when my view appears and when I rotate.
To make things worse, the content size is always set to 638... Whether there is extra space or not. But, for some reason, the scrollView ignores this until we rotate.
Here is the method to update the contentSize:
- (void)updateScrollViewContentSize {
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width, (self.feedbackFooterView.frame.origin.y + self.feedbackFooterView.frame.size.height + 20))];
}

iOS - viewDidLayoutSubviews called before auto-layout completed on iOS7

We're currently having a problem that only seems to affect iOS7 devices.
Within our .xib file we have two views within a container view (i.e.: not at the top level of the view hierarchy) that need to be circular on display. The views have constraints applied to their position and horizontal spacing within the container, and an aspect ratio condition requiring they are square. The views should expand in width/height on larger screen sizes, respecting the constraints described.
In our VC, we have the following in viewDidLayoutSubviews to force these views to appear circular:
- (void)viewDidLayoutSubviews {
self.progressContentContainerView.layer.cornerRadius = self.progressContentContainerView.frame.size.width/2;
}
This seems to work fine on iOS8, however on iOS7 there is a period after the view has been displayed where the constraints have not yet been applied and the size of the view/views is incorrect (see attached screenshots). This resolves itself and correctly renders a circle after half a second. This only appears to happen when the views that we intend to be circular are NOT at the top level of the VC's view hierarchy which seems to imply that viewDidLayoutSubviews is called before the subviews of subviews have also been laid out.
My guess is that we could potentially fix this issue by subclassing UIView for the nested container, adding references to the circular view within this subclass and overriding viewDidLayoutSubviews here to make the cornerRadius adjustment. This seems like a bit of a workaround though and I'm interested to see if there are other options.
Is there a cleaner/more idiomatic solution to this problem?
I know this is an old question but have you tried calling either:
[self.progressContentContainerView setNeedsUpdateConstraints];
or:
[self.progressContentContainerView layoutIfNeeded];

Unresponsive area in UITableView in landscape orientation

I'm developing an iPad application where I have a screen with UITableView hosted on UIScrollView. UITableView's leading space and trailing space is being pinned to superview.
I'm using Autolayout in my project.
When this screen appearing in landscape mode or rotated to it all visible elements of UITableView being resized correctly. However area after x=768pt is being untouchable. It's definitely area because beginning of editable elements (text view and text field) are being touchable.
I checked contentSize of table, it's being OK (1024 in my case).
Also when I rotate iPad from landscape to portrait contentSize of table still stays landscape (1024). I tried solution from this topic: bug in UITableView layout after orientation change and it worked. Don't know if this is connected to my issue.
I tried to place regular view instead of my UITableView. On this view after rotation touch area was OK. However when I placed my table on this view right area still was unresponsive.
Table's property clipsToBounds set to YES so it seems that content is not becaming outside of UITableView.
Please point to what may cause this issue. Right now I'm completely out of ideas what may cause this.
I found a solution. The problem was in overriden method -(void)layoutSubviews in my custom cell. I simply forgot to call [super layoutSubviews] in it.
Never forget to call [super layoutSubviews] in any non-standard view.
Hope my solution will help someone not to waste hours on simple issue.

Showing scroll indicators on a UIScrollView when programmatically scrolling

EDIT: The crux of this problem is that scroll indicators do not show during programmatic scrolling, but I would like them to. My original question (provided below) assumed this had something to do with userInteractionEnabled, but it does not. The mention of a master and slave UIScrollView is also possibly distracting from my core problem (the need to show scroll indicators during a programmatic scroll). Apologies to those of you who answered or commented based on my misleading assumptions/info.
Possible Solution: The only way I found to do this was to use the fact that scroll indicators are instances of UIImageView and use a category on it to hack the alpha. This article shows the approach. It was then a case of using tags and scroll view delegate methods to turn the alpha permanently on prior to a programmatic scroll, and permanently off when the scroll is finished. This feels hacky though, so any further suggestions would be welcome!
Everything below this line is the original unedited question to provide context to users' answers and comments
Setting userInteractionEnabled in a UIScrollView object to NO appears to disable the scroll indicators upon programmatic scrolling. This happens even if you have self.showsVerticalScrollIndicator = self.showsHorizontalScrollIndicator = YES;
Is there any way to programmatically scroll the scroll view but still show the indicators?
(To provide some context: I have a slave scrollview that mimics a master scrollview by hooking up the scrollview delegate callbacks and passing the content offset to the slave scrollview. However, I don't want the user to be able to directly manipulate the slave scrollview, but I do want scroll indicators).
Instead of setting userInteractionEnabled to false try setting the UIScrollView's scrollEnabled property to false. The doc. says "When scrolling is disabled, the scroll view does not accept touch events" that should mean that you should still be able to programmatically scroll the UIScrollView. Hope this helps - Did not test it out let me know.
You could try putting a transparent UIView (alpha == 0.0) over your scroll view (but as a sibling in the view hierarchy, not as a subview). Set touchesEnabled to YES on the transparent view, and it will intercept touches heading for the scroll view.

UITableView in storyboard not updating content size on rotation

I'm working on project targeted for iOS 6 that leverages storyboards and auto layout. In the storyboard there are many places where a UITableView is added as a subview to a view controllers view. This table view uses prototype cells from the storyboard.
The issue we're running into is that if the view controller is initially loaded in landscape orientation and the device is then rotated to portrait, the table view begins to scroll both vertically and horizontally. The table views cells are drawn with the correct dimensions but there is additional white space to the right.
It appears that while the frame and bounds of the table view are being updated to the correct size on rotation, the table views content size is not. Regardless of any update rotation change the content size remains the same dimensions.
The issue doesn't present itself if programatic table view cells are used.
A few garish work arounds I've found, 1.) calling reloadData or reloadRowsAtIndexPaths:withRowAnimation: 2.) manually setting the property contentSize.
Both of these seem less than ideal.
I've added this
link to a dead simple sample project which demonstrates this issue. The only changes made are to the storyboard and the main view controllers implementation.
Before rotation
After rotation
I'm having the same issue - can't seems to find any documented answer related to this. I ended up manually modifying the UITableView contentSize like you mentioned in:
- (void) viewWillLayoutSubviews
{
self.tableView.contentSize = CGSizeMake(self.tableView.frame.size.height, self.tableView.contentSize.height);
}
I ran into this issue today and filed a bug report with Apple.
Appears that if you are using a custom cell with a UI element AND autoLayout, the UIScrollView content size is having problems.
If you remove all UI elements, OR turn off autoLayout, OR use a factory cell (basic, etc), all works fine.
Same issue I have rectified in my project.
I guess this is a bug in Storyboard.
Then I have solved it by manual coding in willAutorotate method by setting
tableview.contentsize = CGSizeMake(tableview.width, tableview.contentsize.height);
Hope this will work for you as well.
If you find any apple documentation regarding the same then please update me as well. Till then you can use the same solution.
Appears that if you are using a custom cell with a UI element AND autoLayout, the UIScrollView content size is having problems.
I had to turn off AutoLayout for my custom UITableViewCells to be able to scroll to the bottom on updating the data and then [self.tableView reloadData].
With AutoLayout turned on, the tableView.contentSize was being updated, but I still wasn't able to scroll to the bottom unless I rotated the device.
I found the following to work for me:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableView.contentSize = CGSizeMake(self.tableView.frame.size.width, self.tableView.contentSize.height);
});
}
Notice the async dispatch: if that line would be executed synchronously then the contentSize change would trigger another layout pass before the current one would have completed. This triggers an exception:
Auto Layout still required after sending -viewDidLayoutSubviews to the
view controller.
Usage of Constraints helped me. Since you are using Storyboards, it is really easy to set Constraint values for all edges, so UITableView will always fill the whole ViewController (of course if UITableView fills whole ViewController) regardless of device orientation.
I had the same problem.
I found this link. When I tried to implement this I did not find the Auto-sizing attributes for my view then I clicked on Master View Controller and then clicked on the File Inspector and uncheck Use Autolayout and then go to Attributes inspector auto-resizing should be there then you can change the attributes how you want it.
I am sure you must have managed to figure this out.

Resources