Skip to content

Commit

Permalink
Merge branch 'release/1.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
malcommac committed Jan 12, 2020
2 parents c3c5d06 + 3dcb8d8 commit 9104ba2
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 34 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,15 @@ class ViewController: ScrollStackController, ScrollStackControllerDelegate {
func scrollStackRowDidBecomeHidden(_ stackView: ScrollStack, row: ScrollStackRow, index: Int, state: ScrollStack.RowVisibility) {
// Row did become partially or entirely invisible.
}


func scrollStackDidUpdateLayout(_ stackView: ScrollStack) {
// This function is called when layout is updated (added, removed, hide or show one or more rows).
}

func scrollStackContentSizeDidChange(_ stackView: ScrollStack, from oldValue: CGSize, to newValue: CGSize) {
// This function is called when content size of the stack did change (remove/add, hide/show rows).
}

}
```

Expand Down
2 changes: 1 addition & 1 deletion ScrollStackController.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "ScrollStackController"
s.version = "1.1.0"
s.version = "1.2.0"
s.summary = "Create complex scrollable layout using UIViewController and simplify your code"
s.homepage = "https://github.com/malcommac/ScrollStackController"
s.license = { :type => "MIT", :file => "LICENSE" }
Expand Down
8 changes: 6 additions & 2 deletions ScrollStackController.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 1.1.0;
MARKETING_VERSION = 1.2.0;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = "com.ScrollStackController.ScrollStackController-iOS";
PRODUCT_NAME = ScrollStackController;
Expand All @@ -569,7 +569,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 1.1.0;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.ScrollStackController.ScrollStackController-iOS";
PRODUCT_NAME = ScrollStackController;
SKIP_INSTALL = YES;
Expand Down Expand Up @@ -617,11 +617,13 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 0;
DEVELOPMENT_TEAM = SXF6X3A7VN;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = ScrollStackControllerDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.2.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.danielemargutti.ScrollStackControllerDemo;
Expand All @@ -643,11 +645,13 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 0;
DEVELOPMENT_TEAM = SXF6X3A7VN;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = ScrollStackControllerDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.2.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.danielemargutti.ScrollStackControllerDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
Binary file not shown.
4 changes: 2 additions & 2 deletions ScrollStackControllerDemo/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
Expand Down
32 changes: 30 additions & 2 deletions ScrollStackControllerDemo/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

import UIKit

class ViewController: UIViewController {
class ViewController: UIViewController, ScrollStackControllerDelegate {


@IBOutlet public var contentView: UIView!

Expand All @@ -28,13 +29,19 @@ class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}

func scrollStackRowDidUpdateLayout(_ stackView: ScrollStack) {
debugPrint("New content insets \(stackView.contentSize.height)")
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

stackController.view.frame = contentView.bounds
contentView.addSubview(stackController.view)


stackView.stackDelegate = self
// Prepare content

welcomeVC = WelcomeVC.create()
Expand All @@ -44,7 +51,6 @@ class ViewController: UIViewController {
notesVC = NotesVC.create(delegate: self)

stackView.addRows(controllers: [welcomeVC, notesVC, tagsVC, galleryVC,pricingVC], animated: false)

}

@IBAction public func addNewRow() {
Expand Down Expand Up @@ -78,6 +84,28 @@ class ViewController: UIViewController {
let randomRow = Int.random(in: 0..<stackView.rows.count)
stackView.scrollToRow(index: randomRow, at: .middle, animated: true)
}


func scrollStackDidScroll(_ stackView: ScrollStack, offset: CGPoint) {

}

func scrollStackRowDidBecomeVisible(_ stackView: ScrollStack, row: ScrollStackRow, index: Int, state: ScrollStack.RowVisibility) {

}

func scrollStackRowDidBecomeHidden(_ stackView: ScrollStack, row: ScrollStackRow, index: Int, state: ScrollStack.RowVisibility) {

}

func scrollStackDidUpdateLayout(_ stackView: ScrollStack) {

}

func scrollStackContentSizeDidChange(_ stackView: ScrollStack, from oldValue: CGSize, to newValue: CGSize) {
// debugPrint("Content size did change from \(oldValue) to \(newValue)")
}

}

extension ViewController: TagsVCProtocol {
Expand Down
52 changes: 50 additions & 2 deletions Sources/ScrollStackController/ScrollStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,16 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
right: UITableView().separatorInset.left
)

private static let defaultRowPadding: UIEdgeInsets = .zero

public static let defaultSeparatorInset: UIEdgeInsets = UITableView().separatorInset
public static let defaultSeparatorColor = (UITableView().separatorColor ?? .clear)
public static let defaultRowColor = UIColor.clear
public static let defaultRowHighlightColor = UIColor(red: 0.85, green: 0.85, blue: 0.85, alpha: 1)


/// Cached content size for did change content size callback in scrollstack delegate.
private var cachedContentSize: CGSize?

// MARK: Public Properties

/// The direction that rows are laid out in the stack view and scrolling works.
Expand Down Expand Up @@ -122,6 +127,15 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
}
}

/// Padding for rows `contentView` (the view of the view controller handled by row).
open var rowPadding: UIEdgeInsets = ScrollStack.defaultRowPadding {
didSet {
rows.forEach { row in
row.rowPadding = rowPadding
}
}
}

/// The color of separators in the stack view.
/// You can set property for a single separator by setting new value inside the row's `separatoView`.
open var separatorColor = ScrollStack.defaultSeparatorColor {
Expand Down Expand Up @@ -515,7 +529,7 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
safeRowAtIndex(rowIndex)?.rowInsets = insets
}

/// Set the ints of the row's content related to the parent row cell.
/// Set the insets of the row's content related to the parent row cell.
///
/// - Parameter row: target rows.
/// - Parameter insets: new insets.
Expand All @@ -525,6 +539,24 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
}
}

/// Set the padding of the row's content related to parent row cell.
///
/// - Parameter row: target row.
/// - Parameter padding: new insets.
open func setRowPadding(index rowIndex: Int, padding: UIEdgeInsets) {
safeRowAtIndex(rowIndex)?.rowPadding = padding
}

/// Set the padding of the row's content related to the parent row cell.
///
/// - Parameter row: target rows.
/// - Parameter insets: new padding.
open func setRowPadding(indexes rowIndexes: [Int], padding: UIEdgeInsets) {
rowIndexes.forEach {
setRowPadding(index: $0, padding: padding)
}
}

/// Return the visibility status of a row.
///
/// - Parameter index: index of the row to check.
Expand Down Expand Up @@ -924,4 +956,20 @@ open class ScrollStack: UIScrollView, UIScrollViewDelegate {
dispatchRowsVisibilityChangesTo(stackDelegate)
}

open override func layoutSubviews() {
super.layoutSubviews()

guard let stackDelegate = stackDelegate else {
return
}

stackDelegate.scrollStackDidUpdateLayout(self)

if let oldContentSize = cachedContentSize, oldContentSize != self.contentSize {
stackDelegate.scrollStackContentSizeDidChange(self, from: oldContentSize, to: contentSize)
}

cachedContentSize = self.contentSize
}

}
88 changes: 64 additions & 24 deletions Sources/ScrollStackController/ScrollStackRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

import UIKit

// MARK: - ScrollStackRow

open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {

// MARK: Private Properties
Expand All @@ -52,12 +54,10 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
}()

/// Constraints to handle separator's insets changes.
private var separatorConstraints: (
top: NSLayoutConstraint,
bottom: NSLayoutConstraint,
leading: NSLayoutConstraint,
trailing: NSLayoutConstraint
)?
private var separatorConstraints: ConstraintsHolder?

/// Constraints to handle content's view padding changes.
private var paddingConstraints: ConstraintsHolder?

/// Location of the separator view.
/// It's automatically managed when you change the axis of the parent stackview.
Expand Down Expand Up @@ -150,6 +150,13 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
}
}

open var rowPadding: UIEdgeInsets {
didSet {
paddingConstraints?.updateInsets(rowPadding)
layoutIfNeeded()
}
}

open override var isHidden: Bool {
didSet {
guard isHidden != oldValue else {
Expand All @@ -162,6 +169,7 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
internal init(controller: UIViewController, stackView: ScrollStack) {
self.stackView = stackView
self.controller = controller
self.rowPadding = stackView.rowPadding
super.init(frame: .zero)

clipsToBounds = true
Expand Down Expand Up @@ -198,6 +206,7 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
}

rowInsets = stackView.rowInsets
rowPadding = stackView.rowPadding
rowBackgroundColor = stackView.rowBackgroundColor
rowHighlightColor = stackView.rowHighlightColor

Expand All @@ -212,40 +221,42 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
// MARK: Manage Separator

private func didUpdateContentViewContraints() {
let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor)
let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: rowPadding.bottom)
bottomConstraint.priority = UILayoutPriority(rawValue: UILayoutPriority.required.rawValue - 1)

paddingConstraints = ConstraintsHolder(
top: contentView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: rowPadding.top),
bottom: bottomConstraint,
left: contentView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: rowPadding.left),
right: contentView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor, constant: rowPadding.right)
)

NSLayoutConstraint.activate([
contentView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
contentView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor),
bottomConstraint
])
paddingConstraints?.activateAll()
}

private func didUpdateSeparatorViewContraintsIfNeeded() {
if separatorConstraints == nil {
separatorConstraints = (
separatorConstraints = ConstraintsHolder(
top: separatorView.topAnchor.constraint(equalTo: topAnchor),
bottom: separatorView.bottomAnchor.constraint(equalTo: bottomAnchor),
leading: separatorView.leadingAnchor.constraint(equalTo: leadingAnchor),
trailing: separatorView.trailingAnchor.constraint(equalTo: trailingAnchor)
left: separatorView.leadingAnchor.constraint(equalTo: leadingAnchor),
right: separatorView.trailingAnchor.constraint(equalTo: trailingAnchor)
)
}
}

private func didUpdateSeparatorAxis() {
separatorConstraints?.top.isActive = (separatorAxis == .vertical)
separatorConstraints?.bottom.isActive = true
separatorConstraints?.leading.isActive = (separatorAxis == .horizontal)
separatorConstraints?.trailing.isActive = true
separatorConstraints?.top?.isActive = (separatorAxis == .vertical)
separatorConstraints?.bottom?.isActive = true
separatorConstraints?.left?.isActive = (separatorAxis == .horizontal)
separatorConstraints?.right?.isActive = true
}

private func didUpdateSeparatorInsets() {
separatorConstraints?.top.constant = separatorInsets.top
separatorConstraints?.bottom.constant = (separatorAxis == .horizontal ? 0 : -separatorInsets.bottom)
separatorConstraints?.leading.constant = separatorInsets.left
separatorConstraints?.trailing.constant = (separatorAxis == .vertical ? 0 : -separatorInsets.right)
separatorConstraints?.top?.constant = separatorInsets.top
separatorConstraints?.bottom?.constant = (separatorAxis == .horizontal ? 0 : -separatorInsets.bottom)
separatorConstraints?.left?.constant = separatorInsets.left
separatorConstraints?.right?.constant = (separatorAxis == .vertical ? 0 : -separatorInsets.right)
}

// MARK: - Sizing the Controller
Expand Down Expand Up @@ -370,3 +381,32 @@ open class ScrollStackRow: UIView, UIGestureRecognizerDelegate {
}

}

// MARK: - ConstraintsHolder

fileprivate class ConstraintsHolder {
var top: NSLayoutConstraint?
var left: NSLayoutConstraint?
var bottom: NSLayoutConstraint?
var right: NSLayoutConstraint?

init(top: NSLayoutConstraint?, bottom: NSLayoutConstraint?,
left: NSLayoutConstraint?, right: NSLayoutConstraint?) {
self.top = top
self.bottom = bottom
self.left = left
self.right = right
}

func activateAll() {
[top, left, bottom, right].forEach { $0?.isActive = true }
}

func updateInsets(_ insets: UIEdgeInsets) {
top?.constant = insets.top
bottom?.constant = insets.bottom
left?.constant = insets.left
right?.constant = insets.right
}

}
Loading

0 comments on commit 9104ba2

Please sign in to comment.