Como atribuir uma ação ao objeto UIImageView no Swift

186

Estou tentando atribuir um UIImageViewa uma ação quando o usuário toca nela.

Eu sei como criar uma ação para a UIButton, mas como eu poderia imitar o mesmo comportamento de a UIButton, mas usando a UIImageView?

user3706773
fonte

Respostas:

421

Você precisará de um UITapGestureRecognizer. Para configurar, use isto:

override func viewDidLoad()
{
    super.viewDidLoad()

    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    imageView.isUserInteractionEnabled = true
    imageView.addGestureRecognizer(tapGestureRecognizer)
}

@objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
    let tappedImage = tapGestureRecognizer.view as! UIImageView

    // Your action
}

(Você também pode usar UIButtonae atribuir uma imagem a ela, sem texto e depois simplesmente conectar uma IBAction)

Aseider
fonte
3
Nitpick: var tgr = UITapGestureRecognizer (target: self action: Selector ("imageTapped:")), precisa de uma vírgula entre os dois parâmetros.
sysuser
3
como declarado abaixo pelo MidHun MP, verifique se você tem o userInteractionEnabled = true
Sheraz 2/15
2
No Swift 3.0, a sintaxe da ação: Selector ("imageTapped:") mudou para action: #selector (imageTapped))
emily
2
Também em Swift 3.0 a propriedade userInteractionEnabled foi renomeado para isUserInteractionEnabled
Doug Amos
2
Usando o Swift 4, isso funcionou para mim, mas tive que adicionar um @objcmodificador à função.
Mark Lyons
68

Você precisa adicionar um reconhecedor de gestos (para tocar, use UITapGestureRecognizer , para tocar e segurar, use UILongPressGestureRecognizer ) ao seu UIImageView.

let tap = UITapGestureRecognizer(target: self, action: #selector(YourClass.tappedMe))
imageView.addGestureRecognizer(tap)
imageView.isUserInteractionEnabled = true

E implemente o método seletor como:

@objc func tappedMe()
{
    println("Tapped on Image")
}
Midhun MP
fonte
13
userInteractionEnabled é a chave.
Kennydust
@hatim: Qual é o problema que você está enfrentando? Se você tiver um novo problema, publique-o como uma nova pergunta.
Midhun MP
@MidhunMP Eu estou gerando a visualização da imagem de forma dinâmica e ter feito exatamente o que está escrito neste resposta, mas a função tappedMe () não está sendo chamado
hatim
1
Funcionou para mim com as seguintes alterações: let tap = UITapGestureRecognizer (target: self, action: #selector (ViewController.tappedMe)) // próxima linha -> successIndicatorImg.addGestureRecognizer (tap) // próxima linha -> successIndicatorImg.isUserInteractionEnabled = verdadeiro
Almir Campos
@hatim você está usando o mesmo gesto para várias visualizações da interface do usuário? Acabei de resolver esse problema, pois estava usando o mesmo gesto para várias visualizações e apenas uma estava funcionando para mim. quando crio vários gestos, funcionou para mim.
Nadafafif 16/03/19
36

Você pode adicionar um UITapGestureRecognizerao imageView, basta arrastar um para o Storyboard / xib, arraste com a tecla Ctrl pressionada a partir do imageView para o gestoRecognizer e com a tecla Ctrl pressionada do gestoRecognizer para o arquivo Swift para criar umIBAction .

Você também precisará ativar as interações do usuário no UIImageView, conforme mostrado nesta imagem: insira a descrição da imagem aqui

Emil
fonte
4
UIImageViewnão responde a toques por padrão. Você também precisa ativar as interações do usuário.
rmaddy
@rmaddy Opa, isso é verdade. Editado.
Emil
1
Eu gosto de como você pode configurar isso usando o IB, arrastar / soltar é poderoso e não esperava que fosse possível. +1 para isso. Como um noob, seria fácil não saber como ele está conectado sem "zoar" o storyboard. Depende da sua preferência, mas eu prefiro "vê-lo no código".
angryITguy
14

Para o Swift 2.0 e superior, faça isso

@IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tappedMe))
        imageView.addGestureRecognizer(tap)
        imageView.userInteractionEnabled = true
    }
    func tappedMe()
    {
        print("Tapped on Image")
    }
Abhishek Kumar
fonte
userInteractionEnabled agora foi renomeado para isUserInteractionEnabled
Chaim Friedman
11

Código Swift4

Experimente alguns novos métodos de extensão:

import UIKit

extension UIView {

    fileprivate struct AssociatedObjectKeys {
        static var tapGestureRecognizer = "MediaViewerAssociatedObjectKey_mediaViewer"
    }

    fileprivate typealias Action = (() -> Void)?


    fileprivate var tapGestureRecognizerAction: Action? {
        set {
            if let newValue = newValue {
                // Computed properties get stored as associated objects
                objc_setAssociatedObject(self, &AssociatedObjectKeys.tapGestureRecognizer, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
        get {
            let tapGestureRecognizerActionInstance = objc_getAssociatedObject(self, &AssociatedObjectKeys.tapGestureRecognizer) as? Action
            return tapGestureRecognizerActionInstance
        }
    }


    public func addTapGestureRecognizer(action: (() -> Void)?) {
        self.isUserInteractionEnabled = true
        self.tapGestureRecognizerAction = action
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
        self.addGestureRecognizer(tapGestureRecognizer)
    }


    @objc fileprivate func handleTapGesture(sender: UITapGestureRecognizer) {
        if let action = self.tapGestureRecognizerAction {
            action?()
        } else {
            print("no action")
        }
    }

}

Agora, sempre que quisermos adicionar um UITapGestureRecognizera umUIView ou UIViewsubclasse comoUIImageView , podemos fazê-lo sem criar funções associadas para seletores!

Uso:

 profile_ImageView.addTapGestureRecognizer {
        print("image tapped")
    }
Ravindra_Bhati
fonte
2
Funciona bem. e simplificou bastante a implementação.
Nick N
me assusta um pouco com as funções de reflexão usadas - existe uma boa chance de isso funcionar em futuras versões rápidas?
BananaAcid
1
Isso é muito elegante e útil. Funciona para mim
Taylor Maxwell
2
❤️Eu amo extensões
Ricardo
8

Você pode simplesmente definir a imagem do UIButtonpara o que você normalmente colocaria em um arquivo UIImageView. Por exemplo, onde você faria:

myImageView.image = myUIImage

Você poderia usar:

myButton.setImage(myUIImage, forState: UIControlState.Normal)

Então, aqui está a aparência do seu código:

override func viewDidLoad(){
  super.viewDidLoad()

  var myUIImage: UIImage //set the UIImage here
  myButton.setImage(myUIImage, forState: UIControlState.Normal)
}

@IBOutlet var myButton: UIButton!
@IBAction func buttonTap(sender: UIButton!){
  //handle the image tap
}

O melhor de usar esse método é que, se você precisar carregar a imagem de um banco de dados, poderá definir o título do botão antes de definir a imagem:

myButton.setTitle("Loading Image...", forState: UIControlState.Normal)

Para informar aos usuários que você está carregando a imagem

Jojodmo
fonte
2

É necessário adicionar preguiçoso para que o TapGestureRecognizer se registre,
pois o 'self' em UITapGestureRecognizer (target: self ...) será nulo se não for um var preguiçoso. Mesmo se você definir isUserInteractionEnable = true, ele não será registrado sem a variante lenta.

lazy var imageSelector : UIImageView = {
    let image = UIImageView(image: "imageName.png")
    //now add tap gesture
    image.isUserInteractionEnabled = true
    image.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleImageSelector)))
    return image
}()
@objc private func handleImageSelector() {
    print("Pressed image selector")
}
candyline
fonte
1

Você pode colocar um UIButtonfundo transparente por cima do UIImageViewe ouvir um toque no botão antes de carregar a imagem

depsch ali
fonte
1
É uma maneira rápida de descrever uma opção. Eu pensei que todo mundo sabia disso!
depsch ali
3
Não é uma boa ideia adicionar componentes de interface do usuário desnecessários sem motivo real. Isso aumentará a complexidade da interface do usuário e você também precisará lidar com as mesmas restrições de layout automático. É apenas melhor adicionar um TapGestureRecognizer.
Gunhan
1

Código Swift 4


Etapa 1 no ViewdidLoad ()

   let pictureTap = UITapGestureRecognizer(target: self, action: #selector(MyInfoTableViewController.imageTapped))
       userImageView.addGestureRecognizer(pictureTap)
       userImageView.isUserInteractionEnabled = true

Etapa 2 Adicionar função a seguir

@objc func imageTapped() {

        let imageView = userImageView
        let newImageView = UIImageView(image: imageView?.image)
        newImageView.frame = UIScreen.main.bounds
        newImageView.backgroundColor = UIColor.black
        newImageView.contentMode = .scaleAspectFit
        newImageView.isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
        newImageView.addGestureRecognizer(tap)
        self.view.addSubview(newImageView)

        self.navigationController?.isNavigationBarHidden = true
        self.tabBarController?.tabBar.isHidden = true

    }

Está testado e funcionando corretamente

Sachin Rasane
fonte
0

Sugiro colocar o botão invisível (opacidade = 0) na visualização de imagem e depois manipular a interação no botão.

levan
fonte