UIImageView 的向上和向下触摸动作

Posted

技术标签:

【中文标题】UIImageView 的向上和向下触摸动作【英文标题】:Touch up and Touch down action for UIImageView 【发布时间】:2015-12-06 18:40:49 【问题描述】:

我想要实现的是当用户触摸 UIImageView 时设置 Image1,当用户抬起手指时设置 Image2。

我只能得到 UIGestureRecognizerState.Ended 这个代码

 var tap = UITapGestureRecognizer(target: self, action: Selector("tappedMe:"))     

        imageView.addGestureRecognizer(tap)
        imageView.userInteractionEnabled = true

func tappedMe(gesture: UITapGestureRecognizer)


    if gesture.state == UIGestureRecognizerState.Began
        imageView.image=originalImage
        dbgView.text="Began"
    else if  gesture.state == UIGestureRecognizerState.Ended
        imageView.image=filteredImage
        dbgView.text="Ended"
    else if  gesture.state == UIGestureRecognizerState.Cancelled
        imageView.image=filteredImage
        dbgView.text="Cancelled"
    else if  gesture.state == UIGestureRecognizerState.Changed
        imageView.image=filteredImage
        dbgView.text="Changed"
    


【问题讨论】:

我的错误。点击手势不支持Began 状态。一旦它被识别,你只会得到Ended 状态。 您可能需要创建一个自定义的UIImageView 子类并覆盖touchesBegantouchesEnded 方法。 使用 UIButton 会更好吗? 我可以使用手势识别器 【参考方案1】:

UITapGestureRecognizer 不会将其状态更改为.Began,但 UILongPressGestureRecognizer 会。如果您出于某种原因想要直接覆盖触摸回调,您可以使用带有非常短 minimumPressDuration 的 UILongPressGestureRecognizer 来实现效果。

@Daij-Djan 的示例:

class ViewController: UIViewController 
  override func viewDidLoad() 
    super.viewDidLoad()

    // Do any additional setup after loading the view, typically from a nib.

    var tap = UILongPressGestureRecognizer(target: self, action: Selector("pressedMe:"))
    tap.minimumPressDuration = 0
    self.view.addGestureRecognizer(tap)
    self.view.userInteractionEnabled = true
  

  func pressedMe(gesture: UITapGestureRecognizer) 
    if gesture.state == .Began
      self.view.backgroundColor = UIColor.blackColor()
     else if  gesture.state == .Ended 
      self.view.backgroundColor = UIColor.whiteColor()
    
  

【讨论】:

对此表示赞同,因为为此对 imageView 进行子类化会有点过分 @Daij-Djan IMO 添加事件监听器比子类化更多。 @eonist 子类化还有很多其他你想避免的问题。 @Kie IMO 子类化有利有弊,管理事件侦听器有利也有弊。可以说,使用子类化并让苹果添加/删除侦听器并不是一个坏主意。【参考方案2】:

解决办法如下:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
    if let touch = touches.first 
        if touch.view == self 
            //began
        
    
    super.touchesBegan(touches, with: event)


override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) 
    if let touch = touches.first 
        if touch.view == self 
            //end
        
    
    super.touchesEnded(touches, with: event)

注意:把这个放在 UIView 的子类中,并在 init 块中添加:userInteractionEnabled = true

【讨论】:

对此投了反对票,因为您没有提供任何解释,而只是一些随机的代码,甚至不仅仅是 1 个块;)——让它更好[如果 UILongPressGestureRecognizer 工作,则为此对 imageView 进行子类化是过大的很好] 这个解决方案很好,因为它保持父视图可滚动【参考方案3】:

最好和最实用的解决方案是将您的 UIImageView 嵌入到 UIControl 子类中。

默认情况下UIImageView 已启用用户交互。如果您创建一个简单的UIControl 子类,您可以轻松地将您的图像视图添加到其中,然后使用以下方法来实现您想要的:

let control = CustomImageControl()
control.addTarget(self, action: "imageTouchedDown:", forControlEvents: .TouchDown)
control.addTarget(self, action: "imageTouchedUp:", forControlEvents: [ .TouchUpInside, .TouchUpOutside ])

这样做的好处是您可以访问所有不同的触摸事件,从而节省您自己检测它们的时间。

根据您想要执行的操作,您还可以覆盖 var highlighted: Boolvar selected: Bool 以检测用户何时与图像交互。 最好采用这种方式,以便您的用户在其应用中的所有控件上获得一致的用户体验。

一个简单的实现如下所示:

final class CustomImageControl: UIControl 

    let imageView: UIImageView = UIImageView()

    override init(frame: CGRect) 
        super.init(frame: frame)

        // setup our image view
        imageView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(imageView)
        imageView.leadingAnchor.constraintEqualToAnchor(leadingAnchor).active = true
        imageView.trailingAnchor.constraintEqualToAnchor(trailingAnchor).active = true
        imageView.topAnchor.constraintEqualToAnchor(topAnchor).active = true
        imageView.bottomAnchor.constraintEqualToAnchor(bottomAnchor).active = true
    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    


final class MyViewController: UIViewController 


    override func viewDidLoad() 
        super.viewDidLoad()

        let control = CustomImageControl()
        control.translatesAutoresizingMaskIntoConstraints = false
        control.imageView.image = ... // set your image here.
        control.addTarget(self, action: "imageTouchedDown:", forControlEvents: .TouchDown)
        control.addTarget(self, action: "imageTouchedUp:", forControlEvents: [ .TouchUpInside, .TouchUpOutside ])

        view.addSubview(control)
        control.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
        control.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = true
    

    @objc func imageTouchedDown(control: CustomImageControl) 
        // pressed down on the image
    

    @objc func imageTouchedUp(control: CustomImageControl) 
        // released their finger off the image
    

【讨论】:

以上是关于UIImageView 的向上和向下触摸动作的主要内容,如果未能解决你的问题,请参考以下文章

自定义按钮视图:检测触摸向下/向上,快速,并回退拖动到 UIScrollView

c_cpp 方形按钮与背景动画触摸向下和向上(突出显示)

Bootstrap modal 使用鼠标滚动/触摸板在 Chrome 41 上停止滚动(但适用于向上/向下键)

在触摸该列时上下移动 Gridview 的列

UITableView 跟踪触摸错误的轴

对象的向上转型向下转型