ios 触摸后保持选中 UIButton

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1785008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:38:16  来源:igfitidea点击:

Keeping a UIButton selected after a touch

iosuibuttonselected

提问by Greg Maletic

After my user clicks a button, I'd like that button to stay pushed during the time that I perform a network operation. When the network operation is complete, I want the button to return to its default state.

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

I've tried calling -[UIButton setSelected:YES]right after the button push (with a corresponding call to -[UIButton setSelected:NO]after my network op finishes) but it doesn't seem to do anything. Same thing if I call setHighlighted:.

我试过[UIButton setSelected:YES]在按下按钮后立即呼叫([UIButton setSelected:NO]在我的网络操作完成后进行相应的呼叫),但它似乎没有做任何事情。如果我打电话,同样的事情setHighlighted:

I suppose I could try swapping out the background image to denote a selected state for the duration of the network op, but that seems like a hack. Any better suggestions?

我想我可以尝试换出背景图像来表示网络操作期间的选定状态,但这似乎是一种黑客行为。有什么更好的建议吗?

Here's what my code looks like:

这是我的代码的样子:

- (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;
}

采纳答案by Bryan Henry

How are you setting the images for the different UIControlStateson the button? Are you setting a background image for UIControlStateHighlightedas well as UIControlStateSelected?

您如何为UIControlStates按钮上的不同设置图像?您是否UIControlStateHighlighted为 以及设置背景图像UIControlStateSelected

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

If you're setting the selected state on the button touch down event rather than touch up inside, your button will actually be in a highlighted+selected state, so you'll want to set that too.

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

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

Edit:

编辑:

To sum up my remarks in the comments and to address the code you posted...you need to set your background images for the full UIControlstate that you're in. According to your code snippet, this control state would be disabled + selected + highlighted for the duration of the network operation. This means that you would need to do this:

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

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

If you remove the highlighted = YES, then you would need this:

如果您删除highlighted = YES,那么您将需要这个:

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

Get the picture?

得到图片?

回答by Hlung

I have an easier way. Just use "performSelector" with 0 delay to perform [button setHighlighted:YES]. This will perform re-highlighting after the current runloop ends.

我有一个更简单的方法。只需使用具有 0 延迟的“performSelector”来执行[button setHighlighted:YES]. 这将在当前 runloop 结束后执行重新突出显示。

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

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

回答by 18446744073709551615

"Everything gets better when you turn power on"

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

    button.selected = !button.selected;

works perfectly... after I connected the outlet to the button in the Interface Builder.

完美运行......在我将插座连接到界面生成器中的按钮之后。

You do not need to setBackgroundImage:forState:, the builder allows you to specify the background (gets resized if necessary) or/and foreground (not resizing) images.

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

回答by roberto.buratti

Try using NSOperationQueue to achieve this. Try out code as follows:

尝试使用 NSOperationQueue 来实现这一点。尝试代码如下:

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

Hope this helps.

希望这可以帮助。

回答by Bob Spryn

Use a block so you don't have to build a whole separate method:

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

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

Update

更新

To be clear you still need to set the background (or normal image) for the combination states as well as the regular ones like sbrocket says in the accepted answer. At some point your button will be both selected and highlighted, and you won't have an image for that unless you do something like this:

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

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

Otherwise your button can fall back to the UIControlStateNormal image for the brief selected+highlighted state and you'll see a flash.

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

回答by Eike

In swift I'm doing it like the following.

在 swift 中,我正在执行以下操作。

I create a Subclass of UIButtonand implemented a custom property state

我创建了一个子类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
        }
    }

}

Works perfectly for me.

非常适合我。

回答by fredrik

I had a similar problem where I wanted a button to keep it's highlight after click. The problem is if you try to use setHighlighted:YESinside of you click action it will reset right after you click action, - (IBAction)checkInButtonPushed

我有一个类似的问题,我想要一个按钮在点击后保持高亮。问题是如果你尝试setHighlighted:YES在你的点击动作里面使用它会在你点击动作后立即重置,- (IBAction)checkInButtonPushed

I solved this by using a NSTimer like this

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

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

and then call setHighlighted:YESfrom my selectCurrentIndexmethod. I use regular UIButtonTypeRoundedRectbuttons.

然后setHighlighted:YES从我的selectCurrentIndex方法调用。我使用普通UIButtonTypeRoundedRect按钮。

回答by Pach

I have another way ...if you don't want to use images, and you want the effect of a pressed button, You can subclass the Button and here's my code:

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

in the .h File:

在 .h 文件中:

@interface reservasButton : UIButton {

BOOL isPressed;
}
 @end

In the .m File:

在 .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;

     }


 } `

回答by t9mike

Here is a C# / MonoTouch (Xamarin.iOS) implementation using approaches presented above. It assumes you have set the Highlighted image state already, and configures the selected and selected|highlighted states to use the same image.

这是使用上述方法的 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;
        });
    });
};