防止UIView(在菜单中滑动)在单击后关闭,但在单击后允许滑动

问题描述 投票:0回答:1

我有一个UIView,可在您1)点击或2)将其滑到顶部后从Botton滑入。现在,您可以通过以下方式将其关闭:1)再次点击它,或2)将其滑动到底部。

我想防止以下情况:Close单击后仅允许向下滑动视图以将其关闭。

这是我当前的代码:(来自:https://www.swiftkickmobile.com/building-better-app-animations-swift-uiviewpropertyanimator

/// A pan gesture that enters into the `began` state on touch down instead of waiting for a touches moved event.
class InstantPanGestureRecognizer: UIPanGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
    if (self.state == UIGestureRecognizer.State.began) { return }
    super.touchesBegan(touches, with: event)
    self.state = UIGestureRecognizer.State.began
   }
}



@objc private func popupViewPanned(recognizer: UIPanGestureRecognizer) {
    print(recognizer.state.rawValue)

    switch recognizer.state {
    case .began:

        // Start the animations
        animateTransitionIfNeeded(to: currentState.opposite, duration: 0.5)

        // Pause all animations, since the next event may be a pan changed
        runningAnimators.forEach { $0.pauseAnimation() }

        // Keep track of each animator's progress
        animationProgress = runningAnimators.map { $0.fractionComplete }

    case .changed:

        // Variable setup
        let translation = recognizer.translation(in: popupView)

        if UIDevice().userInterfaceIdiom == .phone {
            switch UIScreen.main.nativeBounds.height {
            case 1334, 1920, 2208:
                var fraction = -translation.y / popupOffset
                // adjust the fraction for the current state and reversed state
                if currentState == .open { fraction *= -1 }
                if runningAnimators[0].isReversed { fraction *= -1 }

                // apply the new fraction
                for (index, animator) in runningAnimators.enumerated() {
                    animator.fractionComplete = fraction + animationProgress[index]
                }

            case 2436, 2688, 1792:
                var fraction = -translation.y / popupOffsetNotch
                // adjust the fraction for the current state and reversed state
                if currentState == .open { fraction *= -1 }
                if runningAnimators[0].isReversed { fraction *= -1 }

                // apply the new fraction
                for (index, animator) in runningAnimators.enumerated() {
                    animator.fractionComplete = fraction + animationProgress[index]
                }

            default:
                var fraction = -translation.y / popupOffsetNotch
                // adjust the fraction for the current state and reversed state
                if currentState == .open { fraction *= -1 }
                if runningAnimators[0].isReversed { fraction *= -1 }

                // apply the new fraction
                for (index, animator) in runningAnimators.enumerated() {
                    animator.fractionComplete = fraction + animationProgress[index]
                }
            }
        }

    case .ended:

        // variable setup
        let yVelocity = recognizer.velocity(in: popupView).y
        let shouldClose = yVelocity > 0

        // if there is no motion, continue all animations and exit early
        if yVelocity == 0 {
            runningAnimators.forEach { $0.continueAnimation(withTimingParameters: nil, durationFactor: 0) }
            break
        }

        // reverse the animations based on their current state and pan motion
        switch currentState {
        case .open:
            if !shouldClose && !runningAnimators[0].isReversed { runningAnimators.forEach { $0.isReversed = !$0.isReversed } }
            if shouldClose && runningAnimators[0].isReversed { runningAnimators.forEach { $0.isReversed = !$0.isReversed } }
        case .closed:
            if shouldClose && !runningAnimators[0].isReversed { runningAnimators.forEach { $0.isReversed = !$0.isReversed } }
            if !shouldClose && runningAnimators[0].isReversed { runningAnimators.forEach { $0.isReversed = !$0.isReversed } }
        }

        // continue all animations
        runningAnimators.forEach { $0.continueAnimation(withTimingParameters: nil, durationFactor: 0) }

    default:
        ()
    }
}




/// Animates the transition, if the animation is not already running.
private func animateTransitionIfNeeded(to state: State, duration: TimeInterval) {

    // ensure that the animators array is empty (which implies new animations need to be created)
    guard runningAnimators.isEmpty else { return }

    // an animator for the transition
    let transitionAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 1, animations: {
        switch state {
        case .open:
            self.bottomConstraint.constant = 0
            self.popupView.layer.cornerRadius = 10
        case .closed:
            if UIDevice().userInterfaceIdiom == .phone {
                switch UIScreen.main.nativeBounds.height {
                case 1334, 1920, 2208:
                    self.bottomConstraint.constant = self.popupOffset

                case 2436, 2688, 1792:
                    self.bottomConstraint.constant = self.popupOffsetNotch

                default:
                    self.bottomConstraint.constant = self.popupOffsetNotch
                }
            }
            self.popupView.layer.cornerRadius = 5
        }
        self.view.layoutIfNeeded()
    })

    // the transition completion block
    transitionAnimator.addCompletion { position in

        // update the state
        switch position {
        case .start:
            self.currentState = state.opposite
        case .end:
            self.currentState = state
        case .current:
            ()
        @unknown default:
            return
        }

        // manually reset the constraint positions
        switch self.currentState {
        case .open:
            self.bottomConstraint.constant = 0
        case .closed:
            if UIDevice().userInterfaceIdiom == .phone {
                switch UIScreen.main.nativeBounds.height {
                case 1334, 1920, 2208:
                    self.bottomConstraint.constant = self.popupOffset

                case 2436, 2688, 1792:
                    self.bottomConstraint.constant = self.popupOffsetNotch

                default:
                    self.bottomConstraint.constant = self.popupOffsetNotch
                }
            }
        }

        // remove all running animators
        self.runningAnimators.removeAll()
    }

    // start all animators
    transitionAnimator.startAnimation()

    // keep track of all running animators
    runningAnimators.append(transitionAnimator)
}
swift xcode uipangesturerecognizer
1个回答
0
投票

解决方案:panRecognizer.delegate =自我+ UIGestureRecognizerDelegate +

 // This function is needed to add the recognizer only to its parent view.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return touch.view == gestureRecognizer.view
}

并使用子视图。

© www.soinside.com 2019 - 2024. All rights reserved.