今日はパパとどこ行こう
6才と3才のの娘とパパのお出かけ日記
箱根の海賊船
箱根に車で行ったら妙に空いている。
いつも渋滞の箱根町の海賊船乗り場に車がほとんどいないので、初めて寄ってみる。
直前まで悪天候だったのが、天候回復で、通常ダイヤに戻りますとのアナウンスが。
ならばと、初乗船。



桃源台まで行っても、特にやる事はないものの、せっかくなので、往復チケットを買ってみる。
船は大きくて、子供は大喜び。

これはラッキーだったと、思いつつ、桃源台についてから、
そのまま乗っても帰れるけど、せっかくなので、降りてみたのが失敗だった。

そこには大湧谷に行くロープウェイ乗り場ぐらいしか無く、
そのロープウェイも、雷雲が発生しているとかで、運休。

仕方が無いので、そこら辺りをプラプラ歩いて時間をつぶして、次の船の出航時間にあわせて並んでいたら突然の大雨。

だけど、散歩しているときに、空を見たら雨雲もあるものの、すぐ先に青空も見えていたので、すぐに止むと思っていたら、今日の船は全てキャンセルと、言い出した。

窓口に、いや、ここで立ち往生してどうするの?と、言っても、「だから払い戻しします。」と訳のわからない回答しか帰ってこない。金じゃないって、どうやって帰るの?と言うのが聞きたいのに、埒があかないので、とりあえずバス乗り場があったので、その近辺まで行ってみる事に。

ちなみに払い戻されたのは、往復1780円のうち、810円だけ。どうやら往復割引の入った合計から、片道の正規料金970円引いた額を払い戻したらしい。

なんか釈然としない。
でも、こんなのはまだ序の口。

バス停のそばにも海賊船のスタッフがいたので、箱根町までの帰り方を聞いてみると、
バスを乗り継がないと帰れないらしい。

マジで?と思いつつ、さらに行き方を聞いてみると、宮の下までバスで行って、その後、箱根に行くしかないと言う。
宮の下ってかなり下山して、それから登るってマジで言っているの?というレベル。

代替バスを出すとか無いの?そもそも平常運行になったとアナウンスを聞いたから来たのに、と聞いても、天候のせいだから仕方が無いでしょ、と言い返される始末。

仕方が無いので、バス停付近で聞き込みをしてみると、山のホテル行きの最終バスが15時15分にあって、
それで行って、後タクシーなりを使った方が良いのではないか?との事。

まったく、その方が良いじゃないか、本当に海賊船の職員の能のなさにはあきれる、と思っていたのも、実はまだ序の口。

それでも出航しないと言う事が信じられないほどの天気で、子供と家内をバス停に待たせて、船乗り場に行ってみると、今度は出航するとの事。

ふざけるな、と思いつつ、全員で船乗り場に行って、切符を買い直す事に。

ここまでの経緯から、タダでも良いくらいだ、と思っていたら今度はあろう事か、正規料金を請求される。
これだけしか払い戻し受けていない、と言うと、隣の人とコソコソ話して、その金額になったけど、
なんなんだ、この人たちは。

そんなこんなで、ようやく箱根町に戻ってきたときに、船内にある音楽が。。。。
あ、これ小田急グループか。

どおりで、サービス悪いはずだ。
小田急にサービス求めてもしょうがないからね。
サービス以前の問題で、乗せてやっているんだぐらいの対応が当たり前な会社だからね。

これに懲りて、もう二度と乗らない。

しかし、ロープウェイで大湧谷まで行っていなくてよかった。
あそこで、こんな風に見捨てられたら、大変。











[iPad開発]View追加方法 その2
viewDidLoad の中で、addSubview で作ったビューの中身をボタンを押したら変更する場合

UIImageView *iv_Red = [[UIImageView alloc] initWithImage:img_Red];

iv_Redのようにサブビューを表す変数は、
viewDidLoad で宣言したら、ボタンの処理をする関数では使えない。

いわゆる 変数のスコープというやつ。
簡単に言ってしまえば、 {} でくくられた中でしか、宣言した変数は使えない。

なので以下の場合、ボタンを押した時の処理で iv_Redは使えない。

- (void)viewDidLoad {
  UIImageView *iv_Red = [[UIImageView alloc] initWithImage:img_Red];
}
- (void) ButtonClickedEvent:(UIButton*)button{
// ボタンを押した時の処理
}

ヘッダーファイル「ViewController.h」に入れれば、このクラス全体で使えるようになるから、
その手もあるが、ここでは tag を使った方法について触れてみる。

ここで書いたUIView, UIControl両方とも、tag というプロパティを持っている。

数値しか使えないけど、

iv_Red.tag = 1;

のようにセットする。

この tag を指定して、該当するViewを変数に格納するには

UIImageView *iv_old = (UIImageView *) [self.view viewWithTag: 1 ];

のようにする。

これを使ったサンプルが次のもの。簡単に流れを書くと
1. 赤・緑・青を背景色にした三つの箱 (UIImageView)を重ね合わせる。それぞれに 1,2,3 という tag をつける
2. ボタンを三つ用意する。それぞれに 11,12,13という tag をつける
3. それぞれのボタンは押されたら、すべて ButtonClickedEvent という一つの関数を呼び出す
4. ButtonClickedEvent では、呼び出したボタンの tag を見て、それから 10 引いたタグの View を取得
5. そのViewのサイズ・背景色をコピーしたViewを作り、それを最上位に追加する(addSubview)
6. View を削除する ( removeFromSuperview )

ここで、プログラムからボタンを追加するやり方も、さらっと入れてしまいましたが、
それは次回にします。

これを動かすと最初このような画面になり
スクリーンショット 2012-04-30 7.26.30

例えば RedUp というボタンを押すと、このように赤が上になります。
スクリーンショット 2012-04-30 7.41.19


ちなみに、最初私も間違えて ボタンとUIImageViewの両方に同じtagを設定してしまいました。
そうすると、一回目はうまく絵の上下関係がかわるのですが、
二回目はボタンが消えました。

どうやら viewWithTag は重ね合わせの下から探していくようで、
iv_Red (tag = 1) - btn_Red (tag = 1)
から

addSubview でこうなり
iv_Red(tag = 1) - btn_Red (tag = 1) - iv_new (tag = 1)

removeFromSuperviewでこうなって
btn_Red (tag = 1) - iv_new (tag = 1)

次のviewWithTagで
btn_Red を拾ったみたいです。
タグはユニークではなく、しかも、UIControlだろうがUIViewだろうがお構いなしに
拾ってくるので、注意が必要です。




- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.


// ここから
UIImageView *iv_Red = [[UIImageView alloc]init];
iv_Red.backgroundColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0];
iv_Red.frame = CGRectMake(0,0,100,100);
iv_Red.tag = 1;

UIImageView *iv_Green = [[UIImageView alloc]init];
iv_Green.backgroundColor = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0];
iv_Green.frame = CGRectMake(0,0,100,100);
iv_Green.tag = 2;

UIImageView *iv_Blue = [[UIImageView alloc]init];
iv_Blue.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];
iv_Blue.frame = CGRectMake(0,0,100,100);
iv_Blue.tag = 3;

// ここまで、赤・青・緑で塗りつぶした100x100の画像の準備

iv_Red.frame = CGRectMake(10,10,40,40);
iv_Red.tag = 1;
iv_Green.frame = CGRectMake(50,50,40,40);
iv_Green.tag = 2;
iv_Blue.frame = CGRectMake(30,30,40,40);
iv_Blue.tag = 3;


[self.view addSubview:iv_Red];
[self.view addSubview:iv_Green];
[self.view addSubview:iv_Blue];

UIButton *btn_Red = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn_Red.frame = CGRectMake(150, 10, 100, 20);
[btn_Red setTitle:@"RedUp" forState:UIControlStateNormal];
[btn_Red addTarget:self action:@selector(ButtonClickedEvent:) forControlEvents:UIControlEventTouchDown];
btn_Red.tag = 11;
[self.view addSubview:btn_Red];

UIButton *btn_Green = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn_Green.frame = CGRectMake(150, 40, 100, 20);
[btn_Green setTitle:@"GreenUp" forState:UIControlStateNormal];
[btn_Green addTarget:self action:@selector(ButtonClickedEvent:) forControlEvents:UIControlEventTouchDown];
btn_Green.tag = 12;
[self.view addSubview:btn_Green];

UIButton *btn_Blue = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn_Blue.frame = CGRectMake(150, 70, 100, 20);
[btn_Blue setTitle:@"BlueUp" forState:UIControlStateNormal];
[btn_Blue addTarget:self action:@selector(ButtonClickedEvent:) forControlEvents:UIControlEventTouchDown];
btn_Blue.tag = 13;
[self.view addSubview:btn_Blue];


}
- (void) ButtonClickedEvent:(UIButton*)button{
UIImageView *iv_old = (UIImageView *) [self.view viewWithTag:button.tag - 10];
UIImageView *iv_new = [[UIImageView alloc]init];
iv_new.backgroundColor = iv_old.backgroundColor;
iv_new.frame = iv_old.frame;
iv_new.tag = iv_old.tag;

[self.view addSubview:iv_new];
[iv_old removeFromSuperview];
}


[iPad開発]View追加方法
ビューを追加するには addSubview 以外にもあるので、
その話題を。

階層を指定して挿入するには
insertSubview:atIndex:

UIViewを指定して、その上に配置するなら
insertSubview:aboveSubview:
下に配置するなら
insertSubview:belowSubview:

例えば、

// ここから
CGContextRef context = CGBitmapContextCreate(NULL, 100, 100, 8, 100 * 4,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSaveGState(context);
CGContextSetRGBFillColor(context, 1.0,0.0,0.0,1.0);
CGContextFillRect(context,CGRectMake(0,0,100,100));

CGImageRef imgr_Red = CGBitmapContextCreateImage(context);
UIImage* img_Red = [UIImage imageWithCGImage:imgr_Red];

UIImageView *iv_Red = [[UIImageView alloc] initWithImage:img_Red];

CGContextSetRGBFillColor(context, 0.0,1.0,0.0,1.0);
CGContextFillRect(context,CGRectMake(0,0,100,100));

CGImageRef imgr_Green = CGBitmapContextCreateImage(context);

UIImage* img_Green = [UIImage imageWithCGImage:imgr_Green];

UIImageView *iv_Green = [[UIImageView alloc] initWithImage:img_Green];

CGContextSetRGBFillColor(context, 0.0,0.0,1.0,1.0);
CGContextFillRect(context,CGRectMake(0,0,100,100));

CGImageRef imgr_Blue = CGBitmapContextCreateImage(context);

UIImage* img_Blue = [UIImage imageWithCGImage:imgr_Blue];

UIImageView *iv_Blue = [[UIImageView alloc] initWithImage:img_Blue];

// ここまで、赤・青・緑で塗りつぶした100x100の画像の準備

iv_Red.frame = CGRectMake(10,10,40,40);
iv_Green.frame = CGRectMake(50,50,40,40);
iv_Blue.frame = CGRectMake(30,30,40,40);

[self.view addSubview:iv_Red];
[self.view addSubview:iv_Green];
[self.view addSubview:iv_Blue];

CGContextRelease(context);

これを実行すると、
赤・緑・青の順番に上に重ねているのでこんな感じ。

スクリーンショット 2012-04-29 19.48.30


これを

iv_Red.frame = CGRectMake(10,10,40,40);
iv_Green.frame = CGRectMake(50,50,40,40);
iv_Blue.frame = CGRectMake(30,30,40,40);


[self.view addSubview:iv_Red];
[self.view addSubview:iv_Green];
[self.view insertSubview:iv_Blue aboveSubview:iv_Red];

に変えると、
青を赤の上にのせたので、こうなる。

スクリーンショット 2012-04-29 19.50.57

ちなみに
[self.view insertSubview:iv_Blue belowSubview:iv_Green];

でも、
[self.view insertSubview:iv_Blue atIndex:1];
でも、結果は同じ。

ただ、普通は、こんな面倒な事はしないですね。

最初から、下から順番にaddsubviewをすればよいのですから。

一回viewに配置してしまって、例えばボタンを押した時などのように、
後から挿入するときに、使うんでしょう。

そのときに、このUIImageView *iv_Blueをずっとキープするか、
配置順を覚えていて、指定する事もできるのですが

もっと簡単な方法があります。

それは次回。。。




[iPad開発]Viewについての理解
イメージ004

Viewの関係は
簡単にイメージで書くとこんな感じかな?

一番下にはUIScreenとかUIWindowがあるけど、iPadはシングルウィンドウなので、あまり意識する必要がない。

スクリーンサイズを取りたいときに UIScreen を使うぐらいかな。
後、Retinaディスプレイかどうかを判断するために解像度を取るときにも使う。

解像度の取り方
[[UIScreen mainScreen] scale]

Retinaだと、2.0, そうでなければ1.0が返ってきます。

スクリーンサイズの取り方
CGRect *r = [[UIScreen mainScreen] bounds];

CGRect は構造体で、開始の座標と、幅高さが返ってくる。
(float) origin.x
(float) origin.y
(float) size.width
(float) size.height

基本は、ウィザードを通じて、最初から作られる一つのビューの上に、
UIView もしくは UIControl を乗っけていくイメージ。

UIView には、ラベル、ImageView、ピッカービュー、
UIControl には、ボタン、テキストフィールド
などがある。

UIViewとUIControlの区別は配置する上ではあまり意識する必要がなく
配置の仕方は

[乗っける元のView addSubview: 乗っけるUIView or UIControl];

具体的にボタンを配置するのはこんな感じ。

UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(250,526,51,32);
[self.view addSubview:btn];

この意味は
1. 楕円形のボタン (UIButtonTypeRoundedRect) を btn という変数で用意する
2. btn の配置する位置・サイズ (frame)を、(x,y) = (250,526) から、幅 51、高さ 32 にする
3. 自分のビュー (self.view) の上に、btn を配置する


ViewController の viewDidLoad にコードを書くのであれば
self.view とすると、最初の画面(View)の上に配置する事になります。

最初の画面以外の上にのせる事もできます。
例えば、最初の画面の上にimageviewを配置して、その上にボタンを配置したい場合は
こんな感じになります。

UIImageView *iv = [[UIImageView alloc] init];
iv.frame = CGRectMake(0,0,100,100);
[self.view addSubview:iv];

UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(10,10,50,50);
[iv addSubview:btn];

上にのせるのと、そうでない違いを見るには、以下のようなプログラムを起動してみると分かります。

// ここから
CGContextRef context = CGBitmapContextCreate(NULL, 100, 100, 8, 100 * 4,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSaveGState(context);
CGContextSetRGBFillColor(context, 1.0,0.0,0.0,1.0);
CGContextFillRect(context,CGRectMake(0,0,100,100));

CGImageRef img_r = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage* img = [UIImage imageWithCGImage:img_r];
// ここまでは、100 x 100の画像を作る部分(後ほど詳しく解説します)

// 100 x 100の画像を、(x,y) = (120,120) に配置
UIImageView *iv = [[UIImageView alloc] initWithImage:img];
iv.frame = CGRectMake(120,120,100,100);
[self.view addSubview:iv];

// "1" と書かれたボタンを、上記 UIImageViewの上に配置
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(10,50,50,50);

[btn setTitle:@"1" forState:UIControlStateNormal];
[iv addSubview:btn];

// "2" と書かれたボタンを、上記 self.view の上に配置
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn2.frame = CGRectMake(10,50,50,50);

[btn2 setTitle:@"2" forState:UIControlStateNormal];
[self.view addSubview:btn2];

これを実行してみると、こうなります。
btn の frame に入れている座標は同じなのに、ボタンの場所が違います。
ivの原点からの位置になっているので、ズレるんですね。

スクリーンショット 2012-04-29 12.12.54


ちなみに、上に重ねていくだけではなく、途中に挟んだり、入れ替えたりできますが、
長くなったので、それは次回。。。








iPad で地図を勉強できるアプリボタンをプログラムで配置してみる
まず、基本はView。(VBでいうFormかな)

最初にsingle view application で、プロジェクトを作っていれば、

スクリーンショット 2012-04-29 9.12.37

ViewController.h と ViewController.m ができる。

スクリーンショット 2012-04-29 9.15.46

これがMainStoryboard.storyboadのViewに関係するプログラムを書く所。

Viewが表示された後に呼び出される関数が既に作成されているので、
そこの中にプログラムを書いていくのが簡単。

- (void)viewDidLoad

というのがそれ。(VBでいうform_loadイベントかな)

VBの時は、main関数からスタートするか、form_loadイベントからスタートするか、選べたけど
XCodeにも、main.mがあるので、そこにコーディングできるのかな?

でも、VBの時はWindowを必要に応じて開けるイメージだったので
mainから始めて、Formをオープンしていたけど、
iPadは画面がスタートだから、viewDidLoadから始めるのも違和感が無い。

単なる印象(思い込み)の問題で、結果はかわらないんだけど。

Viewの基本的な概念は次回。。。





Copyright © 今日はパパとどこ行こう. all rights reserved.
FC2ブログ