長押しボタンをエミュレートしたいのですが、どうすればよいですか?タイマーが必要だと思います。わかりました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)
ユーザーは、離したとき(終了)ではなく、まだ押しているとき(状態は開始)に何かが起こることを期待しているため、を使用することをお勧めします。
受け入れられた答えの代わりに、これはInterfaceBuilderを使用してXcodeで非常に簡単に行うことができます。
オブジェクトライブラリから長押しジェスチャ認識機能をドラッグし、長押しアクションが必要なボタンの上にドロップするだけです。
次に、追加した長押しジェスチャ認識機能からのアクションをView Controllerに接続し、タイプの送信者を選択します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
と、指を画面から離す前であっても、システムが長押しをキャッチするとすぐに長押しの効果を確認できます。
私が使用しての追加修正をした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の場合、機能させるには「funclongPress」を変更する必要があります。
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")
}
}
ジェスチャーなしの1行の回答:
[btn addTarget:self action:@selector(handleTouch:) forControlEvents:UIControlEventTouchDown | UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
詳細:
これにより、次の3つのイベントでターゲットがトリガーされます。1-指がボタンに触れた直後:UIControlEventTouchDown
。これは、長押しの開始をキャプチャします。2&3-ユーザーが指を持ち上げたとき:UIControlEventTouchUpOutside
&UIControlEventTouchUpInside
。これにより、ユーザーのプレスの終了がキャプチャされます。
注:これは、ジェスチャ認識機能によって提供される追加情報(タッチの場所など)を気にしない場合にうまく機能します。
必要に応じて、中間イベントをさらに追加できます。https://developer.apple.com/documentation/uikit/uicontrolevents?language = objcですべてを参照してください。
ストーリーボードの場合: ストーリーボードが選択するデフォルトのイベント(Touch Up Inside)だけでなく、ボタンを3つのイベントに接続します。
アプリ用にサブクラス化されたUIButtonがあるので、実装を引き出しました。これをサブクラスに追加することも、UIButtonカテゴリと同じくらい簡単に再コーディングすることもできます。
私の目標は、すべてのコードでView Controllerを乱雑にすることなく、ボタンに長押しを追加することでした。ジェスチャレコグナイザーの状態が始まったときにアクションを呼び出す必要があると判断しました。
わざわざ解決したことがないという警告が出てきます。コードをテストしたがリークはないと思ったので、リークの可能性があると言います。
@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:)];
アクションは、すべてのIBActionと同様に定義する必要があります(IBActionなし)。
- (void)longPressAction:(id)sender {
// sender is the button
}
何も機能しなかったので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];
}