I want to implement the following sort of view where the view can be completely scrolled and houses 2 different scrollview (Main and the secondary) with infinite scrollable content. This represents the exact thing I want.
The red view is superview - should scroll vertically
The green view is of the height of the current view and is just static. That doesnt scroll
The blue view is the horizontal scrollview where for each label there is a yellow vertically scrolling infinity collection view
the labels scroll as in the given video. under each label there is the collection view I mentioned in point 3
The blue box is the scroll view and I want the scrolling to happen horizontally in a parallax way such as this.
I am able to implement the above parallax in the correct fashion but each title contains their own collectionview. When I implement this I am not able to have an infinite scroll. Below is the code for that :
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == containerScrollView {
for i in 0..<shotsData.count {
let label = scrollView.viewWithTag(i + tagValueL) as! UILabel
let view = scrollView.viewWithTag(i + tagValueV) as! ShotsMediaView
let scrollContentOffset = scrollView.contentOffset.x + scrollView.frame.width
let viewOffset = (view.center.x - scrollView.bounds.width/4) - scrollContentOffset
label.center.x = scrollContentOffset - ((scrollView.bounds.width/4 - viewOffset)/2)
}
}
}
How can I exactly achieve the same behavior with an infinite scroll vertically? I want each of these titles to have collectionview that have the dynamic height each.
I did a crude implementation of this.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == colorsCollectionView {
let newContentOffSetX = scrollView.contentOffset.x
let distance = contentOffSetX + newContentOffSetX
// Scroll the text collection view proportinately
let titleScrollDistance = (distance/colorsCollectionView.frame.width * 75.0)
titlesCollectionView.contentOffset = CGPoint(x: titleScrollDistance, y: titlesCollectionView.contentOffset.y)
contentOffSetX = newContentOffSetX
}
}
contentOffSetX is a property of the class(ViewController) that I use to keep track of the scrolling distance of the bottom collection view. Initially that is set to 0. When the user scrolls the collection view at the bottom, the above delegate method is called. Then I use the contentOffSet to get the distance that was scrolled along the X-axis. I map that to the width of the title labels(hardcoded as 75.0) to calculate the distance that collection has to be scrolled. Hope this can be refined to serve your purpose, but I am sure that there are better methods out there :)
Related
I have created custom header but I don't know how to animate while scrolling.
Please check below image and let me know how to animate while scrolling.
This animated header in Fotmob app.
First of all add header view as UIvVew and add UIScrollView or UITableView below headerView same as screenshot and follow below step.
set a fixed height constraint to the header view (125 for example) and attach it to top, left and right.
make the UIScrollView below to use all the available space so set to zero top, bottom, left and right constraints.
connect the header view height constraint to the ViewController in order to have something like:
#IBOutlet var headerViewHeightConstraint: NSLayoutConstraint!
set the UIScrollView delegate to the ViewController
declare two properties to limit the maximum and the minimum height of the header view, fox example:
let headerViewMaxHeight: CGFloat = 125
let headerViewMinHeight: CGFloat = 44 + UIApplication.shared.statusBarFrame.height
The entire workaround is based on update the header view height constraint while the UIScrollView is scrolling, so let’s implement the UIScrollViewDelegate and the most important delegate for our case, the scrollViewDidScroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let headerViewMinHeight: CGFloat = 44 + UIApplication.shared.statusBarFrame.height
let yPos = mainScrollView.contentOffset.y
let newHeaderViewHeight: CGFloat = headerViewHeightConstraint.constant - yPos
if newHeaderViewHeight > headerViewMaxHeight {
// Here, Manage Your Score Format View
headerViewHeightConstraint.constant = max(headerViewMaxHeight, newHeaderViewHeight)
} else if newHeaderViewHeight < headerViewMinHeight {
headerViewHeightConstraint.constant = headerViewMinHeight
} else {
headerViewHeightConstraint.constant = newHeaderViewHeight
scrollView.contentOffset.y = 0 // block scroll view
}
}
I have created the same, Check the below image
Overview
TableView
Sample MVVM pattern
Swift 5.0 above
Xcode 11 above
Find the GIT URL for code
HeaderAnimation
One of the cells in a UITableView contains a scroll view. I want to be able to scroll the content in the cell horizontally, but NOT vertically.
How can I achieve this?
Additionally, the scroll view is a subview of UIWebView, so I cannot control its content size.
I have tried setting the content offset directly, but this prevents the entire table from being scrolled. I want the table to scroll vertically, but not the content in the cell.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
DispatchQueue.main.async {
scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x, y: 0)
}
}
You will have to ensure the content is smaller than the vertical bounds of the UIScrollView to prevent vertical scrolling, and in addition you'll need to set scrollView.alwaysBounceVertical = false.
I'm making a collection view with fixed height and width and horizontal scroll direction.
At the start I will have 1 cell and I want it in the right side of the collection view instead of the left and when more cells are coming I want them to stack in the right side of the previous cell like 1 - 2 - 3.
I searched for an answer but all similar questions were for objective c.
Any thoughts how could I do this with swift?
Thanks in advance.
The problem is that if you try to set the contentOffset of your collection view in viewWillAppear, the collection view hasn't rendered its items yet. Therefore self.collectionView.contentSize is still {0,0}. The solution is to ask the collection view's layout for the content size.
Additionally, you'll want to make sure that you only set the contentOffset when the contentSize is taller than the bounds of your collection view.
func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let contentSize: CGSize? = collectionView?.collectionViewLayout.collectionViewContentSize
if contentSize?.height > collectionView?.bounds.size.height {
let targetContentOffset = CGPoint(x: 0.0, y: (contentSize?.height)! - (collectionView?.bounds.size.height)!)
collectionView?.contentOffset = targetContentOffset
}
}
I have a horizontal scrollable collectionView with two cells that take up the screen. Inside those cells is an embedded collection view that scrolls vertically. Is there a way for me to scroll the vertical CV inside the first cell, while using its ContentOffset to scroll the vertical CV in the second cell?
Here's how I'm trying to accomplish it:
let scrollView = notification.userInfo!["scrollView"] as! UICollectionView
if scrollView.contentOffset.y <= 250.0 {
childViewControllerForPosts.collectionViewForGroups?.collectionView.setContentOffset(CGPointMake(0, scrollView.contentOffset.y), animated: false)
self.topVerticalConstraint?.constant = -scrollView.contentOffset.y
}
else {
if self.topVerticalConstraint?.constant > -250 {
// Make sure it stays at -250
self.topVerticalConstraint?.constant = -250
}
}
The FeedCell would be the main collection view (which horizontally scrolls) that contains the vertical scrolling collection view. I'm trying to access the second one to change the vertical contentOffset when I scroll the one in first one.
Here's how I'm trying to save the variable that should contain the second main collection view:
collectionViewForGroups = collectionView(collectionView!, cellForItemAtIndexPath: NSIndexPath(forItem: 1, inSection: 0)) as? FeedCell
EDIT:
Note that when I scroll horizontally, the vertical scroll view didn't change. But I want it to change with the one I just scrolled in the gif. If I were to scroll the 2nd vertical collection view, the UIView above will reappear because the topLayConstraint changes due to the vertical contentOffset change.
I have a scroll view with several elements (textview, label, image view...), I need to display an uiview when my label appears on the screen when I'm scrolling.
How can I do ?
Make sure your view controller is the scroll view delegate. Implement the scrollViewDidScroll method, and check whether the scroll view's frame, offset by the contentOffset, overlaps the label's frame.
func scrollViewDidScroll(scrollView: UIScrollView) {
let offset = self.scrollView.contentOffset
let onScreen = CGRectOffset(self.scrollView.frame, offset.x, offset.y)
if CGRectIntersectsRect(onScreen, self.label.frame) {
NSLog("Overlap")
}
}
If you want to detect when the label is fully on the screen, use CGRectContainsRect instead of CGRectIntersectsRect.