Chcę emulować długie naciśnięcie przycisku, jak mogę to zrobić? Myślę, że potrzebny jest minutnik. Rozumiem, UILongPressGestureRecognizer
ale jak mogę wykorzystać ten typ?
Odpowiedzi:
Możesz zacząć od utworzenia i dołączenia UILongPressGestureRecognizer
instancji do przycisku.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.button addGestureRecognizer:longPress];
[longPress release];
Następnie zaimplementuj metodę obsługującą gest
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateEnded ) {
NSLog(@"Long Press");
}
}
To byłoby podstawowe podejście. Możesz również ustawić minimalny czas trwania prasy i jaki błąd jest tolerowany. Zauważ też, że metoda jest wywoływana kilka razy, jeśli po rozpoznaniu gestu, więc jeśli chcesz coś zrobić na końcu, będziesz musiał sprawdzić jej stan i obsłużyć.
if(gesture.state == UIGestureRecognizerStateBegan)
, ponieważ użytkownik oczekuje, że coś się stanie, gdy nadal naciskają (stan zaczął), a nie po zwolnieniu (zakończone).
Jako alternatywę dla zaakceptowanej odpowiedzi można to zrobić bardzo łatwo w Xcode przy użyciu Interface Builder.
Po prostu przeciągnij narzędzie rozpoznawania gestów z długim naciśnięciem z biblioteki obiektów i upuść je na przycisku w miejscu, w którym ma zostać wykonane długie naciśnięcie.
Następnie połącz akcję z właśnie dodanego narzędzia do rozpoznawania gestów z długim naciśnięciem do kontrolera widoku, wybierając nadawcę, który ma być typu UILongPressGestureRecognizer
. W kodzie tegoIBAction
użyj tego, który jest bardzo podobny do kodu sugerowanego w zaakceptowanej odpowiedzi:
W celu C :
if ( sender.state == UIGestureRecognizerStateEnded ) {
// Do your stuff here
}
Lub w Swift :
if sender.state == .Ended {
// Do your stuff here
}
Muszę jednak przyznać, że po wypróbowaniu tego wolę sugestię @shengbinmeng jako komentarz do zaakceptowanej odpowiedzi, którą miałam użyć:
W celu C :
if ( sender.state == UIGestureRecognizerStateBegan ) {
// Do your stuff here
}
Lub w Swift :
if sender.state == .Began {
// Do your stuff here
}
Różnica polega na tym Ended
, że po podniesieniu palca widać efekt długiego naciśnięcia. Z Began
efektem długiego naciśnięcia widać, gdy tylko długie naciśnięcie zostanie złapane przez system, jeszcze przed oderwaniem palca od ekranu.
Wprowadziłem dodatkową modyfikację, używając UIGestureRecognizerState.Began
zamiast .Ended
tego, ponieważ prawdopodobnie tego naturalnie spodziewałaby się większość użytkowników. Wypróbuj oba i przekonaj się sam.
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")
}
}
Spróbuj tego:
Dodawanie przycisku viewDidLoad:
jak poniżej
-(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];
}
Teraz wywołaj metodę gestów w ten sposób
-(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
daje mi zły tag klikniętego przycisku UIButton. Jakieś rozwiązanie?
Myślę, że potrzebujesz mojego rozwiązania.
powinieneś mieć ten kod dla pojedynczego naciśnięcia
- (IBAction)buttonDidPress:(id)sender {
NSLog("buttonDidPress");
}
najpierw dodaj gest długiego naciśnięcia do przycisku
- (void)viewWillAppear:(BOOL)animated
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonDidLongPress:)];
[self.button addGestureRecognizer:longPress];
}
następnie wielokrotnie wywołuj zdarzenie pojedynczego naciśnięcia, jeśli zostanie rozpoznany gest długiego naciśnięcia.
- (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
trakcie viewWillAppear
cyklu życia, ponieważ za każdym razem, gdy pojawi się widok, zostanie dodany inny aparat do rozpoznawania gestów. Należy to zrobić w metodzie prywatnej wywoływanej podczas inicjalizacji.
W przypadku Swift 4 należy zmienić „func longPress”, aby działał:
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")
}
}
Odpowiedź w jednym wierszu, bez gestów:
[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Szczegóły:
To wyzwala swój cel na trzech imprezach: 1- Natychmiast po palec dotyka przycisk: UIControlEventTouchDown
. To wychwytuje początek długich naciśnięć. 2 & 3- Gdy użytkownik podniesie palec: UIControlEventTouchUpOutside
& UIControlEventTouchUpInside
. To oddaje koniec prasy użytkownika.
Uwaga: działa to dobrze, jeśli nie interesują Cię dodatkowe informacje dostarczane przez aparat rozpoznawania gestów (np. Lokalizacja dotyku itp.)
W razie potrzeby możesz dodać więcej wydarzeń pośrednich. Zobacz je wszystkie tutaj https://developer.apple.com/documentation/uikit/uicontrolevents?language=objc .
W Storyboard: Połącz swój przycisk z 3 wydarzeniami, a nie tylko domyślnym, które wybiera Storyboard (Touch Up Inside).
Mam podklasę UIButton dla mojej aplikacji, więc wyciągnąłem moją implementację. Możesz dodać to do swojej podklasy lub można to równie łatwo przekodować jako kategorię UIButton.
Moim celem było dodanie długiego naciśnięcia przycisku bez zaśmiecania kontrolerów widoku całym kodem. Zdecydowałem, że akcja powinna zostać wywołana, gdy rozpocznie się stan rozpoznawania gestów.
Pojawia się ostrzeżenie, którego nigdy nie próbowałem rozwiązać. Mówi, że to możliwy wyciek, myślałem, że przetestowałem kod i nie wycieka.
@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];
}
}
Aby przypisać akcję, dodaj tę linię do swojej metody viewDidLoad.
[_myLongButton addLongPressTarget:0.75 target:self selector:@selector(longPressAction:)];
Akcję należy zdefiniować jak wszystkie IBActions (bez IBAction).
- (void)longPressAction:(id)sender {
// sender is the button
}
Żaden pracował stąd Próbowałem pisania kodu longpress w IBAction
przycisk lub kliknięcie od storyboard
w Controller
zamiast pisać wviewDidLoad
- (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];
}