【问题标题】:Checkbox in iOS applicationiOS 应用程序中的复选框
【发布时间】:2010-10-13 14:27:56
【问题描述】:

我需要在表单中添加复选框控件。我知道iOS SDK中没有这样的控件。我怎么能这样做?

【问题讨论】:

    标签: ios iphone checkbox


    【解决方案1】:

    使用 SF 符号的简单 UIButton 子类可以解决问题

    class CheckBoxButton: UIButton {
        override init(frame: CGRect) {
            super.init(frame: frame)
            setup()
        }
    
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            setup()
        }
    
        func setup() {
            setImage(UIImage(systemName: "square.fill"), for: .normal)
            setImage(UIImage(systemName: "checkmark.square.fill"), for: .selected)
        }
    }
    

    故事板

    如果您使用故事板,请确保按钮类型设置为custom,如下图所示


    用法

    您所要做的就是在动作/选择器方法中切换isSelected 变量

    @objc func toggle(_ sender: UIButton) {
        sender.isSelected.toggle()
    }
    
    

    演示

    【讨论】:

      【解决方案2】:

      一个简单的UIButton 子类将能够表现得像 Android 中的复选框。

      import UIKit
      
      class CheckedUIButton: UIButton {
          var checked: Bool = false {
              didSet {
                  if checked {
                      setImage(UIImage(systemName: "checkmark.circle"), for: .normal)
                  } else {
                      setImage(UIImage(systemName: "circle"), for: .normal)
                  }
              }
          }
          
          //initWithFrame to init view from code
          override init(frame: CGRect) {
              super.init(frame: frame)
              
              commonInit()
          }
           
          //initWithCode to init view from xib or storyboard
          required init?(coder aDecoder: NSCoder) {
              super.init(coder: aDecoder)
              
              commonInit()
          }
          
          private func commonInit() {
              addTarget(self, action: #selector(self.checkedTapped), for: .touchUpInside)
          }
      
          @objc
          private func checkedTapped() {
              self.checked.toggle()
          }
      }
      

      输出

      (未选中状态)


      (选中状态)

      【讨论】:

        【解决方案3】:

        我最近做了一个。从 GitHub 免费获取。看看this 是否有帮助。效果是这样的

        【讨论】:

          【解决方案4】:

          扩展到Adrean's idea,我已经使用一种非常简单的方法实现了这一点。
          我的想法是根据其状态更改按钮(比如说checkBtn)文本,然后在其IBAction 中更改按钮的状态。
          下面是我如何做到这一点的代码:

          - (void)viewDidLoad
          {
              [super viewDidLoad];
          
              [checkBtn setTitle:@"\u2610" forState:UIControlStateNormal];    // uncheck the button in normal state
              [checkBtn setTitle:@"\u2611" forState:UIControlStateSelected];  // check the button in selected state
          }
          
          - (IBAction)checkButtonTapped:(UIButton*)sender {
              sender.selected = !sender.selected;    // toggle button's selected state  
          
              if (sender.state == UIControlStateSelected) {    
                  // do something when button is checked 
              } else {
                  // do something when button is unchecked
              }
          }
          

          【讨论】:

          • 不幸的是,就像 Adrian 的想法中提到的那样,关闭状态的角色看起来很糟糕:-/
          【解决方案5】:

          子类 UIButton,放一个按钮到视图控制器,选择它并在身份检查器中将类名更改为 CheckBox。

          #import "CheckBox.h"
          
          @implementation CheckBox
          
          #define checked_icon @"checked_box_icon.png"
          #define empty_icon @"empty_box_icon.png"
          
          - (id)initWithCoder:(NSCoder *)aDecoder
          {
              self = [super initWithCoder:aDecoder];
              if (self)
              {
                  [self setImage:[UIImage imageNamed:empty_icon] forState:UIControlStateNormal];
                  [self addTarget:self action:@selector(didTouchButton) forControlEvents:UIControlEventTouchUpInside];
              }
              return self;
          }
          
          - (void)didTouchButton {
              selected = !selected;
              if (selected)
                  [self setImage:[UIImage imageNamed:checked_icon] forState:UIControlStateNormal];
              else
                  [self setImage:[UIImage imageNamed:empty_icon] forState:UIControlStateNormal];
          }
          
          @end
          

          【讨论】:

            【解决方案6】:

            这是我的 iPhone 复选框版本。

            它是扩展 UIButton 的单个类。 这很简单,所以我将它粘贴在这里。

            CheckBoxButton.h 文件内容

            #import <UIKit/UIKit.h>
            
            @interface CheckBoxButton : UIButton
            
            @property(nonatomic,assign)IBInspectable BOOL isChecked;
            
            @end
            

            CheckBoxButton.m 文件内容

            #import "CheckBoxButton.h"
            
            @interface CheckBoxButton()
            
            @property(nonatomic,strong)IBInspectable UIImage* checkedStateImage;
            @property(nonatomic,strong)IBInspectable UIImage* uncheckedStateImage;
            
            @end
            
            @implementation CheckBoxButton
            
            -(id)init
            {
                self = [super init];
            
                if(self)
                {
                    [self addTarget:self action:@selector(switchState) forControlEvents:UIControlEventTouchUpInside];
                }
            
                return self;
            }
            
            -(id)initWithFrame:(CGRect)frame
            {
                self = [super initWithFrame:frame];
            
                if(self)
                {
                    [self addTarget:self action:@selector(switchState) forControlEvents:UIControlEventTouchUpInside];
                }
            
                return self;
            }
            
            -(id)initWithCoder:(NSCoder *)aDecoder
            {
                self = [super initWithCoder:aDecoder];
            
                if(self)
                {
                    [self addTarget:self action:@selector(switchState) forControlEvents:UIControlEventTouchUpInside];
                }
            
                return self;
            }
            
            -(void)setIsChecked:(BOOL)isChecked
            {
                _isChecked = isChecked;
            
                if(isChecked)
                {
                    [self setImage:self.checkedStateImage forState:UIControlStateNormal];
                }
                else
                {
                    [self setImage:self.uncheckedStateImage forState:UIControlStateNormal];
                }
            }
            
            -(void)switchState
            {
                self.isChecked = !self.isChecked;
                [self sendActionsForControlEvents:UIControlEventValueChanged];
            }
            
            @end
            

            您可以在Visual Studio的属性检查器中为选中/未选中以及isChecked属性设置图像。

            要在 storyboard 或 xib 中添加 CheckBoxButton,只需添加 UIButton 并设置自定义类,就像下一张图片一样。

            Button会发送UIControlEventValueChanged事件,每次isChecked状态发生变化。

            【讨论】:

            • 很好的答案,因为它适用于故事板,因此它避免了大量的定位代码(只留下干净的代码)并且我能够使用自定义图像。也很好地解释了,所以对于像我这样的 iOS 新手来说,这很容易实现。现在要弄清楚为什么我的图像像按钮上的文字一样显示为蓝色...
            • 好的,为了避免您的图像被 iOS 7+ 染成蓝色,请将属性类型设置为自定义,正如您在@slobodans 答案的第一个屏幕截图中看到的那样,但我从这里得到了答案:stackoverflow.com/a/21313338/1479962
            • 最佳答案!使按钮 IBDesignable 是一个很好的奖励!
            【解决方案7】:

            我使用 UITextField 来避免绘制任何奇怪的东西,但我喜欢将 NSString 的刻度 unicode (Unicode Character 'CHECK MARK' (U+2713)) 作为文本放入内部:@"\u2713"。

            这样,在我的 .h 文件中(实现 UITextField 'UITextFieldDelegate' 的协议):

            UITextField * myCheckBox;
            

            在我的 viewDidLoad 或准备 UI 的函数中:

            ...
            myCheckBox = [[UITextField alloc] initWithFrame:aFrame];
            myCheckBox.borderStyle = UITextBorderStyleRoundedRect; // System look like
            myCheckBox.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
            myCheckBox.textAlignment = NSTextAlignmentLeft;
            myCheckBox.delegate = self;
            myCheckBox.text = @" -"; // Initial text of the checkbox... editable!
            ...
            

            然后,添加一个事件选择器,用于在触摸事件中进行响应并调用“responseSelected”事件:

            ...
            UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(checkboxSelected)];
            [myCheckBox addGestureRecognizer:tapGesture];
            ...
            

            最后响应那个选择器

            -(void) checkboxSelected
            {
                if ([self isChecked])
                {
                    // Uncheck the selection
                    myCheckBox.text = @" -";
                }else{
                   //Check the selection
                   myCheckBox.text = @"\u2713";
                }
            }
            

            函数 'isChecked' 仅检查文本是否为 @"\u2713" 复选标记。为了防止在选择文本字段时显示键盘,请使用 UITextField 'textFieldShouldBeginEditing' 的事件并添加事件选择器来管理选择:

            -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
            {
                // Question selected form the checkbox
                [self checkboxSelected];
            
                // Hide both keyboard and blinking cursor.
                return NO;
            }
            

            【讨论】:

            • 很好的答案@mTouch - 除了在视图控制器中设置UITextFieldDelegate 之外,我唯一要做的就是将isChecked bool 定义为BOOL isChecked;。这意味着您的 if ([self isChecked]) 改为 if (isChecked)
            【解决方案8】:

            在.h文件中

            #import <UIKit/UIKit.h>
            
            @interface ViewController : UIViewController
            {
                BOOL isChecked;
                UIImageView * checkBoxIV;
            }
            @end
            

            还有.m文件

            - (void)viewDidLoad
            {
                [super viewDidLoad];
                isChecked = NO;
            
                //change this property according to your need
                checkBoxIV = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 15, 15)]; 
                checkBoxIV.image =[UIImage imageNamed:@"checkbox_unchecked.png"]; 
            
                checkBoxIV.userInteractionEnabled = YES;
                UITapGestureRecognizer *checkBoxIVTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handlecheckBoxIVTapGestureTap:)];
                checkBoxIVTapGesture.numberOfTapsRequired = 1;
                [checkBoxIV addGestureRecognizer:checkBoxIVTapGesture];
            }
            
            - (void)handlecheckBoxIVTapGestureTap:(UITapGestureRecognizer *)recognizer {
                if (isChecked) {
                    isChecked = NO;
                    checkBoxIV.image =[UIImage imageNamed:@"checkbox_unchecked.png"];
                }else{
                    isChecked = YES;
                    checkBoxIV.image =[UIImage imageNamed:@"checkbox_checked.png"];   
                }
            }
            

            这样就可以了...

            【讨论】:

              【解决方案9】:

              这也让我发疯了,我找到了一个不同的解决方案,它对我很有效,并且避免了使用图像。

              1. 向 Interface Builder 添加一个新的标签对象。
              2. 在 Xcode 中创建一个 IBOutlet 属性并将其连接到它。在下面的代码中,我将其称为“fullPaid”,因为我想知道是否有人已经全额支付了一笔钱。
              3. 添加以下 2 个函数。 “touchesBegan”函数检查您是否触摸了“fullyPaid”标签对象内的某个位置,如果是,它调用“togglePaidStatus”函数。 'togglePaidStatus' 函数设置两个字符串,它们的 unicode 字符分别代表一个空框 (\u2610) 和一个复选框 (\u2611)。然后它比较“fullyPaid”对象中当前的内容,并将其与另一个字符串切换。

              您可能希望在 viewDidLoad 函数中调用 togglePaidStatus 函数以将其初始设置为空字符串。

              显然,如果标签未启用,您可以添加额外的检查以防止用户切换复选框,但这未在下面显示。

              -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
              {
              UITouch *touch = [touches anyObject];   
                  if (CGRectContainsPoint([fullyPaid frame], [touch locationInView:self.view]))
                  {
                      [self togglePaidStatus];
                  }
              }
              -(void) togglePaidStatus
              {
                  NSString *untickedBoxStr = [[NSString alloc] initWithString:@"\u2610"];
                  NSString *tickedBoxStr = [[NSString alloc] initWithString:@"\u2611"];   
              
                  if ([fullyPaid.text isEqualToString:tickedBoxStr])
                  {
                      fullyPaid.text = untickedBoxStr;
                  }
                  else
                  {
                      fullyPaid.text = tickedBoxStr;
                  }
              
                  [tickedBoxStr release];
                  [untickedBoxStr release];
              }
              

              【讨论】:

              • 我非常非常喜欢这种方法。不必使用图形真是太好了。但是空的和选中的框看起来不太像,实际上相当不匹配。有什么办法可以解决吗?
              【解决方案10】:

              用户Aruna Lakmal;仅供参考,当您按照您的描述将此代码添加到 IB 时,不会调用 initWithFrame,而会调用 initWithCoder。实现 initWithCoder,它会按照你描述的那样工作。

              【讨论】:

                【解决方案11】:

                这里的每个人的代码都很长,略显凌乱,而且可以做得更简单。我在 GitHub 上有一个项目,它是 UIControl 的子类,您可以下载并查看它,并为您提供几乎原生的复选框 UI 元素:

                https://github.com/Brayden/UICheckbox

                【讨论】:

                  【解决方案12】:

                  我喜欢 Adrian 使用字符而不是图像的想法。但我不喜欢这个框,它只需要复选标记本身(@“\u2713”)。我以编程方式绘制了一个框(一个圆角框),并在其中放置了一个包含复选标记的 UILabel。这种实现方式可以轻松地在任何应用程序中使用自定义视图,而无需关心任何依赖资源。您还可以轻松自定义复选标记、圆角框和背景的颜色。 这是完整的代码:

                  #import <UIKit/UIKit.h>
                  
                  @class CheckBoxView;
                  
                  @protocol CheckBoxViewDelegate
                  - (void) checkBoxValueChanged:(CheckBoxView *) cview;
                  @end
                  
                  @interface CheckBoxView : UIView {
                      UILabel *checkMark;
                      bool isOn;
                      UIColor *color;
                      NSObject<CheckBoxViewDelegate> *delegate;
                  }
                  @property(readonly) bool isOn;
                  @property(assign) NSObject<CheckBoxViewDelegate> *delegate;
                  
                  - (void) drawRoundedRect:(CGRect) rect inContext:(CGContextRef) context;
                  @end
                  
                  
                  
                  #import "CheckBoxView.h"
                  
                  #define SIZE 30.0
                  #define STROKE_WIDTH 2.0
                  #define ALPHA .6
                  #define RADIUS 5.0
                  
                  @implementation CheckBoxView
                  @synthesize isOn, delegate;
                  
                  - (id)initWithFrame:(CGRect)frame {
                      if ((self = [super initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, SIZE, SIZE)])) {
                          // Initialization code
                      }
                      //UIColor *color = [UIColor blackColor];
                      color = [[UIColor alloc] initWithWhite:.0 alpha:ALPHA];
                  
                      self.backgroundColor = [UIColor clearColor];
                      checkMark = [[UILabel alloc] initWithFrame:CGRectMake(STROKE_WIDTH, STROKE_WIDTH, SIZE - 2 * STROKE_WIDTH, SIZE - 2*STROKE_WIDTH)];
                      checkMark.font = [UIFont systemFontOfSize:25.];
                      checkMark.text = @"\u2713";
                      checkMark.backgroundColor = [UIColor clearColor];
                      checkMark.textAlignment = UITextAlignmentCenter;
                      //checkMark.textColor = [UIColor redColor];
                      [self addSubview:checkMark];
                      [checkMark setHidden:TRUE];
                      isOn = FALSE;
                      return self;
                  }
                  
                  
                  // Only override drawRect: if you perform custom drawing.
                  // An empty implementation adversely affects performance during animation.
                  - (void)drawRect:(CGRect)rect {
                      // Drawing code
                      CGRect _rect = CGRectMake(STROKE_WIDTH, STROKE_WIDTH, SIZE - 2 * STROKE_WIDTH, SIZE - 2*STROKE_WIDTH);
                      [self drawRoundedRect:_rect inContext:UIGraphicsGetCurrentContext()];
                      [checkMark setHidden:!isOn];
                  }
                  
                  
                  - (void)dealloc {
                      [checkMark release];
                      [color release];
                      [super dealloc];
                  }
                  
                  - (void) drawRoundedRect:(CGRect) rect inContext:(CGContextRef) context{
                      CGContextBeginPath(context);
                      CGContextSetLineWidth(context, STROKE_WIDTH);
                      CGContextSetStrokeColorWithColor(context, [color CGColor]);
                      CGContextMoveToPoint(context, CGRectGetMinX(rect) + RADIUS, CGRectGetMinY(rect));
                      CGContextAddArc(context, CGRectGetMaxX(rect) - RADIUS, CGRectGetMinY(rect) + RADIUS, RADIUS, 3 * M_PI / 2, 0, 0);
                      CGContextAddArc(context, CGRectGetMaxX(rect) - RADIUS, CGRectGetMaxY(rect) - RADIUS, RADIUS, 0, M_PI / 2, 0);
                      CGContextAddArc(context, CGRectGetMinX(rect) + RADIUS, CGRectGetMaxY(rect) - RADIUS, RADIUS, M_PI / 2, M_PI, 0);
                      CGContextAddArc(context, CGRectGetMinX(rect) + RADIUS, CGRectGetMinY(rect) + RADIUS, RADIUS, M_PI, 3 * M_PI / 2, 0);
                      CGContextClosePath(context);
                      CGContextStrokePath(context);
                  }
                  
                  #pragma mark Touch
                  - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
                      UITouch *touch = [touches anyObject];
                      CGPoint loc = [touch locationInView:self];
                      if(CGRectContainsPoint(self.bounds, loc)){
                          isOn = !isOn;
                          //[self setNeedsDisplay];
                          [checkMark setHidden:!isOn];
                          if([delegate respondsToSelector:@selector(checkBoxValueChanged:)]){
                              [delegate checkBoxValueChanged:self];
                          }
                      }
                  }
                  

                  【讨论】:

                  • 我试过这段代码。它不起作用..我试图修复。但无法弄清楚问题所在。你能解决吗?
                  • 刚刚用 Xcode 4.2 iOS 5.0 检查了代码,没有错误。你在一个空的项目中尝试过吗?
                  • 是的。还是行不通。我在 xib 中添加了一个 UIView,并将该视图的类更改为 CheckBoxView。这不是它应该工作的方式吗?
                  • 你拯救了我的一天!谢谢。为了让它工作,我只得到了将复选标记初始化为 UILabel 的代码,几乎没有在代码中为它设置框架。
                  【解决方案13】:

                  我想以编程方式完成此操作,同时也解决点击区域实在太小的问题。这改编自各种来源,包括 Mike 和 Mike 的评论者 Agha。

                  在您的标题中

                  @interface YourViewController : UIViewController {
                      BOOL checkboxSelected;
                      UIButton *checkboxButton;
                  }
                  
                  @property BOOL checkboxSelected;;
                  @property (nonatomic, retain) UIButton *checkboxButton;
                  
                  -(void)toggleButton:(id)sender;
                  

                  在你的实现中

                  // put this in your viewDidLoad method. if you put it somewhere else, you'll probably have to change the self.view to something else
                  // create the checkbox. the width and height are larger than actual image, because we are creating the hit area which also covers the label
                  UIButton* checkBox = [[UIButton alloc] initWithFrame:CGRectMake(100, 60,120, 44)];  
                  [checkBox setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal];
                  // uncomment below to see the hit area
                  // [checkBox setBackgroundColor:[UIColor redColor]];
                  [checkBox addTarget:self action:@selector(toggleButton:) forControlEvents: UIControlEventTouchUpInside];
                  // make the button's image flush left, and then push the image 20px left
                  [checkBox setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
                  [checkBox setImageEdgeInsets:UIEdgeInsetsMake(0.0, 20.0, 0.0, 0.0)];
                  [self.view addSubview:checkBox];
                  
                  // add checkbox text text
                  UILabel *checkBoxLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 74,200, 16)];
                  [checkBoxLabel setFont:[UIFont boldSystemFontOfSize:14]];
                  [checkBoxLabel setTextColor:[UIColor whiteColor]];
                  [checkBoxLabel setBackgroundColor:[UIColor clearColor]];
                  [checkBoxLabel setText:@"Checkbox"];
                  [self.view addSubview:checkBox];
                  
                  // release the buttons
                  [checkBox release];
                  [checkBoxLabel release];
                  

                  把这个方法也放进去:

                  - (void)toggleButton: (id) sender
                  {
                      checkboxSelected = !checkboxSelected;
                      UIButton* check = (UIButton*) sender;
                      if (checkboxSelected == NO)
                          [check setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal];
                      else
                          [check setImage:[UIImage imageNamed:@"checkbox-checked.png"] forState:UIControlStateNormal];
                  
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    如果您要显示一组选项并且用户可以选择其中一个,请使用带有复选标记附件的表格视图,并在所选行上使用不同的文本颜色。

                    如果您只有一个选项,最好的办法是使用开关。如果您不能或不想,请使用按钮,将普通图像设置为空框,将所选图像设置为选中框。您必须自己制作这两个图像,或者找到用于它们的库存图形。

                    【讨论】:

                      【解决方案15】:

                      通常,您会使用 UISwitch 来实现类似复选框的功能。

                      您可以通过使用带有两个图像(选中/未选中)的图像控件并在它们触摸控件时切换图像来滚动自己/

                      【讨论】:

                      • 能否详细说明如何进行图像切换?谢谢!
                      • 虚拟 -1 到 yar 表示“+1 表示未详细说明”; vladimir mitrovic 的虚拟 -1 表示“-1 表示未详细说明”:)
                      • +(1-i) 到 LolaRun 进行虚拟化。
                      • 详细说明:使用 UIButton 并根据用户的触摸切换图像和selected 状态。或者使用 UILabel 并根据用户触摸切换文本。等等。
                      • 我完全同意 UISwitch 是实现复选框的最佳选择。
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-02-15
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多