You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

求指导Tinder式卡片上下滑动显示用户Profile的实现方法

Implementing Up/Down Swipe for User Profile in Tinder-Style Cards

Hey there! Great job getting the left/right swipe working already—let's walk through how to add the up/down swipe to reveal user profiles. Here's a step-by-step approach with code examples and best practices:


Instead of relying on array indexes to match TinderCards with ProfileDetailTinderCards, add a direct reference to your card class for reliability:

class TinderCard: UIView {
    // Add this property to link to its corresponding profile card
    var linkedProfileCard: ProfileDetailTinderCard?
}

When initializing your cards, set this reference:

// Example when loading cards
let mainCard = TinderCard()
let profileCard = ProfileDetailTinderCard()
mainCard.linkedProfileCard = profileCard
currentLoadedCardsArray.append(mainCard)
newDetailTardsArray.append(profileCard)

2. Modify Pan Gesture to Detect Vertical Swipes

Update your existing pan gesture handler to distinguish between horizontal (left/right) and vertical (up/down) swipes. We'll use a threshold to prioritize one direction over the other:

// Add this gesture to your topmost main card
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handleCardPan(_:)))
currentLoadedCardsArray.first?.addGestureRecognizer(panGesture)

@objc private func handleCardPan(_ gesture: UIPanGestureRecognizer) {
    guard let mainCard = gesture.view as? TinderCard else { return }
    let translation = gesture.translation(in: self.view)
    let velocity = gesture.velocity(in: self.view)
    
    // Determine if this is a vertical swipe (prioritize if y-movement is larger than x)
    let isVerticalSwipe = abs(translation.y) > abs(translation.x) && abs(translation.y) > 40 // 40pt threshold
    
    if isVerticalSwipe {
        handleVerticalSwipe(for: mainCard, translation: translation, velocity: velocity, gestureState: gesture.state)
    } else {
        // Keep your existing left/right swipe logic here
        handleHorizontalSwipe(for: mainCard, translation: translation, velocity: velocity, gestureState: gesture.state)
    }
}

3. Implement Vertical Swipe Logic

Create a dedicated function to handle up/down swipes, including animations for revealing/hiding the profile card:

private func handleVerticalSwipe(for mainCard: TinderCard, translation: CGPoint, velocity: CGPoint, gestureState: UIGestureRecognizer.State) {
    guard let profileCard = mainCard.linkedProfileCard else { return }
    
    switch gestureState {
    case .changed:
        // Update main card position in real-time
        mainCard.center = CGPoint(x: mainCard.center.x, y: mainCard.center.y + translation.y)
        gesture.setTranslation(.zero, in: self.view)
        
        // Add profile card to view if not already present (positioned off-screen initially)
        if profileCard.superview == nil {
            view.insertSubview(profileCard, belowSubview: mainCard)
            profileCard.center = CGPoint(x: view.center.x, y: view.center.y + view.bounds.height)
        }
        
        // Animate profile card to follow the main card (with a slight delay for depth)
        profileCard.center = CGPoint(x: profileCard.center.x, y: view.center.y + (translation.y * 0.6))
        
    case .ended:
        let swipeUpComplete = translation.y < -120 || velocity.y < -600
        let swipeDownComplete = translation.y > 120 || velocity.y > 600
        
        if swipeUpComplete {
            // Swipe up: hide main card, reveal profile card
            UIView.animate(withDuration: 0.35, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.2) {
                mainCard.center = CGPoint(x: mainCard.center.x, y: mainCard.center.y - self.view.bounds.height)
                profileCard.center = self.view.center
            } completion: { _ in
                mainCard.removeFromSuperview()
                // Add gesture to profile card for swipe-down to go back
                let profilePan = UIPanGestureRecognizer(target: self, action: #selector(handleProfileCardPan(_:)))
                profileCard.addGestureRecognizer(profilePan)
            }
            
        } else if swipeDownComplete {
            // Swipe down: reset both cards to initial state
            resetCardPositions(mainCard: mainCard, profileCard: profileCard)
            
        } else {
            // Swipe didn't meet threshold: bounce back
            resetCardPositions(mainCard: mainCard, profileCard: profileCard)
        }
        
    default: break
    }
}

// Helper to reset cards to original positions
private func resetCardPositions(mainCard: TinderCard, profileCard: ProfileDetailTinderCard) {
    UIView.animate(withDuration: 0.3) {
        mainCard.center = self.view.center
        profileCard.center = CGPoint(x: self.view.center.x, y: self.view.center.y + self.view.bounds.height)
    } completion: { _ in
        profileCard.removeFromSuperview()
    }
}

4. Add Swipe-Down Logic for Profile Cards

Let users swipe the profile card back down to return to the main card:

@objc private func handleProfileCardPan(_ gesture: UIPanGestureRecognizer) {
    guard let profileCard = gesture.view as? ProfileDetailTinderCard else { return }
    let translation = gesture.translation(in: self.view)
    let velocity = gesture.velocity(in: self.view)
    
    switch gesture.state {
    case .changed:
        profileCard.center = CGPoint(x: profileCard.center.x, y: profileCard.center.y + translation.y)
        gesture.setTranslation(.zero, in: self.view)
        
    case .ended:
        if translation.y > 100 || velocity.y > 500 {
            // Swipe down to return to main card
            UIView.animate(withDuration: 0.35) {
                profileCard.center = CGPoint(x: self.view.center.x, y: self.view.center.y + self.view.bounds.height)
                // Re-add the main card to view
                if let mainCard = profileCard.linkedMainCard { // Add a linkedMainCard property to ProfileDetailTinderCard
                    self.view.addSubview(mainCard)
                    mainCard.center = self.view.center
                }
            } completion: { _ in
                profileCard.removeFromSuperview()
            }
        } else {
            // Bounce back to center if swipe is too weak
            UIView.animate(withDuration: 0.3) {
                profileCard.center = self.view.center
            }
        }
        
    default: break
    }
}

Additional Tips

  • Card Reuse: Implement a reuse pool for both TinderCard and ProfileDetailTinderCard to avoid creating too many views and hitting memory limits.
  • Z-Order Management: Always ensure the active card (main or profile) is at the top of the view hierarchy using bringSubviewToFront(_:) or insertSubview(_:belowSubview:).
  • Feedback: Add haptic feedback when swipes complete to make the interaction feel more tactile (use UIImpactFeedbackGenerator).

内容的提问来源于stack exchange,提问作者Lalit kumar

火山引擎 最新活动