How can I detect when iOS ScrollView is at the very top? - ios

How can I detect when the user scrolled to the very top of my collectionView?
I tried to use this code:
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if collectionView.contentOffset.y <= collectionView.contentSize.height - collectionView.frame.size.height {
print("top")
}
}
But it prints "top" even if I didn't get to the top.

scrollViewDidEndDragging means the user's finger lifted, but because it has physics to simulate inertia, the view may continue to move. There is another delegate method for exactly what you are looking for: scrollViewDidScrollToTop which as the name implies fires when you get to the top of the scrollview.
EDIT:
you can also try:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y <= 0 {
print("top!")
}
}
EDIT third time's the charm? This one only fires once, after the scroll view has stopped moving, if you are at the top.
override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y == 0 {
print("top!")
}
}

You can try
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y == 0 {
// top
}
}

Related

Crashlytics report not clean

this is a function implementation I cant see anything that make app crash
`
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y <= 0 {
//reach top
loggerDebug.info("Scroll view reach to top")
availableRobomartListTV.isScrollEnabled = false
// Add gesture to view if scroll reach to top
view.addGestureRecognizer(gesture)
}
}
`

How do I control the whether a function will happen depending on the speed that a tableView is scrolled

I want an action to occur if a user scrolls down at any speed, or if a user scrolls up at a fast speed (or reaches the top of the view controller). I am using the following code below to sense any movement and implement the function where the "did move up" and "did move down" comments are, but I want to limit the did move up to occur only when scrolling fast or the user reached the top of the tableView. How do I do this?
// we set a variable to hold the contentOffSet before scroll view scrolls
var lastContentOffset: CGFloat = 0
// this delegate is called when the scrollView (i.e your UITableView) will start scrolling
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.lastContentOffset = scrollView.contentOffset.y
}
// while scrolling this delegate is being called so you may now check which direction your scrollView is being scrolled to
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.lastContentOffset < scrollView.contentOffset.y {
// did move up
// I want this to only occur is the user is scrolling fast
} else if self.lastContentOffset > scrollView.contentOffset.y {
// did move down
} else {
// didn't move
}
}
I suppose you can store the time when scrollViewWillBeginDragging is called and then measure up the time difference against a certain amount of time in scrollViewDidScroll
var timeScrollingBegan: Date?
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
// ...
timeScrollingBegan = Date()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.lastContentOffset < scrollView.contentOffset.y {
// Calculate time difference in milliseconds
let timeDifference = Date().timeIntervalSince(timeScrollingBegan) * 1000
let movementDifference = scrollView.contentOffset.y - lastContentOffset
// If the movement difference is past a certain threshold
// in a certain amount of time, then it is too fast. It will
// take a bit of trial and error to determine the correct threshold
}
// ...
}
// You can probably use scrollViewDidEndDecelerating here instead
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
timeScrollingBegan = nil
}

Easiest way to disable back scrolling in scrollview

I want to stop backward scrolling on ScrollView after user scrolls to the next page. How can I do that.
I tried the following two codes, but the first one does not have any effect
self.scrollView.contentOffset = CGPointMake(self.view.frame.width,0)
and the second only disables the forward scrolling.
self.scrollView.contentSize = CGSizeMake( 2 * scrollWidth, scrollHeight);
To disable scrolling in one direction you implement the UIScrollViewDelegate method scrollViewDidScroll and put your logic there. For instance this TableViewController can only ever scroll down, because if the user tries to scroll up, we just overwrite the contentOffset, effectively undoing their scroll before they see it.
class ViewController: UITableViewController {
var lastScrollPosition = CGPoint.zero
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard scrollView.contentOffset.y > lastScrollPosition.y else {
scrollView.setContentOffset(lastScrollPosition, animated: false)
return
}
lastScrollPosition = scrollView.contentOffset
}
}
If your cell is equal in size to your screen, you can apply the following option, which is very smooth:
var lastScrollPosition = CGPoint.zero
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView.contentOffset.x == lastScrollPosition.x + UIScreen.main.bounds.width {
lastScrollPosition.x += UIScreen.main.bounds.width
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard scrollView.contentOffset.x > lastScrollPosition.x else {
scrollView.setContentOffset(lastScrollPosition, animated: false)
return
}
}

content offset doesn't work

I am trying to set the content offset in my uiscrollview. I have tried the following, and none of it works. None of the following affect my scrollView in any way, it simple appears on the screen as normal.:
let point = CGPoint(x: 0, y: self.view.frame.height / 2)
self.scrollView.setContentOffset(point, animated: true)
and:
self.scrollView.contentOffset.y = self.view.frame.size.height / 2
and:
self.scrollView.contentOffset = CGPointMake(0, self.view.frame.size.height / 2)
and:
self.scrollView.contentOffset = CGPointMake(0, scrollView.frame.size.height / 2)
I have a scroll view that is 2 times the height of my view. They are essentially separated into 2 different view that I can page between. I want the scrollview to start on the bottom part.
You should try them in the viewDidLayoutSubviews
Ref: iOS 9 scroll UITextView to top
I was really scratching my head when I found that setting scrollView.contentOffset to any value was not working. Eventually I realized that I was calling the scrollView delegate message 'scrollViewDidScroll' to manage scroll dragging peculiarities.
It turns out that 'scrollViewDidScroll' is called whenever the scrollView contentOffset is changed, and my code to manage drag issues was changing the contentOffset. I just made a 'BOOL isDragging' variable to only make changes to the contentOffset when dragging:
private var isDragging : Bool = false
private var initialContentOffset = CGPoint.zero
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isDragging = true
...
}
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
// need to keep track if we are dragging with isDragging
// since this 'scrollViewDidScroll' API is called with ANY contentOffset change
if (isDragging == true){
// do stuff to contentOffset to manage dragging peculiarities
...
}
}
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if (decelerate == false){
scrollViewDidEndScrollingAnimation(scrollView)
}
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
scrollViewDidEndScrollingAnimation(scrollView)
}
public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
isDragging = false
}

Swift - UITableView scroll event

I was wondering how to detect if the UITableView is scrolled (up or down).
I want to hide the keyboard when the UITableView is scrolled with self.view.endEditing(true).
Thanks in advance
You can set property of UITable view (XCode 7+)
In Storyboard:
in Code:
tableView.keyboardDismissMode = .onDrag
You can add UIScrollViewDelegate. After that you can implement scrollViewDidScroll method.
I believe the complete solution would be the following:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == feedTableView {
let contentOffset = scrollView.contentOffset.y
print("contentOffset: ", contentOffset)
if (contentOffset > self.lastKnowContentOfsset) {
print("scrolling Down")
print("dragging Up")
} else {
print("scrolling Up")
print("dragging Down")
}
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if scrollView == feedTableView {
self.lastKnowContentOfsset = scrollView.contentOffset.y
print("lastKnowContentOfsset: ", scrollView.contentOffset.y)
}
}
The previous answers weren't 100% accurate.
Explanation: scrollViewDidEndDragging will be called when the scrolling stops, therefore we save the last know offset. After that we compare it with the current offset in the delegate method scrollViewDidScroll.
override func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if(velocity.y>0){
NSLog("dragging Up");
}else{
NSLog("dragging Down");
}
}

Resources