触摸后保持UIButton处于选中状态


90

用户单击按钮后,我希望在执行网络操作期间该按钮保持按下状态。网络操作完成后,我希望按钮返回其默认状态。

我曾尝试[UIButton setSelected:YES]在按钮按下后立即拨打电话(与之对应的呼叫- [UIButton setSelected:NO]在我的网络操作完成之后),但似乎没有任何作用。如果我打电话也一样setHighlighted:

我想我可以尝试换掉背景图像以表示在网络运行期间处于选定状态,但这似乎是一种hack。还有更好的建议吗?

这是我的代码:

- (IBAction)checkInButtonPushed
{
    self.checkInButton.enabled = NO;
    self.checkInButton.selected = YES;
    self.checkInButton.highlighted = YES;
    [self.checkInActivityIndicatorView startAnimating];
    [CheckInOperation startWithPlace:self.place delegate:self];
}

- (void)checkInCompletedWithNewFeedItem:(FeedItem*)newFeedItem wasNewPlace:(BOOL)newPlace possibleError:(NSError*)error;
{
    [self.checkInActivityIndicatorView stopAnimating];
    self.checkInButton.enabled = YES;
    self.checkInButton.selected = NO;
    self.checkInButton.highlighted = NO;
}

Answers:


73

您如何UIControlStates在按钮上设置不同的图像?你设置的背景图像UIControlStateHighlighted,以及UIControlStateSelected

UIImage *someImage = [UIImage imageNamed:@"SomeResource.png"];
[button setBackgroundImage:someImage forState:UIControlStateHighlighted];
[button setBackgroundImage:someImage forState:UIControlStateSelected];

如果您是在按钮按下事件上设置选定状态,而不是在内部进行向上触摸,则您的按钮实际上将处于突出显示+选定状态,因此您也需要进行设置。

[button setBackgroundImage:someImage forState:(UIControlStateHighlighted|UIControlStateSelected)];

编辑:

总结我在评论中的评论并解决您发布的代码...您需要将背景图像设置为所处于的完整UIControl状态。根据您的代码段,此控件状态将被禁用+选择+在网络运行期间突出显示。这意味着您需要执行以下操作:

[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateHighlighted|UIControlStateSelected)];

如果您删除了highlighted = YES,则需要这样做:

[button setBackgroundImage:someImage forState:(UIControlStateDisabled|UIControlStateSelected)];

拿照片吗


实际上,我相信我在做您的建议;我只是通过Interface Builder来做的。我在上面的问题中添加了我正在使用的代码...也许可以为这个问题提供一些启示?我想要的行为是我希望在网络操作过程中按钮始终保持选中状态。我所看到的是,触摸时该按钮会突出显示,然后触摸完成后该突出显示就会消失。按钮-从不-被选中。为什么这不起作用对我来说毫无意义,所以我觉得自己在做一些愚蠢的事情。我检查了我所有的IB连接,它们都很好...
Greg Maletic

我不相信您可以在Interface Builder中为突出显示+选定状态设置背景图像,而只能分别为突出显示和选定状态设置背景图像。如果您的按钮处于同时设置了突出显示和选定状态的状态,那么我相信它将默认为您的普通图像,而不是突出显示或选定的图像。从代码中,您正在设置按钮的状态,以使选中和突出显示的按钮均为YES。checkInButtonPushed是否连接到“ Touch Up Inside”或其他东西?
布赖恩·亨利

是的,它已连接到“ Touch Up Inside”。而且,如果我删除与“突出显示”状态相关的代码,它仍然无法正常工作。永远不会显示“选定”状态。
Greg Maletic

另外,为什么要禁用该按钮?这实际上意味着按钮状态为禁用+加亮+选择。如果删除了突出显示为“是”的行设置,则表示已禁用+选择,因此需要为(UIControlStateDisabled | UIControlStateSelected)状态设置图像。
布赖恩·亨利

好的,这就是问题所在。当我取出禁用功能时,它按预期工作。谢谢!(为回答您的问题,我禁用了该按钮,因为我不希望任何人在网络操作正在进行时再次按下该按钮。)
Greg Maletic,2009年

30

我有一个简单的方法。只需使用延迟为0的“ performSelector”即可执行[button setHighlighted:YES]。当前运行循环结束后,这将重新突出显示。

- (IBAction)buttonSelected:(UIButton*)sender {
    NSLog(@"selected %@",sender.titleLabel.text);
    [self performSelector:@selector(doHighlight:) withObject:sender afterDelay:0];
}

- (void)doHighlight:(UIButton*)b {
    [b setHighlighted:YES];
}

27

“打开电源,一切都会变得更好”

    button.selected = !button.selected;

工作完美...将插座连接到Interface Builder中的按钮后。

您不需要setBackgroundImage:forState:,构建器允许您指定背景图像(必要时调整大小)或/和前景图像(不调整大小)。


27

尝试使用NSOperationQueue实现此目的。尝试如下代码:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    theButton.highlighted = YES;
}];

希望这可以帮助。


Roberto&Parth,这是一个很好的解决方案。但是,一个小细节是,如果用户将手指按住按钮,您偶尔会看到“闪烁”。有什么方法可以防止闪烁?
Scott Lieberman 2013年

8

使用块,这样就不必构建整个单独的方法:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{
    theButton.highlighted = YES;
});

更新资料

为了清楚起见,您仍然需要为组合状态设置背景(或正常图像),并在接受的答案中设置常规值,例如sbrocket。在某个时候,您的按钮将被选中并突出显示,除非您执行以下操作,否则您将没有图像:

[button setBackgroundImage:someImage forState (UIControlStateHighlighted|UIControlStateSelected)];

否则,您的按钮可以退回到UIControlStateNormal图像,以显示简短的选定状态和突出显示状态,并且您会看到一个闪烁。


FYI dispatch_get_current_queue()被称为“不可靠”。
Jacob Relkin 2012年

1
哪里写的?有什么选择?
Bob Spryn 2012年

使用dispatch_after相对有什么意义dispatch_async
伊利亚2015年

是的 dispatch_async是更好的选择。
鲍勃·斯普林

3

我正在像下面这样迅速地做到这一点。

我创建了一个子类UIButton并实现了一个自定义属性state

class ActiveButton: UIButton {

    private var _active = false
    var active:Bool {
        set{
            _active = newValue
            updateState()
        }
        get{
            return _active
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.addTarget(self, action: #selector(ActiveButton.touchUpInside(_:)), forControlEvents: .TouchUpInside)
    }

    func touchUpInside(sender:UIButton) {
        active = !active
    }

    private func updateState() {
        NSOperationQueue.mainQueue().addOperationWithBlock {
            self.highlighted = self.active
        }
    }

}

非常适合我。


1

我遇到了类似的问题,我想要一个按钮以使其在单击后保持突出显示。问题是,如果您尝试setHighlighted:YES在点击操作内部使用,它将在您点击操作后立即重置,- (IBAction)checkInButtonPushed

我通过使用这样的NSTimer解决了这个问题

NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.01
                                         target: self
                                       selector: @selector(selectCurrentIndex)
                                       userInfo: nil
                                        repeats: NO];

然后setHighlighted:YES从我的selectCurrentIndex方法中调用。我使用常规UIButtonTypeRoundedRect按钮。


0

我有另一种方法...如果您不想使用图像,并且想要按下按钮的效果,则可以将Button子类化,这是我的代码:

在.h文件中:

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

在.m文件中:

#import <QuartzCore/QuartzCore.h>


 @implementation reservasButton

 -(void)setupView {  //This is for Shadow

    self.layer.shadowColor = [UIColor blackColor].CGColor;
    self.layer.shadowOpacity = 0.5; 
    self.layer.shadowRadius = 1;    
    self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f); //comment
    //   self.layer.borderWidth = 1;
    self.contentVerticalAlignment   = UIControlContentVerticalAlignmentCenter;
    self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;

    // [self setBackgroundColor:[UIColor whiteColor]];

    //  self.opaque = YES;


}

-(id)initWithFrame:(CGRect)frame{
    if((self = [super initWithFrame:frame])){
        [self setupView];
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    if((self = [super initWithCoder:aDecoder])){
        [self setupView];
    }

    return self;
}

//Here is the important code

 -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{


  if (isPressed == FALSE) {

      self.contentEdgeInsets = UIEdgeInsetsMake(1.0,1.0,-1.0,-1.0);
      self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
      self.layer.shadowOpacity = 0.8;

      [super touchesBegan:touches withEvent:event];

      isPressed = TRUE;

     }
     else {

         self.contentEdgeInsets = UIEdgeInsetsMake(0.0,0.0,0.0,0.0);
         self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f);
         self.layer.shadowOpacity = 0.5;

         [super touchesEnded:touches withEvent:event];

         isPressed = FALSE;

     }


 } `

0

这是使用上述方法的C#/ MonoTouch(Xamarin.iOS)实现。假设您已经设置了高亮图像状态,并配置选定和选定状态以使用同一图像。

var selected = button.BackgroundImageForState(UIControlState.Highlighted);
button.SetBackgroundImage(selected, UIControlState.Selected);
button.SetBackgroundImage(selected, UIControlState.Selected | UIControlState.Highlighted);
button.TouchUpInside += delegate
{
    NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(0), delegate
    {
        button.Highlighted = true;
        NSTimer.CreateScheduledTimer(TimeSpan.FromMilliseconds(200), delegate
        {
            button.Highlighted = false;
        });
    });
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.