Skip to content

Commit

Permalink
💫 Update: Exp - AdaptiveModal
Browse files Browse the repository at this point in the history
Summary: Update experiment/test - `swift-programmatic-modal/AdaptiveModal`.
  • Loading branch information
dominicstop committed Jun 4, 2023
1 parent ea46c45 commit a3d5f4a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ struct AdaptiveModalInterpolationPoint: Equatable {
/// The computed frames of the modal based on the snap points
let computedRect: CGRect;

//let modalRotation: CGFloat?;
//let modalRotation: CGFloat;

//let modalScaleX: CGFloat?;
//let modalScaleY: CGFloat?;
//let modalScaleX: CGFloat;
//let modalScaleY: CGFloat;

//let modalTranslateX: CGFloat?;
//let modalTranslateY: CGFloat?;
//let modalTranslateX: CGFloat;
//let modalTranslateY: CGFloat;

//let modalBackgroundColor: UIColor?;
//let modalBackgroundColor: UIColor;
let modalBackgroundOpacity: CGFloat;

let modalCornerRadius: CGFloat;
Expand All @@ -32,8 +32,8 @@ struct AdaptiveModalInterpolationPoint: Equatable {
let modalBackgroundVisualEffect: UIVisualEffect?;
let modalBackgroundVisualEffectIntensity: CGFloat;

//let backgroundColor: UIColor?;
//let backgroundOpacity: CGFloat?;
//let backgroundColor: UIColor;
let backgroundOpacity: CGFloat;

let backgroundVisualEffect: UIVisualEffect?;
let backgroundVisualEffectIntensity: CGFloat;
Expand Down Expand Up @@ -100,6 +100,10 @@ struct AdaptiveModalInterpolationPoint: Equatable {
?? keyframePrev?.modalBackgroundVisualEffectIntensity
?? 1;

self.backgroundOpacity = keyframeCurrent?.backgroundOpacity
?? keyframePrev?.backgroundOpacity
?? 0;

self.backgroundVisualEffect = keyframeCurrent?.backgroundVisualEffect
?? keyframePrev?.backgroundVisualEffect;

Expand All @@ -114,13 +118,17 @@ struct AdaptiveModalInterpolationPoint: Equatable {
modalView.layer.maskedCorners = self.modalMaskedCorners;
};

func apply(toModalBackgroundView modalBackgroundView: UIView?){
modalBackgroundView?.alpha = self.modalBackgroundOpacity;
func apply(toModalBackgroundView modalBgView: UIView?){
modalBgView?.alpha = self.modalBackgroundOpacity;
};

func apply(toBackgroundEffectView effectView: UIVisualEffectView?){
effectView?.effect = self.backgroundVisualEffect;
};

func apply(toBackgroundView bgView: UIView?){
bgView?.alpha = self.backgroundOpacity;
};
};

extension AdaptiveModalInterpolationPoint {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class AdaptiveModalManager {

weak var modalBackgroundView: UIView?;
weak var modalBackgroundVisualEffectView: UIVisualEffectView?;
weak var backgroundDimmingView: UIView?;
weak var backgroundVisualEffectView: UIVisualEffectView?;

var displayLinkStartTimestamp: CFTimeInterval?;
Expand Down Expand Up @@ -179,6 +180,7 @@ class AdaptiveModalManager {
targetView: UIView,
modalBackgroundView: UIView? = nil,
modalBackgroundVisualEffectView: UIVisualEffectView? = nil,
backgroundDimmingView: UIView? = nil,
backgroundVisualEffectView: UIVisualEffectView? = nil,
currentSizeProvider: @escaping () -> CGSize
) {
Expand All @@ -188,13 +190,12 @@ class AdaptiveModalManager {
self.targetView = targetView;

self.modalBackgroundView = modalBackgroundView;
self.backgroundVisualEffectView = backgroundVisualEffectView;
self.modalBackgroundVisualEffectView = modalBackgroundVisualEffectView;

self.currentSizeProvider = currentSizeProvider;
self.backgroundVisualEffectView = backgroundVisualEffectView;
self.backgroundDimmingView = backgroundDimmingView;

modalBackgroundView?.backgroundColor = .systemBackground;
modalView.backgroundColor = .clear;
self.currentSizeProvider = currentSizeProvider;
};

deinit {
Expand All @@ -216,6 +217,14 @@ class AdaptiveModalManager {
bgVisualEffectView.backgroundColor = .clear;
};

if let bgDimmingView = self.backgroundDimmingView {
targetView.addSubview(bgDimmingView);

bgDimmingView.clipsToBounds = true;
bgDimmingView.backgroundColor = .black;
bgDimmingView.alpha = 0;
};

targetView.addSubview(modalView);

modalView.clipsToBounds = true;
Expand All @@ -226,6 +235,7 @@ class AdaptiveModalManager {
modalView.sendSubviewToBack(modalBackgroundView);

modalBackgroundView.backgroundColor = .systemBackground;
modalBackgroundView.isUserInteractionEnabled = false;
};

if let modalBGVisualEffectView = self.modalBackgroundVisualEffectView {
Expand All @@ -234,6 +244,7 @@ class AdaptiveModalManager {

modalBGVisualEffectView.clipsToBounds = true;
modalBGVisualEffectView.backgroundColor = .clear;
modalBGVisualEffectView.isUserInteractionEnabled = false;
};
};

Expand All @@ -253,6 +264,17 @@ class AdaptiveModalManager {
]);
};

if let bgDimmingView = self.backgroundDimmingView {
bgDimmingView.translatesAutoresizingMaskIntoConstraints = false;

NSLayoutConstraint.activate([
bgDimmingView.topAnchor .constraint(equalTo: targetView.topAnchor ),
bgDimmingView.bottomAnchor .constraint(equalTo: targetView.bottomAnchor ),
bgDimmingView.leadingAnchor .constraint(equalTo: targetView.leadingAnchor ),
bgDimmingView.trailingAnchor.constraint(equalTo: targetView.trailingAnchor),
]);
};

if let modalBGView = self.modalBackgroundView {
modalBGView.translatesAutoresizingMaskIntoConstraints = false;

Expand Down Expand Up @@ -438,8 +460,27 @@ class AdaptiveModalManager {
guard let modalCornerRadius = modalCornerRadius else { return nil };
return modalCornerRadius;
};

func interpolateBackgroundOpacity(
forInputPercentValue inputPercentValue: CGFloat,
rangeInput: [CGFloat]? = nil,
rangeOutput: [AdaptiveModalInterpolationPoint]? = nil
) -> CGFloat? {

guard let interpolationSteps = rangeOutput ?? self.interpolationStepsSorted,
let interpolationRangeInput = rangeInput ?? self.interpolationRangeInput
else { return nil };

func applyInterpolationToBackgroundVisualEffect(
return Self.interpolate(
inputValue: inputPercentValue,
rangeInput: interpolationRangeInput,
rangeOutput: interpolationSteps.map {
$0.backgroundOpacity
}
);
};

func applyInterpolationToModalBackgroundVisualEffect(
forInputPercentValue inputPercentValue: CGFloat
) {

Expand All @@ -449,20 +490,20 @@ class AdaptiveModalManager {
);

guard let interpolationRange = interpolationRange else { return nil };
let animator = self.backgroundVisualEffectAnimator;
let animator = self.modalBackgroundVisualEffectAnimator;

let animatorDidRangeChange = animator?.didRangeChange(
let animatorRangeDidChange = animator?.didRangeChange(
interpolationRangeStart: interpolationRange.rangeStart,
interpolationRangeEnd: interpolationRange.rangeEnd
);

if let animator = animator, !animatorDidRangeChange! {
if let animator = animator, !animatorRangeDidChange! {
return animator;
};

animator?.clear();

guard let visualEffectView = self.backgroundVisualEffectView
guard let visualEffectView = self.modalBackgroundVisualEffectView
else { return nil };

visualEffectView.effect = nil;
Expand All @@ -471,19 +512,19 @@ class AdaptiveModalManager {
interpolationRangeStart: interpolationRange.rangeStart,
interpolationRangeEnd: interpolationRange.rangeEnd,
forComponent: visualEffectView,
interpolationOutputKey: \.backgroundVisualEffectIntensity
interpolationOutputKey: \.modalBackgroundVisualEffectIntensity
) {
$0.effect = $1.backgroundVisualEffect;
$0.effect = $1.modalBackgroundVisualEffect;
};
}();

guard let animator = animator else { return };
self.backgroundVisualEffectAnimator = animator;
self.modalBackgroundVisualEffectAnimator = animator;

animator.setFractionComplete(forInputPercentValue: inputPercentValue);
};
func applyInterpolationToModalBackgroundVisualEffect(

func applyInterpolationToBackgroundVisualEffect(
forInputPercentValue inputPercentValue: CGFloat
) {

Expand All @@ -493,20 +534,20 @@ class AdaptiveModalManager {
);

guard let interpolationRange = interpolationRange else { return nil };
let animator = self.modalBackgroundVisualEffectAnimator;
let animator = self.backgroundVisualEffectAnimator;

let animatorRangeDidChange = animator?.didRangeChange(
let animatorDidRangeChange = animator?.didRangeChange(
interpolationRangeStart: interpolationRange.rangeStart,
interpolationRangeEnd: interpolationRange.rangeEnd
);

if let animator = animator, !animatorRangeDidChange! {
if let animator = animator, !animatorDidRangeChange! {
return animator;
};

animator?.clear();

guard let visualEffectView = self.modalBackgroundVisualEffectView
guard let visualEffectView = self.backgroundVisualEffectView
else { return nil };

visualEffectView.effect = nil;
Expand All @@ -515,14 +556,14 @@ class AdaptiveModalManager {
interpolationRangeStart: interpolationRange.rangeStart,
interpolationRangeEnd: interpolationRange.rangeEnd,
forComponent: visualEffectView,
interpolationOutputKey: \.modalBackgroundVisualEffectIntensity
interpolationOutputKey: \.backgroundVisualEffectIntensity
) {
$0.effect = $1.modalBackgroundVisualEffect;
$0.effect = $1.backgroundVisualEffect;
};
}();

guard let animator = animator else { return };
self.modalBackgroundVisualEffectAnimator = animator;
self.backgroundVisualEffectAnimator = animator;

animator.setFractionComplete(forInputPercentValue: inputPercentValue);
};
Expand All @@ -545,12 +586,20 @@ class AdaptiveModalManager {
modalView.layer.cornerRadius = nextModalRadius;
};

if let nextModalBackgroundOpacity = self.interpolateModalBackgroundOpacity(
if let modalBgView = self.modalBackgroundView,
let nextModalBgOpacity = self.interpolateModalBackgroundOpacity(
forInputPercentValue: inputPercentValue
),
let modalBackgroundView = self.modalBackgroundView {
) {

modalBackgroundView.alpha = nextModalBackgroundOpacity;
modalBgView.alpha = nextModalBgOpacity;
};

if let bgDimmingView = self.backgroundDimmingView,
let nextBgOpacity = self.interpolateBackgroundOpacity(
forInputPercentValue: inputPercentValue
) {

bgDimmingView.alpha = nextBgOpacity;
};

self.applyInterpolationToBackgroundVisualEffect(
Expand Down Expand Up @@ -670,7 +719,9 @@ class AdaptiveModalManager {

animator.addAnimations {
interpolationPoint.apply(toModalView: modalView);

interpolationPoint.apply(toModalBackgroundView: self.modalBackgroundView);
interpolationPoint.apply(toBackgroundView: self.backgroundDimmingView);
};

if let completion = completion {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ enum AdaptiveModalConfigTestPresets: CaseIterable {
],
modalBackgroundVisualEffect: UIBlurEffect(style: .systemUltraThinMaterial),
modalBackgroundVisualEffectIntensity: 1,
backgroundOpacity: 0,
backgroundVisualEffect: UIBlurEffect(style: .systemUltraThinMaterialDark),
backgroundVisualEffectIntensity: 0
)
Expand Down Expand Up @@ -169,6 +170,7 @@ enum AdaptiveModalConfigTestPresets: CaseIterable {
.layerMaxXMaxYCorner
],
modalBackgroundVisualEffectIntensity: 0.6,
backgroundOpacity: 0.1,
backgroundVisualEffectIntensity: 0.075
)
),
Expand Down Expand Up @@ -196,6 +198,7 @@ enum AdaptiveModalConfigTestPresets: CaseIterable {
.layerMaxXMaxYCorner
],
modalBackgroundVisualEffectIntensity: 1,
backgroundOpacity: 0,
backgroundVisualEffectIntensity: 0.5
)
),
Expand Down Expand Up @@ -246,6 +249,7 @@ class RNIDraggableTestViewController : UIViewController {
targetView: self.view,
modalBackgroundView: self.modalBackgroundView,
modalBackgroundVisualEffectView: self.modalBackgroundVisualEffectView,
backgroundDimmingView: self.backgroundDimmingView,
backgroundVisualEffectView: self.backgroundVisualEffectView,
currentSizeProvider: {
.zero
Expand Down Expand Up @@ -303,9 +307,11 @@ class RNIDraggableTestViewController : UIViewController {
}();

lazy var modalBackgroundView = UIView();
lazy var backgroundVisualEffectView = UIVisualEffectView();
lazy var modalBackgroundVisualEffectView = UIVisualEffectView();

lazy var backgroundDimmingView = UIView();
lazy var backgroundVisualEffectView = UIVisualEffectView();

lazy var dummyBackgroundView: UIView = {
let view = UIView();

Expand Down

0 comments on commit a3d5f4a

Please sign in to comment.