From d39c4b54d14f09777acb7073b6b4e1ba6f950812 Mon Sep 17 00:00:00 2001 From: Shin Yamamoto Date: Fri, 16 Feb 2024 22:07:14 +0900 Subject: [PATCH] Enable to define and use a subclass object of `BackdropView` (#617) * Enable to create a subclass of BackdropView * Add a custom backdrop sample in the Samples example --- .../Samples/Sources/UseCases/UseCase.swift | 3 ++ .../Sources/UseCases/UseCaseController.swift | 46 +++++++++++++++++++ Sources/BackdropView.swift | 6 +-- Sources/Controller.swift | 7 +-- Sources/Core.swift | 8 +++- 5 files changed, 63 insertions(+), 7 deletions(-) diff --git a/Examples/Samples/Sources/UseCases/UseCase.swift b/Examples/Samples/Sources/UseCases/UseCase.swift index 4ff6a06f..3da2aa75 100644 --- a/Examples/Samples/Sources/UseCases/UseCase.swift +++ b/Examples/Samples/Sources/UseCases/UseCase.swift @@ -24,6 +24,7 @@ enum UseCase: Int, CaseIterable { case showAdaptivePanel case showAdaptivePanelWithCustomGuide case showCustomStatePanel + case showCustomBackdrop } extension UseCase { @@ -50,6 +51,7 @@ extension UseCase { case .showAdaptivePanel: return "Show Adaptive Panel" case .showAdaptivePanelWithCustomGuide: return "Show Adaptive Panel (Custom Layout Guide)" case .showCustomStatePanel: return "Show Panel with Custom state" + case .showCustomBackdrop: return "Show Panel with Custom Backdrop" } } } @@ -83,6 +85,7 @@ extension UseCase { case .showAdaptivePanel: return .storyboard(String(describing: ImageViewController.self)) case .showAdaptivePanelWithCustomGuide: return .storyboard(String(describing: AdaptiveLayoutTestViewController.self)) case .showCustomStatePanel: return .viewController(DebugTableViewController()) + case .showCustomBackdrop: return .viewController(UIViewController()) } } diff --git a/Examples/Samples/Sources/UseCases/UseCaseController.swift b/Examples/Samples/Sources/UseCases/UseCaseController.swift index e0062dda..4f64e42b 100644 --- a/Examples/Samples/Sources/UseCases/UseCaseController.swift +++ b/Examples/Samples/Sources/UseCases/UseCaseController.swift @@ -273,6 +273,52 @@ extension UseCaseController { fpc.set(contentViewController: contentVC) fpc.ext_trackScrollView(in: contentVC) addMain(panel: fpc) + + case .showCustomBackdrop: + class BlurBackdropView: BackdropView { + var effectView: UIVisualEffectView! + override var alpha: CGFloat { + set { + effectView.alpha = newValue + } + get { + effectView.alpha + } + } + override init() { + super.init() + + let effect = UIBlurEffect(style: .prominent) + let effectView = UIVisualEffectView(effect: effect) + addSubview(effectView) + effectView.frame = bounds + effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + self.effectView = effectView + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + class CustomBottomLayout: FloatingPanelBottomLayout { + override var anchors: [FloatingPanelState: FloatingPanelLayoutAnchoring] { + return [ + .full: FloatingPanelLayoutAnchor(absoluteInset: 100.0, edge: .top, referenceGuide: .safeArea), + .half: FloatingPanelLayoutAnchor(fractionalInset: 0.5, edge: .bottom, referenceGuide: .safeArea), + .tip: FloatingPanelLayoutAnchor(fractionalInset: 0.1, edge: .bottom, referenceGuide: .safeArea), + ] + } + override func backdropAlpha(for state: FloatingPanelState) -> CGFloat { + return state == .full ? 0.8 : 0.0 + } + } + + let fpc = FloatingPanelController() + fpc.delegate = self + fpc.set(contentViewController: contentVC) + fpc.backdropView = BlurBackdropView() + fpc.layout = CustomBottomLayout() + addMain(panel: fpc) } } diff --git a/Sources/BackdropView.swift b/Sources/BackdropView.swift index c8da1ab2..b1e48c79 100644 --- a/Sources/BackdropView.swift +++ b/Sources/BackdropView.swift @@ -4,7 +4,7 @@ import UIKit /// A view that presents a backdrop interface behind a panel. @objc(FloatingPanelBackdropView) -public class BackdropView: UIView { +open class BackdropView: UIView { /// The gesture recognizer for tap gestures to dismiss a panel. /// @@ -12,14 +12,14 @@ public class BackdropView: UIView { /// To dismiss a panel by tap gestures on the backdrop, `dismissalTapGestureRecognizer.isEnabled` is set to true. @objc public var dismissalTapGestureRecognizer: UITapGestureRecognizer - init() { + public init() { dismissalTapGestureRecognizer = UITapGestureRecognizer() dismissalTapGestureRecognizer.isEnabled = false super.init(frame: .zero) addGestureRecognizer(dismissalTapGestureRecognizer) } - required init?(coder: NSCoder) { + required public init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } diff --git a/Sources/Controller.swift b/Sources/Controller.swift index 0972dcbc..ca29df14 100644 --- a/Sources/Controller.swift +++ b/Sources/Controller.swift @@ -158,14 +158,15 @@ open class FloatingPanelController: UIViewController { /// Returns the surface view managed by the controller object. It's the same as `self.view`. @objc - public var surfaceView: SurfaceView! { + public var surfaceView: SurfaceView { return floatingPanel.surfaceView } /// Returns the backdrop view managed by the controller object. @objc - public var backdropView: BackdropView! { - return floatingPanel.backdropView + public var backdropView: BackdropView { + set { floatingPanel.backdropView = newValue } + get { return floatingPanel.backdropView } } /// Returns the scroll view that the controller tracks. diff --git a/Sources/Core.swift b/Sources/Core.swift index afec1972..f0481896 100644 --- a/Sources/Core.swift +++ b/Sources/Core.swift @@ -10,7 +10,13 @@ class Core: NSObject, UIGestureRecognizerDelegate { private weak var ownerVC: FloatingPanelController? let surfaceView: SurfaceView - let backdropView: BackdropView + var backdropView: BackdropView { + didSet { + backdropView.dismissalTapGestureRecognizer + .addTarget(self, action: #selector(handleBackdrop(tapGesture:))) + } + } + let layoutAdapter: LayoutAdapter let behaviorAdapter: BehaviorAdapter