Я хочу сымитировать долгое нажатие кнопки, как мне это сделать? Думаю нужен таймер. Понятно, UILongPressGestureRecognizer
но как я могу использовать этот тип?
Ответы:
Вы можете начать с создания и прикрепления UILongPressGestureRecognizer
экземпляра к кнопке.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];
А затем реализуйте метод, обрабатывающий жест
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateEnded ) {
NSLog(@"Long Press");
}
}
Теперь это будет основной подход. Вы также можете установить минимальную продолжительность печати и допустимую ошибку. Также обратите внимание, что метод вызывается несколько раз, если вы распознаете жест, поэтому, если вы хотите что-то сделать в конце, вам нужно будет проверить его состояние и обработать его.
if(gesture.state == UIGestureRecognizerStateBegan)
, потому что пользователь ожидает, что что-то произойдет, когда они все еще нажимают (состояние Начато), а не когда они отпускают (Завершено).
В качестве альтернативы принятому ответу это можно очень легко сделать в Xcode с помощью Interface Builder.
Просто перетащите распознаватель жестов при длительном нажатии из библиотеки объектов и поместите его поверх кнопки, где вы хотите выполнить длительное нажатие.
Затем подключите действие из только что добавленного распознавателя жестов длительного нажатия к вашему контроллеру представления, выбрав отправителя, который должен иметь тип UILongPressGestureRecognizer
. В коде этогоIBAction
используйте это, что очень похоже на код, предложенный в принятом ответе:
В Objective-C :
if ( sender.state == UIGestureRecognizerStateEnded ) {
// Do your stuff here
}
Или в Swift :
if sender.state == .Ended {
// Do your stuff here
}
Но я должен признать, что после попытки я предпочитаю предложение @shengbinmeng в качестве комментария к принятому ответу, который должен был использовать:
В Objective-C :
if ( sender.state == UIGestureRecognizerStateBegan ) {
// Do your stuff here
}
Или в Swift :
if sender.state == .Began {
// Do your stuff here
}
Разница в том, что с помощью Ended
, вы видите эффект длительного нажатия, когда поднимаете палец. С помощью Began
, вы видите эффект длительного нажатия, как только долгое нажатие улавливается системой, даже до того, как вы уберете палец с экрана.
Я сделал дополнительную модификацию using UIGestureRecognizerState.Began
, .Ended
так как это, вероятно, то, чего, естественно, ожидает большинство пользователей. Однако попробуйте их оба и убедитесь сами.
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")
}
}
Попробуй это:
Добавление кнопки, viewDidLoad:
как показано ниже
-(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];
}
Теперь вызовите метод жеста следующим образом
-(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
дает мне неправильный тег UIButton. Любое решение?
Думаю, тебе нужно мое решение.
у вас должен быть этот код для однократного нажатия
- (IBAction)buttonDidPress:(id)sender {
NSLog("buttonDidPress");
}
сначала добавьте жест долгого нажатия на кнопку
- (void)viewWillAppear:(BOOL)animated
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
[self.button addGestureRecognizer:longPress];
}
затем повторно вызовите событие однократного нажатия, если распознается жест долгого нажатия.
- (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
во время viewWillAppear
жизненного цикла, потому что всякий раз, когда появляется представление, будет добавлен другой распознаватель жестов. Это должно быть сделано в частном методе, который вызывается во время инициализации.
Для Swift 4 необходимо изменить "func longPress", чтобы он работал:
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")
}
}
Однострочный ответ, без жестов:
[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Подробности:
Это вызывает вашу цель на три события: 1- Сразу , как только палец касается вниз кнопок: UIControlEventTouchDown
. Это фиксирует начало долгого нажатия. 2 и 3- Когда пользователь поднимает палец вверх: UIControlEventTouchUpOutside
& UIControlEventTouchUpInside
. Это фиксирует конец нажатия пользователем.
Примечание: это хорошо работает, если вам не важна дополнительная информация, предоставляемая распознавателем жестов (например, местоположение касания и т. Д.)
При необходимости вы можете добавить дополнительные промежуточные события, см. Их все здесь https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .
В раскадровке: подключите кнопку к трем событиям, а не только к тому, которое по умолчанию выбирает раскадровка (Touch Up Inside).
У меня есть подкласс UIButton для моего приложения, поэтому я вытащил свою реализацию. Вы можете добавить это в свой подкласс, или это можно так же легко перекодировать, как категорию UIButton.
Моей целью было добавить долгое нажатие на мою кнопку, не загромождая контроллеры представления всем кодом. Я решил, что действие должно вызываться, когда начинается состояние распознавателя жестов.
Появляется предупреждение, которое я никогда не решал. Говорит, что это возможная утечка, думал, что тестировал код, и утечки нет.
@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];
}
}
Чтобы назначить действие, добавьте эту строку в свой метод viewDidLoad.
[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];
Действие должно быть определено как все IBActions (без IBAction).
- (void)longPressAction:(id)sender {
// sender is the button
}
Никто не работал , следовательно , я пытался писать код longpress в IBAction
или кнопку мыши из storyboard
в Controller
вместо того , чтобы писать вviewDidLoad
- (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];
}