フォームにチェックボックス コントロールを追加する必要があります。iOS SDK にはそのようなコントロールがないことは知っています。どうすればこれを行うことができますか?
15 に答える
これも私を怒らせており、私にとってうまく機能し、画像を使用する必要を回避する別のソリューションを見つけました。
- 新しいラベル オブジェクトを Interface Builder に追加します。
- Xcode で IBOutlet プロパティを作成し、それに接続します。以下のコードでは、誰かが全額を支払ったかどうかを知りたいので、それを「fullPaid」と呼んでいます。
- 以下の 2 つの関数を追加します。「touchesBegan」関数は、「fullyPaid」ラベル オブジェクト内のどこかに触れたかどうかをチェックし、そうであれば、「togglePaidStatus」関数を呼び出します。「togglePaidStatus」関数は、それぞれ空のボックス (\u2610) とチェック ボックス (\u2611) を表す Unicode 文字を含む 2 つの文字列を設定します。次に、「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];
}
通常、チェックボックスのような機能には UISwitch を使用します。
ただし、2 つの画像 (チェック/チェックなし) を持つイメージ コントロールを使用し、コントロールに触れたときに画像を切り替えることで、独自のロールを作成できます。
オプションのグループを表示していて、ユーザーがそのうちの 1 つを選択できる場合は、選択した行にチェックマーク アクセサリと別のテキスト色を付けたテーブルビューを使用します。
選択肢が 1 つしかない場合は、スイッチを使用するのが最善の策です。できない、またはしたくない場合は、ボタンを使用して、通常の画像を空のボックスに設定し、選択した画像をチェック ボックスに設定します。これらの 2 つの画像を自分で作成するか、それらに使用するストック グラフィックを見つける必要があります。
Adrean のアイデアを拡張して、私は非常に単純なアプローチを使用してこれを達成しました。私の考えは、ボタンの状態に応じて
ボタン (たとえば) のテキストを変更し、ボタンの状態を.
以下は、私がこれを行ったコードです。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
}
}
これをプログラムで実行し、ヒット領域が小さすぎるという問題も解決したかったのです。これは、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];
}
ここにある全員のコードは非常に長く、少し面倒ですが、もっと簡単に実行できます。ダウンロードしてチェックアウトできる UIControl をサブクラス化し、ほぼネイティブのチェックボックス UI 要素を提供する GitHub のプロジェクトがあります。
UIButton をサブクラス化し、ボタンを View Controller にドロップして選択し、ID インスペクターでクラス名を 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
奇妙な描画を避けるために UITextField を使用して作成しましたが、NSString: @"\u2713" のティック Unicode (Unicode Character 'CHECK MARK' (U+2713)) をテキストとして入れるのが好きでした。
このように、私の .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;
}
画像ではなくキャラクターを使用するエイドリアンのアイデアが気に入っています。しかし、私はボックスが好きではありません。チェックマーク自体 (@"\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];
}
}
}
ユーザーArunaLakmal; 参考までに、initWithFrameが呼び出されないことを説明するときに、このコードをIBに追加すると、initWithCoderが呼び出されます。initWithCoderを実装すると、説明どおりに機能します。