如何在不重叠的情况下在 UIButton 中实现两个 IBAction?

Posted

技术标签:

【中文标题】如何在不重叠的情况下在 UIButton 中实现两个 IBAction?【英文标题】:How to implement two IBActions in UIButton without overlap? 【发布时间】:2013-03-23 15:37:27 【问题描述】:

我从 UIButton 中拖动 2 个 IBActions,一个带有 touchDown 事件,第二个带有内部拖动。

- (IBAction)clickButton:(UIButton *)sender 
    NSLog(@"Click Button");


- (IBAction)dragInsideButton:(UIButton *)sender 
    NSLog(@"Drag Button");

但是当我往里面拖动时,touchDown 动作也会被触发。

如何在 dragInside 时禁用 touchDown 事件。

谢谢!

【问题讨论】:

只是猜测,做一个 BOOL 并检查方法并通过以下方式翻转操作:-(void)removeTarget:action: 您是否还希望发生相反的情况——也就是说,如果触发了 touchDown,您是否需要在用户开始拖动时不发生 dragInside?完成这项工作的唯一方法是在开始时稍微延迟等待,看看是否开始拖拽。如果这不可接受,那么您将不得不采用不同的设计。 【参考方案1】:

我已经使用拖动事件解决了这样的问题

在 .xib 文件中或以编程方式将事件添加到您的按钮。

以编程方式是:

[mybut addTarget:self action:@selector(dragBegan:withEvent: )
  forControlEvents: UIControlEventTouchDown];
    [mybut addTarget:self action:@selector(dragMoving:withEvent: )
  forControlEvents: UIControlEventTouchDragInside];
    [mybut addTarget:self action:@selector(dragEnded:withEvent: )
  forControlEvents: UIControlEventTouchUpInside |
     UIControlEventTouchUpOutside];

那么事件的定义是:

- (void) dragBegan: (UIButton *) c withEvent:ev

    NSLog(@"dragBegan......");
    count=NO;//bool Value to decide the Down Event
    c.tag=0;
  [self performSelector:@selector(DownSelected:) withObject:mybut afterDelay:0.1];
 //user must begin dragging in 0.1 second else touchDownEvent happens



- (void) dragMoving: (UIButton *) c withEvent:ev

    NSLog(@"dragMoving..............");
    c.tag++;


- (void) dragEnded: (UIButton *) c withEvent:ev

    NSLog(@"dragEnded..............");
    if (c.tag>0 && !count)
    

        NSLog(@"make drag events");

    





-(void)DownSelected:(UIButton *)c

    if (c.tag==0) 
        NSLog(@"DownEvent");
        count=YES;//count made Yes To interrupt drag event
    


【讨论】:

聪明的方法!但是 touchDown 目标变成了 touchUpInside 事件。【参考方案2】:

这个方法已经过测试,应该能做我认为你想做的事。您可以更改计时器中的延迟以获得您想要的效果。我必须将 3 个动作连接到按钮才能使这项工作 - 第三个动作是将系统重置为启动状态的 touchUp。

@interface LastViewController ()
@property (nonatomic) BOOL touchedDown;
@property (strong,nonatomic) NSTimer *downTimer;
@end

@implementation LastViewController 

- (void)viewDidLoad 
    [super viewDidLoad];
    self.touchedDown = NO;


-(IBAction)clickDown:(id)sender 
    self.downTimer = [NSTimer scheduledTimerWithTimeInterval:.3 target:self selector:@selector(buttonAction:) userInfo:nil repeats:NO];


-(IBAction)dragInside:(id)sender 
    [self.downTimer invalidate];
    [self buttonAction:self];



-(void) buttonAction:(id) sender 
    if ([sender isKindOfClass:[NSTimer class]]) 
        self.touchedDown = YES;
        NSLog(@"click down");
    else
        if (! self.touchedDown) 
             NSLog(@"Drag");
        
    


-(IBAction)touchUpAction:(id)sender 
    self.touchedDown = NO;

【讨论】:

谢谢!第一次拖动就可以正常工作。单击,再次拖动不起作用。接下来我需要做什么?我不知道如何控制定时器。 您是否实现了 touchUpAction 方法(并将其连接到按钮)?对我来说效果很好,反复点击和拖动。 谢谢先生!我的目标 touchDownAction。 @ios10,如果我的回答解决了你的问题,你应该接受。 是的,先生!我需要更多时间来测试。谢谢!【参考方案3】:

试试这个方法:

isClicked 是 BOOL 类型的属性。设置为YES

- (IBAction)clickButton:(UIButton *)sender  //touch down
    if(isClick==YES)
       NSLog(@"Click Button");
       //do all your stuffs here
    
    isClick=YES;


- (IBAction)dragInsideButton:(UIButton *)sender 
    NSLog(@"Drag Button");
    isClick=NO;

除此之外你还可以实现removeTarget:Action:

首先调用哪个方法设置 isClick=NO,我希望在按钮操作中首先调用 clickButton。

【讨论】:

谢谢!点击按钮按钮总是先触发,我不知道如何控制。我都尝试了,但总是 2 个动作触发。 我认为所有的动作都会进入调用状态,一旦设置好就无法停止。 removeTarget:Action:你试过了吗我是ios新手,还在学习中,请见谅。 谢谢!如果这样做,我的 touchDown 事件只会在双击时触发。 对不起先生!不能很快回复。在我睡觉的时间。还不行。【参考方案4】:

我来自Two action methods for an UIButton; next track and seek forward:

根据您的要求更改它。

就我个人而言,我只是在您的视图控制器或按钮子类中使用整数来跟踪按钮的状态。如果您跟踪按钮的操作,您可以控制每个操作的操作。在您的 .h 文件中放入如下内容:

enum 
    MyButtonScanning,
    MyButtonStalling,
    MyButtonIdle
;



@interface YourClass : UIViewController 
    NSInteger buttonModeAt;

@property (nonatomic) NSInteger buttonModeAt;
-(IBAction)buttonPushedDown:(id)sender;
-(void)tryScanForward:(id)sender;
-(IBAction)buttonReleasedOutside:(id)sender;
-(IBAction)buttonReleasedInside:(id)sender;
@end

然后在你的 .m 文件中加入一些这样的东西:

@implementation YourClass
///in your .m file
@synthesize buttonModeAt;


///link this to your button's touch down
-(IBAction)buttonPushedDown:(id)sender 
    buttonModeAt = MyButtonStalling;
    [self performSelector:@selector(tryScanForward:) withObject:nil afterDelay:1.0];


-(void)tryScanForward:(id)sender 
    if (buttonModeAt == MyButtonStalling) 
        ///the button was not released so let's start scanning
        buttonModeAt = MyButtonScanning;
        
        ////your actual scanning code or a call to it can go here
        [self startScanForward];
    


////you will link this to the button's touch up outside
-(IBAction)buttonReleasedOutside:(id)sender 
    if (buttonModeAt == MyButtonScanning) 
        ///they released the button and stopped scanning forward
        [self stopScanForward];
     else if (buttonModeAt == MyButtonStalling) 
        ///they released the button before the delay period finished
        ///but it was outside, so we do nothing
    
    
    self.buttonModeAt = MyButtonIdle;


////you will link this to the button's touch up inside
-(IBAction)buttonReleasedInside:(id)sender 
    if (buttonModeAt == MyButtonScanning) 
        ///they released the button and stopped scanning forward
        [self stopScanForward];
     else if (buttonModeAt == MyButtonStalling) 
        ///they released the button before the delay period finished so we skip forward
        [self skipForward];
    
    
    self.buttonModeAt = MyButtonIdle;
    

之后,只需将按钮的操作链接到我在 IBactions 之前在 cmets 中记录的内容。我没有对此进行测试,但它应该可以工作。

【讨论】:

【参考方案5】:

我不确定它是否会起作用,但你可以尝试

   - (IBAction)dragInsideButton:(UIButton *)sender 
    [sender removeTarget:self forSelector:@selector(clickButton:) forControlEvent:UIControlEventTouchDown];

【讨论】:

以上是关于如何在不重叠的情况下在 UIButton 中实现两个 IBAction?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不冻结 GUI 的情况下在单个插槽中实现阻塞进程?

在不移动数据的情况下在 CUDA 中实现 realloc

如何在没有中间副本的情况下在标准 C 中实现 memmove?

我们可以在不使用 GraphQL 的情况下在项目中实施 AWS-Appsync 吗?

在不使用CollectionView的情况下在网格视图中列出UIButtons

如何在elasticsearch中实现两种类型之间的交叉连接?