iOS - scrollViewDidEndDecelerating runs for both scrollView and collectionView - ios

I have a VC that contains a collectionView and a scrollView. I put this code to change current page of pageController by scrolling in scrollView :
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
self.pageController.currentPage = Int(pageNumber)
}
It works nice for scrollView but the problem is when i even scroll in collectionView it declares and causes unwanted changing in pageController!
What should i do?

In addition to the answers posted above, You can make use of the tag property of the view.
Just assign a tag (Int) to your scrollview either in xib or via code.
yourScrollView.tag = 10
And in the scrollview delegate method check for this tag:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView.tag == 10 {
///Your scrollview was scrolled
} else {
// Collection view was scrolled
}
}

if scrollView == yourScrollView{
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
self.pageController.currentPage = Int(pageNumber)
}
check if the instance running the method is actually your scrollView

First you have to understand bit detail about UICollectionView. The UICollectionView is subclassed from UIScrollView. That's why its getting called for both the scrolling (Scrolling collection view and scrolling scroll view). You can do like this to differentiate what type of scrolling it is,
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView == "Your scrollView outlet name" { // Scroll view
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
self.pageController.currentPage = Int(pageNumber)
} else {
// Collection view
}
}
Thanks.

You need to check the scrollView inside the scrollViewDidEndDecelerating if it is your scroll view or your collection view.
Just add an if scrollView == myScrollView before doing the 2 lines of code you have.
Your code shoudl look like this
func
scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView == myScrollView {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
self.pageController.currentPage = Int(pageNumber)
}
}

Related

iOS Unable to Disable Horizontal Scrolling when swipe the screen in scrollView?

In my application I have to implement ScrollView and page control, I used ScrollView for both vertical scrolling and horizontal scrolling. when I drag the screen with scroll horizontal means it works fine but when I drag the screen with scroll Vertical means it has some glitches like(scrolling both vertically and horizontally) unable to stop that or unable to find the issue.
So I decided to place two buttons named next and previous for horizontal scrolling for next page and previous page in page control so I want to stop horizontal scroll when dragging the screen, but I don't know how to stop horizontal scrolling(not vertical scrolling).
Here I have posted the code for Scrolling in page control and Next and previous button actions.
I have declared and called the ScrollView Delegate.
UIScrollViewDelegate
override func viewDidLoad() {
super.viewDidLoad()
configurePageControl()
scrollMainHolderView.delegate = self
scrollMainHolderView.isPagingEnabled = true
}
ScrollView Method is:
//MARK:- Scrollview delegate -
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControlNew.currentPage = Int(pageNumber)
self.scrollMainHolderView.contentSize=CGSize(width: self.view.frame.size.width * CGFloat(templateMutArray.count), height: CGFloat((globalYarr[Int(pageNumber)] as? CGFloat)!))
}
Set up code for Page control,
func configurePageControl() {
self.pageControlNew.numberOfPages = templateMutArray.count
self.pageControlNew.currentPage = 0
self.pageControlNew.tintColor = UIColor.red
self.pageControlNew.pageIndicatorTintColor = UIColor.black
self.pageControlNew.currentPageIndicatorTintColor = UIColor.green
}
Code for next and previous button action is,
#IBAction func pagePreviousBtnTapped(_ sender: Any) {
isHorizontalSCrolling = true
scrollMainHolderView.delegate = self
let scrollBounds = self.scrollMainHolderView.bounds
let contentOffset = CGFloat(floor(self.scrollMainHolderView.contentOffset.x - scrollBounds.size.width))
self.movScrollToFrame(contentOffset: contentOffset)
}
#IBAction func pageNextBtnTapped(_ sender: Any) {
isHorizontalSCrolling = true
scrollMainHolderView.delegate = self
let scrollBounds = self.scrollMainHolderView.bounds
let contentOffset = CGFloat(floor(self.scrollMainHolderView.contentOffset.x + scrollBounds.size.width))
self.movScrollToFrame(contentOffset: contentOffset)
}
From what i understand from the comments is that you want to stop horizontal scrolling. That is actually pretty straight forward.
You can stop horizontal scrolling or vertical scrolling in the ScrollViewDelegate Method. Here it is how,
Setting the contentOffset.x value to zero will prevent the scrollview scroll in horizontal direction.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
sender.contentOffset.x = 0.0
}

Move SubView of ChildViewController using scrollViewDidScroll

I am using a viewController to handle two ChildViewControllers, each containing a UITableView. Would it be possible to set the the position y of a SubView of viewController (e.g. a UILabel) depending on the scrollView.contentOffset of the current ChildViewController?
It works fine with its own subviews already,..
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.testConstt.constant = scrollView.contentOffset.y
}
Thanks for helping!
Just observe the correct scroll view using a conditional statement. I assume the scroll views of the children are table views, so you may do something like this:
let tableViewA = UITableView(...)
let tableViewB = UITableView(...)
let someScrollView = UIScrollView()
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == tableViewA {
// observe a specific table view's scroll view and do something
} else if scrollView == someScrollView {
// observe a specific scroll view and do something
}
}
Remember, UITableView is a subclass of UIScrollView so they can be treated the same in scrollViewDidScroll(_ scrollView:).

How to scroll two UITableViews symmetrically?

In my app I have two table views. Both are same height and width and same cell count.
I want when tableview A Scroll Simultaneously tableview B also scroll.
You can use scrollview delegate scrollViewDidScroll for this purpose. This will do the exact thing you want.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.tableA{
self.tableB.setContentOffset(self.tableA.contentOffset, animated: false)
}
else if scrollView == self.tableB{
self.tableA.setContentOffset(self.tableA.contentOffset, animated: false)
}
print("scrollViewDidScroll") // to check whether this function is called while scrolling
}
TRY THIS:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
<your tableView Name>.contentOffset = scrollview.contentOffset
}
As Tableview inherits from ScrollView. Try this.
FOR SWIFT 4:
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
<your tableView Name>.contentOffset = scrollview.contentOffset
}
Instead of using tableview you can use UIPickerView with two components.
If you need code let me know.

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
}
}

Detect when Scrollview Scrolling not tableview scrolling

I have a scrollview inside tableview (tableview's header) and I want to call this action when scroll finish:
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let pageNumber = round(bookScrollView.contentOffset.x / bookScrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
print("scroll")
}
when I scroll bookScrollView nothing happen, but when table view scroll this function run.
How I detect when bookScrollView scroll and run function?
thanks
Here, you can define, scrollOfTable, or you can also define TAG property. identify and only scroll when scrollview comes in, not tableview.
You also need to check, if your scrollView is setting delegate
self.vsScrollView.delegate = self
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if scrollView == scrollOfTable {
}
else if scrollView == scrollOfScrollView {
}
else {
//something else
}
}

Resources