You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中UIPanGesture仅左右生效,上下滑动失效问题排查

问题描述

开发一款卡牌游戏,布局包含7×7主网格,以及主网格北、东、南、西四个方向的3×7侧边网格。计划通过UIPanGesture实现侧边卡牌的滚动,但添加右侧卡牌后,手势仅支持左右滑动,上下滑动功能失效。排查发现arrayAllCards.append(button)这行代码导致南北方向的手势无法正常工作。

相关代码

创建右侧卡牌的循环代码

for j in 0...6{
    for i in 0...3 {
        let image = UIImage(named: arrayShuffle[(i+1)*(j+1)].suitRank) as UIImage?
        var cardPos: [Int] = []
        cardPos.append(j)
        cardPos.append(7+i)
        
        var button = Card(suitRank: arrayShuffle[(i+1)*(j+1)].suitRank,
                          position: cardPos,
                          suit: arrayShuffle[(i+1)*(j+1)].suit,
                          rank: arrayShuffle[(i+1)*(j+1)].rank,
                          x: cardPos[0] * (Int(screensize)/7),
                          y: cardPos[1] * (Int(screensize)/7),
                          isChosen: false)
        
        arrayShuffle.remove(at: (i+1)*(j+1))
        
        let valueX = Int(CGFloat(0 + (i * sizeButton)))
        let valueY = Int(CGFloat(middlepos - CGFloat(sizeButton * j)))
        
        button.frame = CGRect(x: valueX,
                              y: valueY,
                              width: sizeButton,
                              height: sizeButton)
        button.backgroundColor = .red
        button.configuration?.imagePadding = 0
        button.setImage(image, for: .normal)
        button.contentVerticalAlignment = .fill
        button.contentHorizontalAlignment = .fill

        arrayAllCards.append(button)
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        let scrollGesture = UITapGestureRecognizer(target: self, action: #selector(swipeUp))
        button.isUserInteractionEnabled = false
        view.addSubview(button)
        view.addGestureRecognizer(scrollGesture)
      
    }
}

UIPanGesture处理代码

@objc func swipeUp(_ gesture: UIPanGestureRecognizer) {
    var vertical: Bool = false
    let moveDirection = gesture.translation(in: self.view)
    if (abs(moveDirection.x) < abs(moveDirection.y)){
        vertical = true
    }
    let result = UIPanGestureRecognizer.State.ended.rawValue
    
    var screenRealEstate: Int = (Int) (self.screenheight - self.screensize) / 2
    screenRealEstate -= (Int)(screensize) / 7 * 2
    
    var stoppage: Bool = false
    for i in arrayAllCards {
        let translation = gesture.translation(in: self.view)
        
        let value1 : Int = Int(arrayAllCards[90].center.y)
        let value: Int = (self.origin + 7 * buttonSize) -  3 * self.buttonSize
        let value2: Int = (self.origin + 13 * buttonSize)
        
        let value3 : Int = Int(arrayAllCards[90].center.x)
        let value4 : Int = 4 * self.buttonSize
        let value5 : Int = 10 * self.buttonSize
        
        if(value3 > value4 && value3 < value5 && !vertical){
            i.center.x = translation.x/10 + i.center.x
        }
        
        if(value1 > value && value1 < value2 && vertical){
            i.center.y = translation.y/10 + i.center.y // Customize this.
        }
        if(gesture.state.rawValue == 3){
            UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
                for k in 0..<self.arrayAllCards.count
                {
                    self.arrayAllCards[k].center.x = CGFloat(self.arrayAllCards[k].position[1]) * CGFloat(self.buttonSize) + CGFloat(self.buttonSize/2)
                    
                    self.arrayAllCards[k].center.y = CGFloat((Int)(self.origin)) + CGFloat(self.arrayAllCards[k].position[0] * self.buttonSize) + CGFloat(self.buttonSize/2)
                }
            }, completion: { finished in
            }
            )}
    }
}
问题分析与修复方案

核心问题点

  1. 手势类型错误:代码中用UITapGestureRecognizer(点击手势)处理滑动操作,完全不符合需求,应该使用UIPanGestureRecognizer(平移手势)。
  2. 手势重复添加:循环里每创建一个按钮就给view加一次手势,导致view上堆叠大量重复手势,引发冲突。
  3. 数组与判断逻辑绑定错误:所有侧边卡牌放入同一数组后,手势处理用固定索引arrayAllCards[90]的位置做判断,该索引可能越界,且南北侧卡牌位置不满足条件,导致上下滑动无响应。
  4. 统一遍历逻辑混乱:不分方向遍历所有卡牌,滑动方向与对应侧边卡牌的匹配逻辑错位,只有东侧卡牌符合左右滑动判断,南北侧卡牌无法触发上下滑动。

修复步骤

  1. 替换手势类型并统一添加
    删除循环内添加手势的代码,在viewDidLoad中仅添加一次平移手势:
override func viewDidLoad() {
    super.viewDidLoad()
    // 其他初始化代码...
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    view.addGestureRecognizer(panGesture)
}
  1. 拆分侧边卡牌数组
    为四个方向的卡牌分别创建数组,方便区分处理:
var northCards: [Card] = []
var eastCards: [Card] = []
var southCards: [Card] = []
var westCards: [Card] = []

创建对应方向卡牌时,将按钮加入对应数组,而非统一放入arrayAllCards。

  1. 修正手势处理逻辑
    重命名原swipeUp方法为handlePan,根据滑动方向操作对应数组的卡牌:
@objc func handlePan(_ gesture: UIPanGestureRecognizer) {
    let translation = gesture.translation(in: view)
    let vertical = abs(translation.y) > abs(translation.x)
    
    if vertical {
        // 垂直滑动:操作南北侧卡牌
        adjustVerticalCards(translation: translation)
    } else {
        // 水平滑动:操作东西侧卡牌
        adjustHorizontalCards(translation: translation)
    }
    
    if gesture.state == .ended {
        resetAllCards()
    }
    
    gesture.setTranslation(.zero, in: view)
}

// 调整垂直方向卡牌位置
private func adjustVerticalCards(translation: CGPoint) {
    let offset = translation.y * 0.1
    northCards.forEach { $0.center.y += offset }
    southCards.forEach { $0.center.y += offset }
}

// 调整水平方向卡牌位置
private func adjustHorizontalCards(translation: CGPoint) {
    let offset = translation.x * 0.1
    eastCards.forEach { $0.center.x += offset }
    westCards.forEach { $0.center.x += offset }
}

// 复位所有卡牌到初始位置
private func resetAllCards() {
    UIView.animate(withDuration: 0.3) {
        [self.northCards, self.eastCards, self.southCards, self.westCards].forEach { cards in
            cards.forEach { card in
                card.center = CGPoint(
                    x: CGFloat(card.position[1]) * self.buttonSize + self.buttonSize/2,
                    y: CGFloat(self.origin) + CGFloat(card.position[0]) * self.buttonSize + self.buttonSize/2
                )
            }
        }
    }
}
  1. 移除错误索引判断
    删掉原代码中依赖arrayAllCards[90]的位置判断,改为根据卡牌所属数组区分处理,确保不同方向卡牌能响应对应滑动操作。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:15:24