【问题标题】:How to know that if the only visible area of a .png is touched in Xcode如何知道是否在 Xcode 中触摸了 .png 的唯一可见区域
【发布时间】:2015-03-11 11:21:31
【问题描述】:

我已经在 Xcode 中将一个 .png 图像导入到UIImageView,我想做的是当图像被触摸时,它将被隐藏。

但我的问题是 png 图像包含透明部分,当我触摸透明部分时,动作会继续。我希望仅在触摸图像的可见部分时才进行操作。如何解决问题?

Swift 或 Objective-C

【问题讨论】:

    标签: ios objective-c swift uiimageview


    【解决方案1】:

    我创建了一个自定义 UIButton 子类,它的行为与您描述的完全一样,看看:https://github.com/spagosx/iOS-Shaped-Button-Swift

    它是用 Swift 编写的,但很容易转换为 Objective-c。

    方法是从触摸点获取像素数据并访问 RGBA 值,在这种情况下,我们读取 A (alpha) 并检查它是否高于我们的阈值。

    看一点代码:

    func alphaFromPoint(point: CGPoint) -> CGFloat {
        var pixel: [UInt8] = [0, 0, 0, 0]
        let colourSpace = CGColorSpaceCreateDeviceRGB()
        let alphaInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colourSpace, bitmapInfo: alphaInfo.rawValue)
    
        context?.translateBy(x: -point.x, y: -point.y)
    
        self.layer.render(in: context!)
    
        let floatAlpha = CGFloat(pixel[3])
        return floatAlpha
    }
    

    您可以将 floatAlpha 值与您可接受的 alpha 值进行比较:

        override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
            return self.alphaFromPoint(point) >= 100
        }
    

    【讨论】:

    • 比目前票数最高的答案要好得多。
    • 非常好的解决方案!您应该更新您的答案,以在您的算法上提供一两句话(这是一个很好的解决方案!),因为其中只有链接的答案在这里不会被善意地看待:-)
    • 非常感谢。这对我帮助很大
    • 斯威夫特 2.2:let alphaInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue) let context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, colorSpace, alphaInfo.rawValue)
    【解决方案2】:

    我冒昧地更新了“Danny S”对 Swift 5 的回答并删除了无关代码、修复了错误并为用户体验增加了一些额外的清晰度。

    代码如下:

    https://github.com/ZoeESummers/SOXShapedTapView-Updated.git

    【讨论】:

      【解决方案3】:
        -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
          {
              UITouch *touch = [touches anyObject]; 
              CGPoint touch_point = [touch locationInView:self.view];
      
              if (![imageView pointInside:touch_point withEvent:event]) 
              {
                  NSLog(@"you inside imageview");
      // write here what you want
              }
          } 
      

      【讨论】:

      • 请注意这个问题stackoverflow.com/questions/2958808/…Imo 你应该转换坐标!
      • @thura 也看看上面的链接。如果你的问题没有解决。
      • @Sport 这如何回答这个问题?该问题询问如何确定点击是否位于图像的可见部分和透明部分。您在这里所做的只是检查水龙头是否在图像视图内。但这并不能以任何方式回答这个问题。甚至评论中的链接也没有添加任何相关内容。
      • @Fogmeister 他有一个 CGPoint,然后他可以在图像视图内部检查该点是否在透明区域中
      • 是的,但这就是整个问题。他是怎么做到的。他的问题是“我如何检查水龙头是否在透明部分”,而您的答案是“拿到水龙头。然后检查它是否在透明部分”。你还没有真正回答过这个问题。
      【解决方案4】:

      在 Swift 4.2 中结合 Danny 和 Sport 的答案作为扩展。

      extension UIButton{
      
          open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
              if let touch = event!.touches(for: self)?.first {
                  let location = touch.location(in: self)
                  if alphaFromPoint(point: location) == 0 {
                      self.cancelTracking(with: nil)
                      print("cancelled!")
                  } else{
                      super.touchesBegan(touches, with: event)
                  }
              }
          }
      
          func alphaFromPoint(point: CGPoint) -> CGFloat {
              var pixel: [UInt8] = [0, 0, 0, 0]
              let colorSpace = CGColorSpaceCreateDeviceRGB();
              let alphaInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
              let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: alphaInfo.rawValue)
      
              context!.translateBy(x: -point.x, y: -point.y)
              self.layer.render(in: context!)
      
              let floatAlpha = CGFloat(pixel[3])
              return floatAlpha
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-11
        • 1970-01-01
        • 1970-01-01
        • 2019-11-09
        • 2013-06-26
        • 1970-01-01
        相关资源
        最近更新 更多