UIPangestureRecognizer - 一个图像与另一个图像相交
Posted
技术标签:
【中文标题】UIPangestureRecognizer - 一个图像与另一个图像相交【英文标题】:UIPangestureRecognizer - One Image Interects with Another 【发布时间】:2020-02-07 18:08:43 【问题描述】:我不知道如何从我的 UIPanGestureRecognizer 实验中获得某种行为。
当用户点击并按住一张图片,然后它与另一张图片相交时,就会触发一个行为。在这种情况下,行为是绿色或红色图像的不透明度变为 100%。
一旦用户继续在屏幕上拖动图像,并打破与绿色或红色图像的交叉点,我希望它的不透明度恢复到 50%。我的控制流越来越难看。我一直在调整它,但很难找到让我得到我想要的逻辑。
visual
@objc func handlePan(sender: UIPanGestureRecognizer)
let imageOneView = sender.view!
let translation = sender.translation(in: view)
switch sender.state
case .began, .changed:
imageOneView.center = CGPoint(x: imageOneView.center.x + translation.x, y: imageOne.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
view.bringSubviewToFront(imageOne)
if imageOne.frame.intersects(winImage.frame)
winImage.alpha = 1
else
if imageOne.frame.intersects(loseImage.frame)
loseImage.alpha = 1
winImage.alpha = 0.5
else
return
case .ended:
if imageOne.frame.intersects(winImage.frame)
UIView.animate(withDuration: 0.3, animations:
self.imageOne.alpha = 0.0
)
performSegue(withIdentifier: "winnerDetailView", sender: self)
else
if imageOne.frame.intersects(loseImage.frame)
UIView.animate(withDuration: 0.3, animations:
self.imageOne.alpha = 0.0
)
navigationItem.rightBarButtonItem?.isEnabled = true
loseImage.alpha = 0.5
else
UIView.animate(withDuration: 0.3)
self.imageOne.frame.origin = self.imageOneOrgin
default:
break
附加代码:https://github.com/ericmseitz/imageWar
谢谢。
【问题讨论】:
【参考方案1】:几件事...
-
控制流看起来不错。
要重置“赢”和“输”的 alpha,请在进入
handlePan()
时将它们都设置为 0.5。如果检测到相交,请将相应的设置为 1.0。在 UI 更新之前它不会更新,这不会在此函数内部发生。
如果您将可拖动视图嵌入到堆栈视图中(就像您在 GitHub 存储库中所做的那样),您将无法将它们放在彼此前面。
此外,如果您将可拖动视图嵌入到堆栈视图(或其他视图)中,请确保将框架转换为主视图的坐标空间。
这里是修改后的代码,基于您在问题中发布的内容和存储库中的布局(嵌入堆栈视图):
class ViewController: UIViewController
// IBOutlets
@IBOutlet weak var winImage: UIImageView!
@IBOutlet weak var loseImage: UIImageView!
@IBOutlet weak var imageOne: UIImageView!
@IBOutlet weak var imageTwo: UIImageView!
@IBOutlet weak var imageThree: UIImageView!
@IBOutlet weak var imageFour: UIImageView!
// Constants and Variables
var currentImageCenter = CGPoint.zero
override func viewDidLoad()
super.viewDidLoad()
[imageOne, imageTwo, imageThree, imageFour].forEach
let p = UIPanGestureRecognizer(target: self, action: #selector(handlePan(sender:)))
$0?.addGestureRecognizer(p)
winImage.alpha = 0.5
loseImage.alpha = 0.5
@objc func handlePan(sender: UIPanGestureRecognizer)
guard let imageOneView = sender.view else return
let translation = sender.translation(in: view)
// set alpha for both to 0.5
// if either is intersected, it will be set to 1.0
winImage.alpha = 0.5
loseImage.alpha = 0.5
switch sender.state
case .began:
// track center of drag-view so we can return if needed
currentImageCenter = imageOneView.center
case .changed:
imageOneView.center = CGPoint(x: imageOneView.center.x + translation.x, y: imageOneView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: view)
// convert drag-view frame to view coordinate space
guard let r = view.getConvertedFrame(fromSubview: imageOneView) else return
view.bringSubviewToFront(imageOneView)
if r.intersects(winImage.frame)
winImage.alpha = 1
else
if r.intersects(loseImage.frame)
loseImage.alpha = 1
else
return
case .ended:
// convert drag-view frame to view coordinate space
guard let r = view.getConvertedFrame(fromSubview: imageOneView) else return
if r.intersects(winImage.frame)
UIView.animate(withDuration: 0.3, animations:
imageOneView.alpha = 0.0
)
//performSegue(withIdentifier: "winnerDetailView", sender: self)
else
if r.intersects(loseImage.frame)
UIView.animate(withDuration: 0.3, animations:
imageOneView.alpha = 0.0
)
navigationItem.rightBarButtonItem?.isEnabled = true
else
UIView.animate(withDuration: 0.3)
imageOneView.center = self.currentImageCenter
default:
break
注意:以上需要这个UIView
扩展来转换框架坐标:
// from Answer on ***: https://***.com/a/57261226/6257435
extension UIView
// there can be other views between `subview` and `self`
func getConvertedFrame(fromSubview subview: UIView) -> CGRect?
// check if `subview` is a subview of self
guard subview.isDescendant(of: self) else
return nil
var frame = subview.frame
if subview.superview == nil
return frame
var superview = subview.superview
while superview != self
frame = superview!.convert(frame, to: superview!.superview)
if superview!.superview == nil
break
else
superview = superview!.superview
return superview!.convert(frame, to: self)
【讨论】:
DonMag - 这是一个很棒的帮助。我仍在努力理解这一切,但即使没有真正理解你的指导,我也成功地让它发挥了作用。说真的,你今天做出了很大的改变,我很感激你的时间和专业知识。以上是关于UIPangestureRecognizer - 一个图像与另一个图像相交的主要内容,如果未能解决你的问题,请参考以下文章
如何在父视图中限制 UIPanGestureRecognizer
未调用 iOS 13 UIPanGestureRecognizer 选择器
Swift:获取 UIPanGestureRecognizer 的目标