How much a UIScrollView has been scrolled inside a UIPageViewController? - ios

I'm trying to figure out how much of the scroll view inside my UIPageViewController has been scrolled. I have the following code in the viewLoad that access the UIScrollView from UIPageViewController.
for (UIView *view in self.pageViewController.view.subviews)
{
if ([view isKindOfClass:[UIScrollView class]])
{
thisControl = (UIScrollView *)view;
}
}
So once I have the UIScrollView, called thisControl I would like to print how much has been scrolled by doing something like this:
NSLog (#"Scroll: %f",thisControl.contentOffset.x);
The problem, is that I don't really know where to put this line, or how print continuously how much has been scrolled.
Any idea?

Set the delegate to that controller(myScroll.delegate = self;) and then add this method:
- (void) scrollViewDidScroll: (UIScrollView *) scrollView
{
CGFloat y = scrollView.contentOffset.y;
NSLog(#"%f",y);
// some stuff
}

Related

Weird thing with WKWebView subviews

I have a viewController that holds WKWebView in his properties.
I made my viewController to implement UIScrollViewDelegate and in 'didScroll' put some code that wont let the scrollView scroll vertically.
like that:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, 0);
}
The disabling part is good I tried it on other scrollView and it works just fine.
I set the webView.scrollView delegate to be the viewController.
I also made a method that loop over all of the subViews of webView and if it comes across another scrollView it set the delegate of that scrollView to be the viewController.
After all that it still not working...
-(void)setDelegateForScrollViewsInView:(UIView *)view{
if (view.subviews.count > 0) {
for (UIView *subView in view.subviews){
if ([subView isKindOfClass:[UIScrollView class]]) {
[((UIScrollView *)subView) setDelegate:self];
[((UIScrollView *)subView) setShowsHorizontalScrollIndicator:false];
[((UIScrollView *)subView) setBackgroundColor:UIColor.blueColor];
}
[self setDelegateForScrollViewsInView:subView];
}
}I }
After View Debugger i found that my webView is build up in that hirarchy:
And my method cant catches the inside scrollView so the disabling of the vertical scroll won't work.
How can I fix it?

Exclude views from scroll view touch delay

How do you exclude specific views from having a touch delay in a UIScrollView when delaysContentTouches property is set to YES?
Here's what works for me. Subclass UIScrollView, and implement only this method:
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
NSLog(#"touchesShouldCancelInContentView");
if ([view isKindOfClass:[UIButton class]])
return NO;
else
return YES;
}

UIView on top of UIScrollview, pass through only scrolls, not taps

I have a UITableview with a subclass of UIVIew on top of a section of the table, like so:
-uitable--
|--uiview-|
|| ||
|| ||
|---------|
| |
| |
-----------
The view has the same superview as the tableview, but covers the tableview partially. There are a few buttons on the UIView. I want the user to be able to scroll on the view and subsequently move the tableview (as if he were scrolling on the table). But, if he taps a button on the view, I want that tap to register on the view, not get sent down to the tableview. Right now, I am overriding the view's - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method to always return NO, which works for the scrolling but has the effect of sending all touches down to the tableview, rendering my buttons ineffective. Is there any way for me to pass down swipe/pan gestures to the tableview but keep the tap gestures?
Thanks,
Instead of always returning NO from pointInside, check to see if the point intersects any of your UIButton subviews - and return YES if it does.
- (BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for ( UIView* sv in self.subviews )
{
if ( CGRectContainsPoint( sv.frame, point) )
return YES;
}
return NO;
}
EDIT: alternate solution
Per your comment you'd like the user to begin scrolling the UITableView with a touch-down on one of the subview buttons. To make this work you'll need to make the UIView that contains your buttons a subview of the UITableView.
By doing this the UIView will then begin to scroll along with the UITableViewCells. To prevent this you need to adjust the frame as scrolling happens, or possibly lock it in place using constraints.
- (void) viewDidLoad
{
[super viewDidLoad];
// instantiate your subview containing buttons. mine is coming from a nib.
UINib* n = [UINib nibWithNibName: #"TSView" bundle: nil];
NSArray* objs = [n instantiateWithOwner: nil options: nil];
_tsv = objs.firstObject;
// add it to the tableview:
[self.tableView addSubview: _tsv];
}
// this is a UIScrollView delegate method - but UITableView IS a UIScrollView...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[scrollView bringSubviewToFront:_tsv];
CGRect fixedFrame = _tsv.frame;
fixedFrame.origin.y = 100 + scrollView.contentOffset.y;
_tsv.frame = fixedFrame;
}

UIScrollView inside paged UIScrollView

I have UIScrollView (inner - UICollectionView to be honest) in VC which is in paged UIScrollView (outer). Both are horizontal.
When I scroll inner to edge (either left or right side) it starts passing touches to outer scroll and outer scroll starts scrolling.
How to avoid that kind of behaviour? I want outer scroll to not react on touches in inner scroll.
You can put an UIView under the outer UIScrollView, and set it to userInteractionEnabled to NO
I found out how to do this:
Subclass UIScrollView - this will be your outer scrollView
now the method:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
UIView *touchedView = gestureRecognizer.view;
CGPoint loc = [gestureRecognizer locationInView:touchedView];
UIView* subview = [touchedView hitTest:loc withEvent:nil];
if([[subview nextResponder] isKindOfClass:[MyInnerScrollVC class]]) {
return NO;
} else {
return YES;
}
}
and thats it

Redraw subviews after UIScrollView zoom

I've got a UIScrollView with a child UIView (CATiledLayer) - then I have a bunch more child views of that view (some of which are UITextViews)
After zooming everything is all fuzzy.
I have read various articles on the subject and they all seem to indicate that I must handle scrollViewDidEndZooming then 'do some transform stuff, mess with the frame and tweak the content offset'. Please can someone put me out of my misery and explain how this is meant to work.
Thanks in advance...
I had a similar problem where I needed zooming with text. Mine wasn't using the CATiledLayer, so this may or may not work for you. I also wasn't using ARC, so if you are, you'll have to adjust that as well.
The solution I came up with was to set the UIScrollViewDelegate methods as follows this:
// Return the view that you want to zoom. My UIView is named contentView.
-(UIView*) viewForZoomingInScrollView:(UIScrollView*)scrollView {
return self.contentView;
}
// Recursively find all views that need scaled to prevent blurry text
-(NSArray*)findAllViewsToScale:(UIView*)parentView {
NSMutableArray* views = [[[NSMutableArray alloc] init] autorelease];
for(id view in parentView.subviews) {
// You will want to check for UITextView here. I only needed labels.
if([view isKindOfClass:[UILabel class]]) {
[views addObject:view];
} else if ([view respondsToSelector:#selector(subviews)]) {
[views addObjectsFromArray:[self findAllViewsToScale:view]];
}
}
return views;
}
// Scale views when finished zooming
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGFloat contentScale = scale * [UIScreen mainScreen].scale; // Handle retina
NSArray* labels = [self findAllViewsToScale:self.contentView];
for(UIView* view in labels) {
view.contentScaleFactor = contentScale;
}
}
I hit the same problem and the code above didn't work for my case. Then I followed the documentation:
If you intend to support zoom in your scroll view, the most common technique is to use a single subview that encompasses the entire contentSize of the scroll view and then add additional subviews to that view. This allows you to specify the single ‘collection’ content view as the view to zoom, and all its subviews will zoom according to its state.
"Adding Subviews" section of https://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/UIScrollView_pg/CreatingBasicScrollViews/CreatingBasicScrollViews.html
I simply created an empty view and added my CATiledLayer and all other subviews to that empty view. Then added that empty view as the only child view of the scroll view. And, it worked like a charm. Something along these lines:
- (void)viewDidLoad
{
_containerView = [[UIView alloc] init];
[_containerView addSubView:_yourTiledView];
for (UIView* subview in _yourSubviews) {
[_containerView addSubView:subview];
}
[_scrollView addSubView:_containerView];
}
-(UIView*) viewForZoomingInScrollView:(UIScrollView*)scrollView {
return _containerView;
}

Resources