Quero emular um botão de pressionamento longo, como posso fazer isso? Acho que é necessário um cronômetro. Entendo, UILongPressGestureRecognizer
mas como posso utilizar esse tipo?
Respostas:
Você pode começar criando e anexando a UILongPressGestureRecognizer
instância ao botão.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];
E então implemente o método que lida com o gesto
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateEnded ) {
NSLog(@"Long Press");
}
}
Agora, esta seria a abordagem básica. Você também pode definir a duração mínima da impressão e quanto erro é tolerável. E também note que o método é chamado poucas vezes se você depois de reconhecer o gesto, então se você quiser fazer algo no final dele, você terá que verificar seu estado e manipulá-lo.
if(gesture.state == UIGestureRecognizerStateBegan)
, porque o usuário espera que algo aconteça quando ainda está pressionando (o estado Começou), não quando ele soltou (Terminado).
Como alternativa à resposta aceita, isso pode ser feito facilmente no Xcode usando o Interface Builder.
Basta arrastar um Reconhecedor de gestos de pressionamento longo da Biblioteca de objetos e soltá-lo no topo do botão onde deseja pressionar prolongadamente.
Em seguida, conecte uma ação do Long Press Gesture Recognizer recém-adicionado ao controlador de exibição, selecionando o remetente para ser do tipo UILongPressGestureRecognizer
. No código desse IBAction
uso, que é muito semelhante ao código sugerido na resposta aceita:
Em Objective-C :
if ( sender.state == UIGestureRecognizerStateEnded ) {
// Do your stuff here
}
Ou em Swift :
if sender.state == .Ended {
// Do your stuff here
}
Mas devo admitir que depois de tentar, prefiro a sugestão feita por @shengbinmeng como comentário à resposta aceita, que era usar:
Em Objective-C :
if ( sender.state == UIGestureRecognizerStateBegan ) {
// Do your stuff here
}
Ou em Swift :
if sender.state == .Began {
// Do your stuff here
}
A diferença é que com Ended
, você vê o efeito do toque longo ao levantar o dedo. Com Began
, você vê o efeito do toque longo assim que o toque longo for capturado pelo sistema, mesmo antes de tirar o dedo da tela.
Fiz a modificação adicional de usar em UIGestureRecognizerState.Began
vez de, .Ended
uma vez que é provavelmente o que a maioria dos usuários naturalmente espera. Experimente os dois e veja por si mesmo.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// add gesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
self.button.addGestureRecognizer(longPress)
}
func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
@IBAction func normalButtonTap(sender: UIButton) {
print("Button tapped")
}
}
Experimente isto:
Adicionando botão viewDidLoad:
como abaixo
-(void)viewDidLoad {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setTag:1]; //you can set any integer value as tag number
btn.title = @"Press Me";
[btn setFrame:CGRectMake(50.0, 50.0, 60.0, 60.0)];
// now create a long press gesture
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressTap:)];
[btn addGestureRecognizer:longPress];
}
Agora chame o método de gesto assim
-(void)longPressTap:(id)sender {
UIGestureRecognizer *recognizer = (UIGestureRecognizer*) sender
// Recogniser have all property of button on which you have clicked
// Now you can compare button's tag with recogniser's view.tag
// View frame for getting the info on which button the click event happened
// Then compare tag like this
if(recognizer.view.tag == 1) {
// Put your button's click code here
}
// And you can also compare the frame of your button with recogniser's view
CGRect btnRect = CGRectMake(50.0, 50.0, 60.0, 60.0);
if(recogniser.view.frame == btnRect) {
//put your button's click code here
}
// Remember frame comparing is alternative method you don't need to write frame comparing code if you are matching the tag number of button
}
recognizer.view.tag
me dá a tag errada do UIButton clicado. Qualquer solução?
Eu acho que você precisa da minha solução.
você deve ter este código para um único toque
- (IBAction)buttonDidPress:(id)sender {
NSLog("buttonDidPress");
}
primeiro, adicione um gesto de toque longo para o botão
- (void)viewWillAppear:(BOOL)animated
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
[self.button addGestureRecognizer:longPress];
}
em seguida, chame o evento de toque único repetidamente se o gesto de toque longo for reconhecido.
- (void)buttonDidLongPress:(UILongPressGestureRecognizer*)gesture
{
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
{
self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(buttonDidPress:) userInfo:nil repeats:YES];
NSRunLoop * theRunLoop = [NSRunLoop currentRunLoop];
[theRunLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
}
break;
case UIGestureRecognizerStateEnded:
{
[self.timer invalidate];
self.timer = nil;
}
break;
default:
break;
}
}
UIGestureRecognizer
durante o viewWillAppear
evento de ciclo de vida, porque sempre que a visualização aparecer, outro reconhecedor de gesto será adicionado. Isso deve ser feito em um método privado que é chamado durante a inicialização.
Para Swift 4, o "func longPress" precisa ser alterado para que funcione:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// add guesture recognizer
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(_:)))
self.button.addGestureRecognizer(longPress)
}
@objc func longPress(_ guesture: UILongPressGestureRecognizer) {
if guesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
@IBAction func normalButtonTap(sender: UIButton) {
print("Button tapped")
}
}
Resposta de uma linha, sem gestos:
[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Detalhes:
Isso desencadeia o seu alvo em três eventos: 1- Imediatamente, uma vez toques de dedo pressionado o botão: UIControlEventTouchDown
. Isso captura o início de pressionamentos longos. 2 e 3- Quando o usuário levanta o dedo: UIControlEventTouchUpOutside
& UIControlEventTouchUpInside
. Isso captura o final da imprensa do usuário.
Observação: isso funciona bem se você não se importar com as informações extras fornecidas pelo reconhecedor de gestos (por exemplo, localização do toque, etc.)
Você pode adicionar mais eventos intermediários se necessário, veja todos aqui https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .
No Storyboard: Conecte seu botão aos 3 eventos, não apenas ao padrão que o Storyboard seleciona (Touch Up Inside).
Eu tenho um UIButton subclasse para meu aplicativo, então retirei minha implementação. Você pode adicionar isso à sua subclasse ou pode ser facilmente recodificado como uma categoria UIButton.
Meu objetivo era adicionar o toque longo ao meu botão sem sobrecarregar meus controladores de visualização com todo o código. Decidi que a ação deve ser chamada quando o estado do reconhecedor de gestos começa.
Há um aviso que nunca me preocupei em resolver. Diz que é um possível vazamento, pensei ter testado o código e não vaza.
@interface MYLongButton ()
@property (nonatomic, strong) UILongPressGestureRecognizer *gestureRecognizer;
@property (nonatomic, strong) id gestureRecognizerTarget;
@property (nonatomic, assign) SEL gestureRecognizerSelector;
@end
@implementation MYLongButton
- (void)addLongPressTarget:(CGFloat)interval target:(id)target action:(SEL)selector
{
_gestureRecognizerTarget = target;
_gestureRecognizerSelector = selector;
_gestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPressGestureRecognizer:)];
_gestureRecognizer.minimumPressDuration = interval;
[self addGestureRecognizer:_gestureRecognizer];
}
- (void)handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
NSAssert([_gestureRecognizerTarget respondsToSelector:_gestureRecognizerSelector], @"target does not respond to selector");
self.highlighted = NO;
// warning on possible leak -- can anybody fix it?
[_gestureRecognizerTarget performSelector:_gestureRecognizerSelector withObject:self];
}
}
Para atribuir a ação, adicione esta linha ao seu método viewDidLoad.
[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];
A ação deve ser definida como todas as IBActions (sem a IBAction).
- (void)longPressAction:(id)sender {
// sender is the button
}
Nenhum funcionou, portanto, tentei escrever código longpress em IBAction
ou clicar storyboard
no botão em em Controller
vez de escrever emviewDidLoad
- (IBAction)btnClick:(id)sender {
tag = (int)((UIButton *)sender).tag;
// Long press here instead of in viewDidLoad
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
longPress.cancelsTouchesInView = NO;
[sender addGestureRecognizer:longPress];
}