iOS Swift : ScrollView strict dragging - ios

I have a scrollView(only horizontal scrolling) in which two collection views and want that if it is dragged/Swiped upto >= mid of screen then it should scroll forward i.e right side (show 2nd collection view) else it should be in left side(show first collection view). It should not stay half scrolled either full or none. How can i make this possible?

To achieve a scroll snap, you want to use this UIScrollViewDelegate method:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
You'll want to set the following within this method.
targetContentOffset.pointee.x =
Here's a tutorial link that may help explain.
Or just convert this ObjC SO answer to swift and change from vertical snapping to horizontal as it describes.

Related

Get default scroll direction for UIScrollView Swift

I have an application that uses more UIScrollViews and extensions from it like UICollectionViews and UITableViews and for a little dynamism I have created some general functions to help me with some paddings / margins.
My functions are created as extensions for UIScrollView and I want to use them just when the scroll view is only vertical.
My Question
How can I find the scrolling direction of a UIScrollView?
I have found a lot of answers of how to find the scrolling direction, but I need when the UIScrollView is initialised to find the scrolling direction of it, if it's vertical or horizontal.
Thank you for your time!
One solution I can think of in order to get the scroll direction before scrolling is to react accordingly to the type of UIScrollView in question.
So first step check if it is a UIScrollView, UICollectionView or UITableView.
In the case of a UITableView
I think a fair assumption here is that the scrolling direction will be vertical
In the case of a UIScrollView
This one could be tricky but I guess here you would have to compare the content size of the scroll view with the frame of the scrollview as Desdenova suggested and this can suggest if you can scroll horizontally and / or vertically.
In the case of a UICollectionView
This data will lie in the in the layout of the UICollectionView.
For example, I set up a basic UICollectionView in Storyboard using a FlowLayout without any data in it.
Then I add this code somewhere appropriate
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
{
if layout.scrollDirection == .horizontal {
print("horizontal")
}
else {
print("vertical")
}
}
This prints out horizontal.
For the UIScrollView you have to use the UIScrollViewDelegate scrollViewDidScroll which is helps you in UIScrollView's Scroll direction also for that you have to add some checks for the get the directions:
func scrollViewDidScroll(scrollView: UIScrollView!) {
// Update ScrollView direction
if self.lastContentOffset.y > scrollView.contentOffset.y && self.lastContentOffset.y < scrollView.contentOffset.y {
// Vertical Scroll
} else {
// Horizontal Scroll
}
}

How to change UIScrollView with isPagingEnabled autoscroll drag trashhold

I have horizontal UIScrollView with isPagingEnabled = true containing few pages. If I drag scrollview content and release finger it scrolls to next page only if I dragged at least 50% of scrollview width. I want to auto scroll to next/previous page if drag distance is more than 25%.
I was able to achieve it by overriding scrollViewDidEndDragging in UIScrollViewDelegate, calculating drag distance and calling scrollView.setContentOffset. But issue is that if distance > 25 and < 50 then it scrolls back automatically probably because scrollview calls it's default implementation.
Any idea how can I achieve this? Thanks
I would use the following delegate's callback by modifying offset to desired page
// called on finger up if the user dragged. velocity is in points/millisecond.
// targetContentOffset may be changed to adjust where the scroll view comes to rest
#available(iOS 5.0, *)
optional func scrollViewWillEndDragging(_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>)

iOS: can I programmatically decide what component to interact with (scrolling)?

I'm in a situation where I have two scrollable views, one horinzontally and the other vertically. Is there a way to detect if the user did a vertical or horizontal gesture, and depending on that, choose the view to interact with?
Thank you for your help.
You can use scrollViewWillBeginDragging from UIScrollViewDelegate to get the direction on which your scroll will go.
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview)
if translation.y > 0 {
// swipes from top to bottom of screen -> down
} else {
// swipes from bottom to top of screen -> up
}
}
But since this method doesn't return a scroll view, you will only know which scroll was dragged and to which direction.
Please see if isDirectionalLockEnabled helps.
This helps to lock the scrolling direction.
If this property is YES and the user begins dragging in one general direction (horizontally or vertically), the scroll view disables scrolling in the other direction. If the drag direction is diagonal, then scrolling will not be locked and the user can drag in any direction until the drag completes.

How do I find UITableview scroll difference - swift

How to find the scroll difference of a UITableView.
I need to find the difference of the Tableview content scroll from the tableview top position in swift
I tried the below code,
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let contentOffset = tableview.frame.origin.y
let maximumOffset = (contentOffset - scrollView.contentOffset.y)
let dif = maximumOffset
}
Contents offset of tableview, itself describe as difference between top of content to current scroll position.
Try this and see:
print(tableView.contentOffset)
For more, see Apple Document - contentOffset
contentOffset : The point at which the origin of the content view is offset from the origin of the scroll view.
Also look at this refernce:
Understanding of Content Offset
A UITableView is a subclass of UIScrollView, so it has a contentOffset property.
When you're learning about a class, remember to check it's parent class. Sometimes the properties/methods you're looking for are in the parent. (I'm as guilty of forgetting to check the interface of parent classes as anybody.)

UICollectionView Scroll to next item

The idea is replacing PageController with UIScrollView, UIScrollView should only scroll to the next/previous item and stop. I've found a few solutions, but I've only understood that I've to use targetContentOffsetForProposedContentOffset, but have no idea what CGPoint should I return and how to stop on the next item even if user scrolls with high velocity.
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
return CGPoint(x: 0, y: 0)
}
Use below of code. Your problem will be solved.
YourScrollView.pagingEnabled = YES;
With UIScrollView, you can enable paging. The property is called pagingEnabled. This means if it will snap to full widths (or heights) providing you set the content size properly.
i.e. If you want 2 pages and have a width of 100 and height of 200. You set the content size to be CGSize 200 for width and 200 for height. The scroll view will handle the snapping and paging.
If you want to have a function to go to a page like goToPage(2). Then you just need to call scrollRectToVisible method in UIScrollView with a CGRect of (pageNumber * scrollView.width (or page width), 1 height)
It looks like you are using Swift, so your implementation may vary.

Resources