如何在不重叠的情况下在 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?的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有中间副本的情况下在标准 C 中实现 memmove?
我们可以在不使用 GraphQL 的情况下在项目中实施 AWS-Appsync 吗?