at_yasu's blog

ロード的なことを

UILabelで文字列表示

トラックバック先(アプリでグルグル画像(indicator)をIBを使わずに簡単に表示させる方法 - わっふるわっふる)にて、

> グルグルしつつ Loading... みたいな文字はどうやってだすのか不明。

とあったので、UILabelで表示する方法。*1

「Loading.」→「Loading..」→「Loading...」と時間が経つ事に、「.」が増えたり減ったりするのには対応してませんが、NSThreadや[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:... userInfo:nil repeats:YES]; などでメソッドを呼び出し、内部でUILabelのテキストを書き換える方法があると思います。


以下ソースコード

@interface TIView : UIView
{
}

- (void) stop;
@end

#define INDICATOR_TAG  100
#define LABEL_TAG	  101
#define LOADING_STRING @"Loading..."

@implementation TIView
- (void) addLabel
{
	// 既にlabelが張られてないか確認
	UILabel* label = (UILabel*)[[self superview] viewWithTag:LABEL_TAG];
	// Loading...のフォントを設定。
	UIFont *loadingFont = [UIFont fontWithName:@"Times New Roman" size:21.0f];
	
	// labelが張られてない場合は新規に作成。
	if (!label)
	{
		// Loading... をUILabelで表示
		// フォントを指定し「Loading...」を描画した場合の、「Loading...」の大きさを取得
		CGSize size = [LOADING_STRING sizeWithFont:loadingFont];
		
		// 横幅、だいたい70px、縦だいたい12pxと考える
		CGRect loadingFrame = CGRectMake(160.0f - size.width / 2,
										 240.0f + 32.0f,
										 size.width,
										 size.height);
		// UILabelで表示
		UILabel* label = [[UILabel alloc] initWithFrame:loadingFrame];
		// Font指定
		label.font = loadingFont;
		// Loading... と指定
		label.text = LOADING_STRING;
		// 後で取り出せるように、タグを指定
		label.tag  = LABEL_TAG;
		// 文字の色を指定。今回はベタに黒
		label.textColor = [UIColor blackColor];
		// subviewに追加
		[self addSubview:label];
		// 解放
		[label release];
	}
	else
	{
		// ここでlabelの文字とか変えてみたり、ごにょごにょごにょ...
	}
}

- (void) addIndicators
{
	// ActivityIndicatorの大きさを設定
	CGRect activityIndicatorFrame = CGRectMake(0, 0, 32.0f, 32.0f);
	
	// 大きさを指定してインスタンスを生成
	UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:activityIndicatorFrame];
	// 画面の真ん中の表示するように設定
	[activityIndicator setCenter:CGPointMake(160.0f, 240.0f)];
	// 色を設定
	[activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
	// あとで取り出せるようにタグを設定
	activityIndicator.tag = INDICATOR_TAG;
	// subview に追加する
	[self addSubview:activityIndicator];
	// グルグルスタート
	[activityIndicator startAnimating];
	
	// 解放
	[activityIndicator release];
}

- (id)initWithFrame:(CGRect)frame
{
	if (self = [super initWithFrame:frame])
	{
		// Initialization code
		// Indicatorを付ける
		[self addIndicators];
		// Loading...を付ける
		[self addLabel];
	}
	return self;
}

// 何か処理を行って、準備できたらこれを呼ぶ
- (void)stop {
	// タグ指定で追加したUIActivityIndicatorViewを取得する
	UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *)[[self superview] viewWithTag:INDICATOR_TAG];
	// グルグルストップ
	[activityIndicator stopAnimating];
	// 解放
	[activityIndicator release];
	
	// ラベルを取得。面倒なので、UIViewとして取得。
	UIView* label = [[self superview] viewWithTag:LABEL_TAG];
	// 解放
	[label release];
}
@end

IBでする方法。ものすごく適当な説明だけど。

IBの場合だと、ActivityIndicatorとUILabelをwindowに貼付けて、下記のようにヘッダーファイルを書き換えて、IB上でつなげてやる必要があります。UIViewを作るのが面倒だったのでAppDelegateのクラスに書いちゃってます。参考にすらならないかも・・・

@interface testindicatorAppDelegate : NSObject <UIApplicationDelegate> {
	UIWindow *window;
	
	IBOutlet UIActivityIndicatorView* activityIndicator; // くるくるのActivityIndicator
	IBOutlet UILabel*                 label; // Loading...と表示させるラベル
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView* activityIndicator;
@property (nonatomic, retain) IBOutlet UILabel* label;
@end

@implementation testindicatorAppDelegate

@synthesize window;
@synthesize activityIndicator;
@synthesize label;


- (void)applicationDidFinishLaunching:(UIApplication *)application {
	// TIView(上のIBを使わずに、ActivityIndicatorを表示させるUIView)を生成
//	UIView* view = [[[TIView alloc] initWithFrame:[window frame]] autorelease];
	// windowに張りつけ。
//	[window addSubview:view];
	// IB上のactivityIndicatorのくるくるをスタート
	[activityIndicator startAnimating];
	// Override point for customization after application launch
	[window makeKeyAndVisible];
}


- (void)dealloc {
	[window release];
	[super dealloc];
}
@end

*1:NSStringにも、drawAtRect:withFont:ってのがあるけど、どうもUIViewのdrawAtRect:内でしか使えなくて、drawAtRect:がいつ呼び出されるか、setNeedsDisplayを自前で呼び出すにも面倒だったので、UILabelにしました。参考