頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


ボタンに画像を使ってみる

ボタンに画像を使う場合について再確認してみました。

使うpng画像←今回使う画像はこれで、サイズは23 x 23ピクセルのpng画像です。

(1) 画像をセットする場合
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:button1];
button1.frame = CGRectMake(10, 10, 60, 60);
[button1 setImage:[UIImage imageNamed:@"twbtn1.png"] forState:UIControlStateNormal];
[button1 addTarget:self action:@selector(buttonTappedHandler) forControlEvents:UIControlEventTouchUpInside];
button1.layer.shadowOpacity = 0.5f;//shadow
button1.layer.shadowOffset = CGSizeMake(0, 2);//shadow
ボタン1

おー、ちゃんと影も画像のまわりに出来てるな。
意表をついてframe周りに出るんじゃないの?とか一瞬思いましたが。

ところでコード内にあるように、frameでサイズを 60 x 60ピクセルに設定してます。
というのも最初23 x 23ピクセルとして作成していたのですが、ボタンの押せる範囲が小さかったので大きくしたのです。
で、気が付いたのですが、ありがたいことにこういう場合、画像はframeの中心に自動的に配置してくれるんですね。
次の画像は、frameがどこにあるかわかるように色を付けたものです。

ボタン1(frameに色付き)

確かに、中心にあるな。


(2) 背景画像として使う
UIButton *button2 = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:button2];
button2.frame = CGRectMake(10, 10, 23, 23);
[button2 setTitle:@"/" forState:UIControlStateNormal];
[button2 setBackgroundImage:[UIImage imageNamed:@"twbtn1.png"] forState:UIControlStateNormal];
[button2 addTarget:self action:@selector(buttonTappedHandler) forControlEvents:UIControlEventTouchUpInside];
button2.layer.shadowOpacity = 0.5f;//shadow
button2.layer.shadowOffset = CGSizeMake(0, 2);//shadow
ボタン2

setBackgroundImage:forState: なんてメソッドがUIButtonクラスにあるので使ってみました。
背景画像に画像を設定できるんですね。
背景画像って言うくらいだから手前に文字の設定もできるんです(見にくいけど)。

ともかく、背景画像を自分で作成して文字列をコード内でいろいろと変えるような場合にはこの方法が使えるんだな。


(3) 画像をテキストの代わりに使う
UIButton *button3 = [UIButton buttonWithType:100];
[self.view addSubview:button3];
button3.frame = CGRectMake(10, 10, 230, 30);
[button3 setImage:[UIImage imageNamed:@"twbtn1.png"] forState:UIControlStateNormal];
[button3 addTarget:self action:@selector(buttonTappedHandler) forControlEvents:UIControlEventTouchUpInside];
ボタン3

よく使う100番のボタンなんかのテキストに相当する部分にも画像が置けるんですね。
ところが、どういうわけかframeのサイズが設定できません。
コードだと230 x 30ピクセルで指定してますが、実際のボタンのサイズはもっと小さいですよね。画像サイズを見て内部で決定してるんでしょうか。
うーん、設定する方法ないのかなあ。


iPod touchにiOS 5を入れてみた

やっぱりiOS 5を実機でも動作確認したくなったのですが、iPhone 3GSは実生活で使ってるし、動かなくなると困るアプリもたくさんあるし、ってことでiPod touch (4G)にiOS 5をインストールしてみました。

まずはiTunes 10.5 beta 6 とtouch用のiOS 5 beta 6をダウンロード。
iTunesをアップデートして、それを使ってtouchもアップデート。

ふんふん、なるほど、、、

バージョンが5.0だって画像をアップしようとしたけどそれ用の某アプリがiOS 5だからか動いてくれないじゃないか!


masksToBoundsでもマスクできる!

あー、CALayerクラスにmasksToBoundsなんて便利なプロパティがあったのねぇというお話です。

次のコードはUILabelオブジェクトがUIViewオブジェクトに乗っているというよくあるシンプルなものです :
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 150, 150)];
view.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1.f];
[self.view addSubview:view];
[view release];
    
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
label.backgroundColor = [UIColor clearColor];
[view addSubview:label];
[label release];
label.text = @"Stay Hungry. Stay Foolish.";
実行結果はこんな風になるはずです :

masksToBoundsを使わない場合

今まで深く考えなかったのですが、UIViewオブジェクトのフレームの外でもそれに乗ってるオブジェクト(ここではUILabelオブジェクト)は表示されてます。
ところがこれに、次の一行を足します :
view.layer.masksToBounds = YES;
すると先ほどのと異なり、、、 :

masksToBoundsを使った場合

おー、枠外のは表示されませんやん!
まるでマスクやん!(ってそういうプロパティ名だけどね)
このプロパティを知らなかったので、同様のことを実現するのにわざわざマスクしてましたもん。
しかも驚くことに、このmasksToBoundsを使う方法だとコード内でスクリーンショットを撮影する時に使う renderInContext: メソッドで無視されないのです!

参考:renderInContext:メソッドはマスクを無視する

あぁ、もっと早くこの方法を知っていればよかったのに!


textView: shouldChangeTextInRange: replacementText: 内で新しい文字列を作る

UITextViewクラスを使う時、入力された文字が何なのかをチェックする場合なんかに次のデリゲートメソッドを使うことがあります。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
このメソッドはユーザーが文字を入力するたびにコールされます。
次のコードは'Apple'と文字を入力した時に引数の内容を表示するコードとその結果です。

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    NSLog(@"'%@' text:%@ , loc:%d , len:%d",textView.text , text , range.location , range.length);
    return YES;
}
UITextViewでAppleと入力

結果1

ふんふん、なるほど。 textView.textは入力前の文字列が入ってるんだな。 で、textで入力された文字が入ってると。 NSRangeオブジェクトには位置とかが入っているのか。


ところで、これらの内容から入力後の文字列をすぐに得たかったのですが、、、
え、もしかして、入力された位置を特定して分解して挿入とかそういうややこしい処理になっちゃうの、、、?
とか思っていたのですが、ありがたいことに使えるメソッドがNSStringクラスにありました。
stringByReplacingCharactersInRange:withString:

これを使って上のコードを書き換えたコードと結果を以下に:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    NSString *newString = [textView.text stringByReplacingCharactersInRange:range withString:text];
    NSLog(@"'%@' text:%@ , loc:%d , len:%d → %@",textView.text , text , range.location , range.length , newString);
    return YES;
}

結果2

お~、一撃じゃねえかっ!


Xcode 4.2 beta 6をダウンロードしてみた

Xcode 4.2 beta 6

何を血迷ったか(?)先ほどXcodeを4.0.2から4.2(beta 6,スノレパ)へアップデートしました。
4.2はまだbeta版なので何かとあれですが、、、
まあiOS 5のAPIのお勉強であります。




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.