iOS:拖动按钮的副本

时间:2017-01-29 18:06:44

标签: ios uibutton uipangesturerecognizer

我不确定是否有人问过,但我找不到解决办法。我正在按钮上实现平移手势,但想法是:按钮固定到一个位置,当用户拖动它时,创建按钮的副本并随手势移动;原始的一个停留在它的初始位置(因此视图中将有2个按钮)。当平移结束时,新按钮用于某些处理,之后它应该消失(原始按钮保持不变;因此整个过程可以重复)。目前我所拥有的如下:

private func addPanGesture() {
    for btn in self.selectors { //selectors is a list of buttons which needs this gesture
        let pan = UIPanGestureRecognizer(target: self, action:#selector(self.panDetected(_:)))
        pan.minimumNumberOfTouches = 1
        pan.maximumNumberOfTouches = 1
        btn.addGesturerecognizer(pan)
    }
}

@objc private func panDetected(_ panGesture: UIPanGestureRecognizer) {
    var translation = panGesture.translation(in: view)
    panGesture.setTranslation(CGPoint(x: 0, y: 0), in: view)

    var newButton = UIButton()
    if let initButton = panGesture.view as? UIButton {
        print ("Button recognized!") // this msg is printed out
        newButton.center = CGPoint(x: initButton.center.x + translation.x, y: initButton.center.y + translation.y)
        newButton.setImage(UIImage(named: "somename"), for: .normal)
    }

    if panGesture.state == UIGestureRecognizerState.began {
        self.view.addSubview(newButton)
    }
    if panGesture.state == UIGestureRecognizerState.ended {
        //some other processing
    }
    if panGesture.state == UIGestureRecognizerState.changed {
        self.view.addSubview(newButton)
    }
    // printed-out msgs show began, ended, changed states have all been reached
}

但是我的视图中没有显示新按钮。我可以知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

很难说没有调试它,但我看到的一些事情:

每次通过panDetected创建一个新按钮,并每次将其添加到视图中。您应该只创建一个添加.began状态的按钮。

您应该使用init(frame:)创建按钮,并将其初始化为图像的大小。

看起来您正在将平移手势附加到按钮上。然后你在按钮的坐标系中得到平移坐标,这是没有意义的。您应该将平移手势转换为按钮的超级视图坐标系,除非平移手势的状态为.began,否则不应调用setTranslation。

每次收到1st.changed`消息时,您应该将按钮的坐标设置为平移手势的新位置。

答案 1 :(得分:0)

  1. 您只需在.began上创建新按钮并将其添加为子视图,然后在.ended上将其删除。
  2. 因此,您需要保留对新按钮的引用。
  3. 您正在设置新按钮的中心,但不是它的大小。您可以设置其.frame
  4. 您无需为平移手势设置翻译。获得var translation = panGesture.translation(in: view)后,您将获得所需的一切。
  5. 我只为一个按钮编写了下面的代码,但如果您要允许同时拖动按钮,则需要保留一个移动按钮列表而不是var movingButton: UIButton?

        private func addPanGesture() {
            let pan = UIPanGestureRecognizer(target: self, action:#selector(self.panDetected(_:)))
            pan.minimumNumberOfTouches = 1
            pan.maximumNumberOfTouches = 1
            btn.addGestureRecognizer(pan)
        }
    
        @objc private func panDetected(_ panGesture: UIPanGestureRecognizer) {
            let translation = panGesture.translation(in: view)
    
            let initButton = panGesture.view as! UIButton
    
    
            if panGesture.state == UIGestureRecognizerState.began {
                // this is just copying initial button
                // this might be overkill
                // just make sure you set the frame, title and image of the new button correctly
                let initButtonData = NSKeyedArchiver.archivedData(withRootObject: initButton)
                let newButton = NSKeyedUnarchiver.unarchiveObject(with: initButtonData) as! UIButton
    
                // we store new button's reference since we will just move it while it is added to view
                movingButton = newButton
                self.view.addSubview(movingButton!)
    
            }
            if panGesture.state == UIGestureRecognizerState.ended {
                //some other processing
    
                // when we are done just we just remove it from superview
                movingButton!.removeFromSuperview()
            }
            if panGesture.state == UIGestureRecognizerState.changed {
    
                // at any change, all we need to do is update movingButton's frame
                var buttonFrame = initButton.frame;
                buttonFrame.origin = CGPoint(x: buttonFrame.origin.x + translation.x, y: buttonFrame.origin.y + translation.y)
                movingButton!.frame = buttonFrame
            }
        }