如何使 UIImageView 可点击并使其执行某些操作? (Swift)
How to make a UIImageView tappable and cause it to do something? (Swift)
(我几天前才开始使用Swift,对编程还比较陌生,所以请耐心等待。)我正在尝试让随机块出现在屏幕上,用户必须点击他们让他们消失。我已经能够创建块,但我不知道如何真正使它们可点击。有人可以帮帮我吗?到目前为止,这是我的代码:
func createBlock(){
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -50, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
})
}
编辑: 这是我正在尝试的新代码:
func createBlock(){
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -50, width: size, height: size)
self.view.addSubview(imageView)
imageView.userInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped"))
imageView.addGestureRecognizer(tapRecognizer)
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
let tappedImageView = gestureRecognizer.view!
tappedImageView.removeFromSuperview()
score += 10
}
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
})
}
创建视图后,您需要将其 userInteractionEnabled 属性 设置为 true。然后你需要给它附加一个手势。
imageView.userInteractionEnabled = true
//now you need a tap gesture recognizer
//note that target and action point to what happens when the action is recognized.
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped:"))
//Add the recognizer to your view.
imageView.addGestureRecognizer(tapRecognizer)
现在您仍然需要函数,在本例中为 imageTapped:,这是识别手势时发生动作的地方。被识别的手势将作为参数发送,您可以从他们的手势视图中找出哪个 imageView 被点击 属性.
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
//tappedImageView will be the image view that was tapped.
//dismiss it, animate it off screen, whatever.
let tappedImageView = gestureRecognizer.view!
}
而不是使用 UIImageView
,您可以尝试使用自定义 UIButton
并将默认按钮图像替换为您的按钮图像。因此,您不需要为每个 UIImageView 添加 UITapGestureRecognizer
。 @JeremyPope 的方法实际上比这种方法更有效。
处理 UIButton
非常简单,它是 UIControl
的子类,因此有 hide
和 enabled
等属性,您可以按照自己的方式操作它们。
您需要做的是以编程方式创建 UIButton
,就像他们创建 UIImageView
的方式一样。创建它们的方法类似于 UIImageView
,请阅读 create UIButton programmaticly in Swift。
了解更多信息
下图是自定义 UIButton
的样子。
如果您需要更多信息,请发表评论。
对于向 UIImageView 添加点击识别器,我之前的回答仍然是准确的,但是对于动画视图而言,它是不够的。如果您真的在创建游戏,您可能会想研究一下 SpriteKit,因为它确实是为此量身定做的。然而,这可以通过普通的 UIKit 来完成。我已经测试了两种方法,它们都有效。
这两种方法在实际设备上的效果都比在模拟器上好得多
方法 1,更简单但精度稍差 在我的测试中最多慢了十分之一秒。
不向 UIImageView 添加点击手势,而是向超级视图添加手势。在数组 属性 中保留对您的方块的引用,并检查是否有任何方块被点击拦截。
class ViewController: UIViewController {
let size = CGFloat(40)
let xPosition = CGFloat(14)
let options = UIViewAnimationOptions.Autoreverse
var blocks = [UIImageView]()
override func viewDidLoad() {
super.viewDidLoad()
// Adding recognizer to the whole view.
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("screenTapped:"))
view.addGestureRecognizer(tapRecognizer)
blocks.append(createBlock())
}
//changed to return the created block so it can be stored in an array.
func createBlock() -> UIImageView {
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -40, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(2, delay: 0.0, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
self.blocks.append(self.createBlock())
})
return imageView
}
func screenTapped(gestureRecognizer: UITapGestureRecognizer) {
let tapLocation = gestureRecognizer.locationInView(view)
//This is to keep track of the blocks to remove from the array.
//If you remove them as you iterate the array, and you have more than
//one block to remove, you may end up removing the wrong block
//or with an index out of bounds.
var removeBlocks = [Int]()
for (index, block) in enumerate(blocks) {
//this is the frame of the view as we see it on screen.
//unfortunately block.frame is not where we see it making a recognizer
//on the block itself not work.
if block.layer.presentationLayer().frame.contains(tapLocation) {
//Then this block was clicked.
block.removeFromSuperview()
removeBlocks.append(index)
}
}
//get the indexes ro remove backwards so we are removing from
//back to front.
for index in removeBlocks.reverse() {
blocks.removeAtIndex(index)
}
}
}
方法 2,最佳性能 SpriteKit 之外
在方法二中,您将 UIView 子类化,并将您的主视图设置为它而不是 UIView。您只需要重写一个方法。为了方便起见,我将块数组存储在视图中。
首先是 TouchView。
import UIKit
class TouchView: UIView {
var blocks = [UIImageView]()
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
// ignoring multiple touches for now
if touches.count == 1 {
if let touch = touches.first as? UITouch {
let touchLocation = touch.locationInView(self)
//This is to keep track of the blocks to remove from the array.
//If you remove them as you iterate the array, and you have more than
//one block to remove, you may end up removing the wrong block
//or with an index out of bounds.
var removeBlocks = [Int]()
for (index, block) in enumerate(blocks) {
//this is the frame of the view as we see it on screen.
//unfortunately block.frame is not where we see it making a recognizer
//on the block itself not work.
if block.layer.presentationLayer().frame.contains(touchLocation) {
//Then this block was clicked.
block.removeFromSuperview()
removeBlocks.append(index)
}
}
//get the indexes ro remove backwards so we are removing from
//back to front.
for index in removeBlocks.reverse() {
blocks.removeAtIndex(index)
}
}
}
}
}
现在 ViewController 看起来像:
import UIKit
class ViewController: UIViewController {
let size = CGFloat(40)
let xPosition = CGFloat(14)
let options = UIViewAnimationOptions.Autoreverse
var blocks = [UIImageView]()
// computed get only property for conveniece of accessing block array
var touchView:TouchView {
get {
return self.view as! TouchView
}
}
override func viewDidLoad() {
super.viewDidLoad()
touchView.blocks.append(createBlock())
// Do any additional setup after loading the view, typically from a nib.
}
func createBlock() -> UIImageView {
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -40, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(2, delay: 0.0, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
self.touchView.blocks.append(self.createBlock())
})
return imageView
}
}
在我的测试中,这似乎工作得很好,即使是快速动画 "blocks"。同样,如果您打算制作一款成熟的游戏,那么您真的应该看看 SpriteKit。有一个非常简单的教程 here 可以帮助您入门。如果您可以从我之前的答案中删除已接受的答案,那将有助于其他人不会走上错误的道路,除非他们只想向不动的 UIImageView 添加手势。
默认情况下,图像视图用户交互未启用,因此请务必通过将其设置为 true 来启用它。
let myImageView = UIImageView()
myImageView.isUserInteractionEnabled = true
在 swift 3.0 中:
imvEditName.isUserInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
imvEditName.addGestureRecognizer(tapRecognizer)
和目标方法:
func imageTapped(sender: UIImageView) {
print("image tapped")
}
(我几天前才开始使用Swift,对编程还比较陌生,所以请耐心等待。)我正在尝试让随机块出现在屏幕上,用户必须点击他们让他们消失。我已经能够创建块,但我不知道如何真正使它们可点击。有人可以帮帮我吗?到目前为止,这是我的代码:
func createBlock(){
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -50, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
})
}
编辑: 这是我正在尝试的新代码:
func createBlock(){
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -50, width: size, height: size)
self.view.addSubview(imageView)
imageView.userInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped"))
imageView.addGestureRecognizer(tapRecognizer)
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
let tappedImageView = gestureRecognizer.view!
tappedImageView.removeFromSuperview()
score += 10
}
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
})
}
创建视图后,您需要将其 userInteractionEnabled 属性 设置为 true。然后你需要给它附加一个手势。
imageView.userInteractionEnabled = true
//now you need a tap gesture recognizer
//note that target and action point to what happens when the action is recognized.
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped:"))
//Add the recognizer to your view.
imageView.addGestureRecognizer(tapRecognizer)
现在您仍然需要函数,在本例中为 imageTapped:,这是识别手势时发生动作的地方。被识别的手势将作为参数发送,您可以从他们的手势视图中找出哪个 imageView 被点击 属性.
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
//tappedImageView will be the image view that was tapped.
//dismiss it, animate it off screen, whatever.
let tappedImageView = gestureRecognizer.view!
}
而不是使用 UIImageView
,您可以尝试使用自定义 UIButton
并将默认按钮图像替换为您的按钮图像。因此,您不需要为每个 UIImageView 添加 UITapGestureRecognizer
。 @JeremyPope 的方法实际上比这种方法更有效。
处理 UIButton
非常简单,它是 UIControl
的子类,因此有 hide
和 enabled
等属性,您可以按照自己的方式操作它们。
您需要做的是以编程方式创建 UIButton
,就像他们创建 UIImageView
的方式一样。创建它们的方法类似于 UIImageView
,请阅读 create UIButton programmaticly in Swift。
下图是自定义 UIButton
的样子。
如果您需要更多信息,请发表评论。
对于向 UIImageView 添加点击识别器,我之前的回答仍然是准确的,但是对于动画视图而言,它是不够的。如果您真的在创建游戏,您可能会想研究一下 SpriteKit,因为它确实是为此量身定做的。然而,这可以通过普通的 UIKit 来完成。我已经测试了两种方法,它们都有效。
这两种方法在实际设备上的效果都比在模拟器上好得多
方法 1,更简单但精度稍差 在我的测试中最多慢了十分之一秒。
不向 UIImageView 添加点击手势,而是向超级视图添加手势。在数组 属性 中保留对您的方块的引用,并检查是否有任何方块被点击拦截。
class ViewController: UIViewController {
let size = CGFloat(40)
let xPosition = CGFloat(14)
let options = UIViewAnimationOptions.Autoreverse
var blocks = [UIImageView]()
override func viewDidLoad() {
super.viewDidLoad()
// Adding recognizer to the whole view.
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("screenTapped:"))
view.addGestureRecognizer(tapRecognizer)
blocks.append(createBlock())
}
//changed to return the created block so it can be stored in an array.
func createBlock() -> UIImageView {
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -40, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(2, delay: 0.0, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
self.blocks.append(self.createBlock())
})
return imageView
}
func screenTapped(gestureRecognizer: UITapGestureRecognizer) {
let tapLocation = gestureRecognizer.locationInView(view)
//This is to keep track of the blocks to remove from the array.
//If you remove them as you iterate the array, and you have more than
//one block to remove, you may end up removing the wrong block
//or with an index out of bounds.
var removeBlocks = [Int]()
for (index, block) in enumerate(blocks) {
//this is the frame of the view as we see it on screen.
//unfortunately block.frame is not where we see it making a recognizer
//on the block itself not work.
if block.layer.presentationLayer().frame.contains(tapLocation) {
//Then this block was clicked.
block.removeFromSuperview()
removeBlocks.append(index)
}
}
//get the indexes ro remove backwards so we are removing from
//back to front.
for index in removeBlocks.reverse() {
blocks.removeAtIndex(index)
}
}
}
方法 2,最佳性能 SpriteKit 之外
在方法二中,您将 UIView 子类化,并将您的主视图设置为它而不是 UIView。您只需要重写一个方法。为了方便起见,我将块数组存储在视图中。
首先是 TouchView。
import UIKit
class TouchView: UIView {
var blocks = [UIImageView]()
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
// ignoring multiple touches for now
if touches.count == 1 {
if let touch = touches.first as? UITouch {
let touchLocation = touch.locationInView(self)
//This is to keep track of the blocks to remove from the array.
//If you remove them as you iterate the array, and you have more than
//one block to remove, you may end up removing the wrong block
//or with an index out of bounds.
var removeBlocks = [Int]()
for (index, block) in enumerate(blocks) {
//this is the frame of the view as we see it on screen.
//unfortunately block.frame is not where we see it making a recognizer
//on the block itself not work.
if block.layer.presentationLayer().frame.contains(touchLocation) {
//Then this block was clicked.
block.removeFromSuperview()
removeBlocks.append(index)
}
}
//get the indexes ro remove backwards so we are removing from
//back to front.
for index in removeBlocks.reverse() {
blocks.removeAtIndex(index)
}
}
}
}
}
现在 ViewController 看起来像:
import UIKit
class ViewController: UIViewController {
let size = CGFloat(40)
let xPosition = CGFloat(14)
let options = UIViewAnimationOptions.Autoreverse
var blocks = [UIImageView]()
// computed get only property for conveniece of accessing block array
var touchView:TouchView {
get {
return self.view as! TouchView
}
}
override func viewDidLoad() {
super.viewDidLoad()
touchView.blocks.append(createBlock())
// Do any additional setup after loading the view, typically from a nib.
}
func createBlock() -> UIImageView {
let imageName = "block.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: xPosition, y: -40, width: size, height: size)
self.view.addSubview(imageView)
UIView.animateWithDuration(2, delay: 0.0, options: options, animations: {
imageView.backgroundColor = UIColor.redColor()
imageView.frame = CGRect(x: self.xPosition, y: 590, width: self.size, height: self.size)
}, completion: { animationFinished in
imageView.removeFromSuperview()
self.touchView.blocks.append(self.createBlock())
})
return imageView
}
}
在我的测试中,这似乎工作得很好,即使是快速动画 "blocks"。同样,如果您打算制作一款成熟的游戏,那么您真的应该看看 SpriteKit。有一个非常简单的教程 here 可以帮助您入门。如果您可以从我之前的答案中删除已接受的答案,那将有助于其他人不会走上错误的道路,除非他们只想向不动的 UIImageView 添加手势。
默认情况下,图像视图用户交互未启用,因此请务必通过将其设置为 true 来启用它。
let myImageView = UIImageView()
myImageView.isUserInteractionEnabled = true
在 swift 3.0 中:
imvEditName.isUserInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
imvEditName.addGestureRecognizer(tapRecognizer)
和目标方法:
func imageTapped(sender: UIImageView) {
print("image tapped")
}