【问题标题】:Keeping a UIButton selected after a touch触摸后保持 UIButton 处于选中状态
【发布时间】:2010-12-19 14:12:29
【问题描述】:

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

我尝试在按钮按下后立即调用 -[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;
}

【问题讨论】:

    标签: ios uibutton selected


    【解决方案1】:

    您如何为按钮上的不同UIControlStates 设置图像?您是否为UIControlStateHighlightedUIControlStateSelected 设置了背景图片?

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

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

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

    编辑:

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

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

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

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

    获取图片?

    【讨论】:

    • 实际上,我相信我正在按照您的建议做;我只是通过 Interface Builder 来做。我在上面的问题中添加了我正在使用的代码......也许这会对问题有所了解?我想要的行为是我希望按钮在我的网络操作期间保持选中状态。我看到的是按钮在触摸时突出显示,然后在触摸完成时突出显示消失。按钮 - 永远 - 被选中。为什么这不起作用对我来说毫无意义,所以我觉得我在做一些愚蠢的事情。我检查了我所有的 IB 连接,它们都很好......
    • 我不相信您可以在界面生成器中为突出显示+选择状态设置背景图像,只能分别设置突出显示和选择状态。如果您的按钮处于同时设置突出显示和选择的状态,我相信它将默认为您的正常图像,而不是突出显示或选定的图像。从您的代码中,您正在设置按钮的状态,以便选中和突出显示都是“是”。 checkInButtonPushed 是否连接到“Touch Up Inside”或其他内容?
    • 是的,它连接到“Touch Up Inside”。如果我删除与“突出显示”状态相关的代码,它仍然不起作用。 “选定”状态永远不会显示。
    • 另外,为什么要禁用该按钮?这实际上意味着按钮状态是禁用+突出显示+选择。如果您将突出显示的行设置删除为 YES,那么您已禁用+已选择,因此您需要为 (UIControlStateDisabled|UIControlStateSelected) 状态设置图像。
    • 好的,这就是问题所在。当我取出禁用功能时,它按预期工作。谢谢! (为了回答您的问题,我禁用了该按钮,因为我不希望任何人在网络运行期间再次按下它。)
    【解决方案2】:

    我有一个更简单的方法。只需使用延迟为 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];
    }
    

    【讨论】:

      【解决方案3】:

      “打开电源后一切都会变好”

          button.selected = !button.selected;
      

      完美运行...在我将插座连接到 Interface Builder 中的按钮之后。

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

      【讨论】:

        【解决方案4】:

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

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

        希望这会有所帮助。

        【讨论】:

        • 这是一个很好的解决方案,Roberto & Parth。不过,一个小细节是,如果用户将手指放在按钮上,您偶尔会看到“闪烁”。有什么办法可以防止闪烁?
        【解决方案5】:

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

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

        更新

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

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

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

        【讨论】:

        • 仅供参考 dispatch_get_current_queue() 被声明为“不可靠”。
        • 这是在哪里说明的?有什么选择?
        • 使用dispatch_after而不是dispatch_async有什么意义吗?
        • 是的。 dispatch_async 是更好的选择。
        【解决方案6】:

        在 swift 中,我正在按照以下方式进行操作。

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

        非常适合我。

        【讨论】:

          【解决方案7】:

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

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

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

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

          【讨论】:

            【解决方案8】:

            我有另一种方法...如果您不想使用图像,并且想要按下按钮的效果,您可以将 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;
            
                 }
            
            
             } `
            

            【讨论】:

              【解决方案9】:

              这是使用上述方法的 C#/MonoTouch (Xamarin.iOS) 实现。它假定您已经设置了 Highlighted 图像状态,并配置 selected 和 selected|highlighted 状态以使用相同的图像。

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

              【讨论】:

                猜你喜欢
                • 2014-09-10
                • 1970-01-01
                • 2014-09-05
                • 2021-04-30
                • 1970-01-01
                • 2020-09-16
                • 2014-08-29
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多