Skip to content

Commit

Permalink
Fix the scroll tracking of WKWebView on iOS 17.4 (#630)
Browse files Browse the repository at this point in the history
* Fix a scroll tracking issue of WKWebView on iOS 17.4
* Add 'Scroll tracking(List CollectionView)' use case in Samples app
  • Loading branch information
scenee authored May 18, 2024
1 parent 8f2be39 commit e473c3c
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 4 deletions.
8 changes: 8 additions & 0 deletions Examples/Samples/Samples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
54CDC5D8215BBE23007D205C /* SupplementaryViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54CDC5D7215BBE23007D205C /* SupplementaryViews.swift */; };
54EAD35B263A75EB006A36EA /* PanelLayouts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54EAD35A263A75EB006A36EA /* PanelLayouts.swift */; };
54EAD365263A765F006A36EA /* PagePanelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54EAD364263A765F006A36EA /* PagePanelController.swift */; };
54F185822BF4AD0000916F57 /* DebugListCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F185812BF4AD0000916F57 /* DebugListCollectionViewController.swift */; };
54F185842BF4B82E00916F57 /* UnavailableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F185832BF4B82E00916F57 /* UnavailableViewController.swift */; };
5D82A6AD28D1843C006A44BA /* libswiftCoreGraphics.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D82A6AC28D18438006A44BA /* libswiftCoreGraphics.tbd */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -76,6 +78,8 @@
54CDC5D7215BBE23007D205C /* SupplementaryViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupplementaryViews.swift; sourceTree = "<group>"; };
54EAD35A263A75EB006A36EA /* PanelLayouts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelLayouts.swift; sourceTree = "<group>"; };
54EAD364263A765F006A36EA /* PagePanelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagePanelController.swift; sourceTree = "<group>"; };
54F185812BF4AD0000916F57 /* DebugListCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugListCollectionViewController.swift; sourceTree = "<group>"; };
54F185832BF4B82E00916F57 /* UnavailableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnavailableViewController.swift; sourceTree = "<group>"; };
5D82A6AC28D18438006A44BA /* libswiftCoreGraphics.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftCoreGraphics.tbd; path = usr/lib/swift/libswiftCoreGraphics.tbd; sourceTree = SDKROOT; };
/* End PBXFileReference section */

Expand All @@ -97,6 +101,7 @@
children = (
5442E23F25FC533800A26F43 /* DebugTableViewController.swift */,
5442E24925FC53C100A26F43 /* DebugTextViewController.swift */,
54F185812BF4AD0000916F57 /* DebugListCollectionViewController.swift */,
5442E23325FC528400A26F43 /* DetailViewController.swift */,
5442E24325FC538200A26F43 /* InspectorViewController.swift */,
5442E22325FC51AF00A26F43 /* ImageViewController.swift */,
Expand All @@ -106,6 +111,7 @@
5442E22B25FC521F00A26F43 /* SettingsViewController.swift */,
5442E22F25FC525200A26F43 /* TabBarViewController.swift */,
544BC56726CC918200D0A436 /* AdaptiveLayoutTestViewController.swift */,
54F185832BF4B82E00916F57 /* UnavailableViewController.swift */,
);
path = ContentViewControllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -247,6 +253,7 @@
5442E23A25FC52CD00A26F43 /* ModalViewController.swift in Sources */,
5442E22425FC51AF00A26F43 /* ImageViewController.swift in Sources */,
5442E24025FC533800A26F43 /* DebugTableViewController.swift in Sources */,
54F185822BF4AD0000916F57 /* DebugListCollectionViewController.swift in Sources */,
5442E25225FC541700A26F43 /* NestedScrollViewController.swift in Sources */,
5442E22825FC51E200A26F43 /* MultiPanelController.swift in Sources */,
546341A125C6415100CA0596 /* UseCase.swift in Sources */,
Expand All @@ -257,6 +264,7 @@
54EAD365263A765F006A36EA /* PagePanelController.swift in Sources */,
5442E24425FC538200A26F43 /* InspectorViewController.swift in Sources */,
5442E22C25FC521F00A26F43 /* SettingsViewController.swift in Sources */,
54F185842BF4B82E00916F57 /* UnavailableViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2018 the FloatingPanel authors. All rights reserved. MIT license.

import UIKit

@available(iOS 14, *)
class DebugListCollectionViewController: UIViewController {

enum Section {
case main
}

var dataSource: UICollectionViewDiffableDataSource<Section, Int>! = nil
var collectionView: UICollectionView! = nil

override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "List"
configureHierarchy()
configureDataSource()
}
}

@available(iOS 14, *)
extension DebugListCollectionViewController {
/// - Tag: List
private func createLayout() -> UICollectionViewLayout {
var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
config.trailingSwipeActionsConfigurationProvider = { indexPath -> UISwipeActionsConfiguration? in
return UISwipeActionsConfiguration(
actions: [UIContextualAction(
style: .destructive,
title: "Delete",
handler: { _, _, completion in
// Do nothing now
}
)]
)
}
return UICollectionViewCompositionalLayout.list(using: config)
}
}

@available(iOS 14, *)
extension DebugListCollectionViewController {
private func configureHierarchy() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(collectionView)
collectionView.delegate = self
}
private func configureDataSource() {

let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
var content = cell.defaultContentConfiguration()
content.text = "\(item)"
cell.contentConfiguration = content
}

dataSource = UICollectionViewDiffableDataSource<Section, Int>(collectionView: collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in

return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
}

var snapshot = NSDiffableDataSourceSnapshot<Section, Int>()
snapshot.appendSections([.main])
snapshot.appendItems(Array(0..<94))
dataSource.apply(snapshot, animatingDifferences: false)
}
}

@available(iOS 14, *)
extension DebugListCollectionViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2018 the FloatingPanel authors. All rights reserved. MIT license.

import UIKit

class UnavailableViewController: UIViewController {
weak var label: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
label.text = "Unavailable content"
label.numberOfLines = 0
label.textAlignment = .center
label.frame = view.bounds
label.autoresizingMask = [
.flexibleTopMargin,
.flexibleLeftMargin,
.flexibleBottomMargin,
.flexibleRightMargin
]
view.addSubview(label)
self.label = label
}
}
11 changes: 11 additions & 0 deletions Examples/Samples/Sources/UseCases/UseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import UIKit
enum UseCase: Int, CaseIterable {
case trackingTableView
case trackingTextView
case trackingCollectionViewList
case showDetail
case showModal
case showPanelModal
Expand All @@ -31,6 +32,7 @@ extension UseCase {
var name: String {
switch self {
case .trackingTableView: return "Scroll tracking(TableView)"
case .trackingCollectionViewList: return "Scroll tracking(List CollectionView)"
case .trackingTextView: return "Scroll tracking(TextView)"
case .showDetail: return "Show Detail Panel"
case .showModal: return "Show Modal"
Expand Down Expand Up @@ -65,6 +67,15 @@ extension UseCase {
private var content: Content {
switch self {
case .trackingTableView: return .viewController(DebugTableViewController())
case .trackingCollectionViewList:
if #available(iOS 14, *) {
return .viewController(DebugListCollectionViewController())
} else {
let vc = UnavailableViewController()
vc.loadViewIfNeeded()
vc.label.text = "UICollectionLayoutListConfiguration is unavailable.\nBuild this app on iOS 14 and later."
return .viewController(vc)
}
case .trackingTextView: return .storyboard("ConsoleViewController") // Storyboard only
case .showDetail: return .storyboard(String(describing: DetailViewController.self))
case .showModal: return .storyboard(String(describing: ModalViewController.self))
Expand Down
24 changes: 24 additions & 0 deletions Examples/Samples/Sources/UseCases/UseCaseController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,30 @@ extension UseCaseController {
fpc.ext_trackScrollView(in: contentVC)
addMain(panel: fpc)

case .trackingCollectionViewList:
let fpc = FloatingPanelController()
fpc.delegate = self
fpc.contentInsetAdjustmentBehavior = .always
fpc.surfaceView.appearance = {
let appearance = SurfaceAppearance()
appearance.cornerRadius = 6.0
return appearance
}()

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(UseCaseController.handleSurface(tapGesture:)))
tapGesture.cancelsTouchesInView = false
tapGesture.numberOfTapsRequired = 2
// Prevents a delay to response a tap in menus of DebugTableViewController.
tapGesture.delaysTouchesEnded = false
fpc.surfaceView.addGestureRecognizer(tapGesture)

fpc.set(contentViewController: contentVC)
if #available(iOS 14, *),
let scrollView = (fpc.contentViewController as? DebugListCollectionViewController)?.collectionView {
fpc.track(scrollView: scrollView)
}
addMain(panel: fpc)

case .trackingTextView:
let fpc = FloatingPanelController()
fpc.delegate = self
Expand Down
13 changes: 9 additions & 4 deletions Sources/Core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,16 @@ class Core: NSObject, UIGestureRecognizerDelegate {
// When no scrollView, nothing to handle.
guard let scrollView = scrollView, scrollView.frame.contains(initialLocation) else { return false }

// For _UISwipeActionPanGestureRecognizer
if let scrollGestureRecognizers = scrollView.gestureRecognizers {
// Prevents moving a panel on swipe actions using _UISwipeActionPanGestureRecognizer.
// [Warning] Do not apply this to WKWebView. Since iOS 17.4, WKWebView has an additional pan
// gesture recognizer besides UIScrollViewPanGestureRecognizer. Applying this to WKWebView
// will block panel movements because another pan gesture isn't `scrollView.panGestureRecognizer`.
if let scrollGestureRecognizers = scrollView.gestureRecognizers,
scrollView is UITableView || scrollView is UICollectionView {
for gesture in scrollGestureRecognizers {
guard gesture.state == .began || gesture.state == .changed
else { continue }
guard gesture.state == .began || gesture.state == .changed else {
continue
}

if gesture != scrollView.panGestureRecognizer {
return true
Expand Down

0 comments on commit e473c3c

Please sign in to comment.