xcode - objective - uiimageview set image swift
¿Cómo hacer que UIImageView se pueda tocar y hacer que haga algo?(Rápido) (5)
En swift 3.0:
imvEditName.isUserInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
imvEditName.addGestureRecognizer(tapRecognizer)
Y el método de destino:
func imageTapped(sender: UIImageView) {
print("image tapped")
}
(Empecé a utilizar Swift hace unos días y soy relativamente nuevo en programación, así que por favor tengan paciencia). Estoy tratando de hacer que aparezcan bloques aleatorios en la pantalla, y el usuario debe tocarlos para hacerlos desaparecer. Pude crear los bloques, pero no tengo idea de cómo hacerlos tappables. ¿Puede alguien ayudarme? Este es mi código hasta ahora:
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()
})
}
Este es el nuevo código:
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()
})
}
Mi respuesta anterior sigue siendo precisa para agregar un reconocedor de tap a un UIImageView, sin embargo, no es suficiente para los propósitos de una vista que está animando. Si realmente está creando un juego, es probable que desee buscar en SpriteKit, ya que está hecho a medida para esto. Sin embargo, esto se puede lograr con UIKit normal. He probado dos enfoques, que funcionan.
Ambos enfoques funcionaron mucho mejor en un dispositivo real que en el simulador
Enfoque 1, más simple pero ligeramente menos preciso hasta una décima de segundo más lento en mis pruebas.
En lugar de agregar un gesto de tap a UIImageView, agregue el gesto a la supervista. Mantenga una referencia a sus bloques en una propiedad de matriz, y verifique si algún bloque es interceptado por el tap.
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)
}
}
}
Enfoque 2, mejor rendimiento fuera de SpriteKit
En el acercamiento dos, usted subclase UIView, y configure su vista principal en lugar de UIView. Solo necesita anular un solo método. Estoy almacenando la matriz de bloques en la vista por conveniencia.
Primero el 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)
}
}
}
}
}
Ahora el ViewController se vería así:
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
}
}
En mis pruebas, esto parece funcionar bastante bien, incluso con "bloques" animados rápidamente. De nuevo, si planea hacer un juego completo, realmente debería mirar SpriteKit. Aquí hay un tutorial realmente simple que debería ayudarlo a comenzar. Si puede eliminar la respuesta aceptada de mi respuesta anterior, eso ayudaría a otros a no ser guiados por el camino equivocado, a menos que solo estén buscando agregar un gesto a un UIImageView no móvil.
Una vez que haya creado la vista, debe establecer su propiedad userInteractionEnabled en verdadero. Luego debes adjuntar un gesto a él.
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)
Ahora todavía necesita la función, en este caso imageTapped :, que es donde ocurre la acción cuando se reconoce el gesto. El gesto que se reconoció se enviará como argumento, y usted puede averiguar qué imageView se tomó desde la propiedad de vista de gestos.
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
//tappedImageView will be the image view that was tapped.
//dismiss it, animate it off screen, whatever.
let tappedImageView = gestureRecognizer.view!
}
En lugar de usar UIImageView
, puede intentar usar un UIButton de UIButton
y reemplazar la imagen de botón predeterminada con la suya. Por lo tanto, no es necesario agregar UITapGestureRecognizer
para cada UIImageView. El enfoque de @JeremyPope es en realidad más eficiente en comparación con este enfoque.
Manejar UIButton
es bastante simple, es la subclase de UIControl
por lo que existen propiedades como hide
y enabled
y puedes manipularlas de la manera que desees.
Lo que tienes que hacer es crear UIButton
programáticamente, igual que tú forma de crear UIImageView
. La forma de crearlos es similar a UIImageView
, lea más sobre create UIButton programmaticly en Swift .
La siguiente imagen muestra cómo se ve un UIButton
personalizado.
Deja comentarios si necesitas más información.
De manera predeterminada, la interacción del usuario de la vista de imagen no está habilitada, así que asegúrese de desactivarla.
let myImageView = UIImageView()
myImageView.isUserInteractionEnabled = true