トランジション[1] UIViewを使ったもの

2010年9月30日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

トランジション調査の為に簡単なサンプルを作った。

UIViewのトランジション


UIViewには次の5つが用意されている。
typedef enum {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
} UIViewAnimationTransition;

これらを見ることのできるサンプルを作った。

FlipFromLeft

CurlUp


ソースコード


アニメーション部分だけ抜き出すとこんな感じ。
- (void)doTransition:(UIViewAnimationTransition)transition
{
 [UIView beginAnimations:nil context:nil];
 
 [UIView setAnimationTransition:transition
         forView:self.imageView
        cache:NO];
 [UIView setAnimationDuration:self.slider.value];
 imageIndex = (imageIndex+1)%8;
 self.imageView.image = [self.images objectAtIndex:imageIndex];
 
 
 [UIView commitAnimations];
}

-(IBAction)none:(id)sender
{
 [self doTransition:UIViewAnimationTransitionNone];
}
 :
 :

UIImageView を1枚用意しておき、アニメーションのトランザクション内でトランジションタイプを設定し、画像を入れ替えるだけ。実に簡単だ。


GitHub からどうぞ。

TransitionSample at 2010-09-30 from xcatsan's iOS-Sample-Code - GitHub


参考情報


C開発者によるiPhoneプログラミング: UIViewクラスで裏返したりめくったり

UIView Class Reference


- - - -
簡単だがこの方法だとディゾルブ(フェードイン・フェードアウトを組み合わせて画像を入れ替える)はできない。CATransition を使うとこれができる。

簡易スライドビューア [13] UIPageControl を追加

2010年9月29日水曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加

UIPageControl を追加してみた。

追加自体は簡単で UIPageControl のインスタンスを作成し、表示したい UIViewに追加するだけ。
// setup page control
 CGRect pageControlFrame = CGRectMake(
            0, self.bounds.size.height-DEFAULT_MARGIN_HEIGHT,
            self.bounds.size.width, DEFAULT_MARGIN_HEIGHT);
 self.pageControl = [[[UIPageControl alloc] initWithFrame:pageControlFrame] autorelease];
 self.pageControl.autoresizingMask =
  UIViewAutoresizingFlexibleLeftMargin  |
  UIViewAutoresizingFlexibleWidth       |
  UIViewAutoresizingFlexibleRightMargin |
  UIViewAutoresizingFlexibleTopMargin   |
  UIViewAutoresizingFlexibleHeight      |
  UIViewAutoresizingFlexibleBottomMargin;
 self.pageControl.hidesForSinglePage = NO;
 [self.pageControl addTarget:self
       action:@selector(pageControlDidChange:)
      forControlEvents:UIControlEventValueChanged];
 [self addSubview:self.pageControl];

今回少し手間取ったのは UIPageControl をクリックした時の処理。UIControlEventValueChanged イベントが発生すると addTarget:action:forControlEvents: で指定したメソッドが呼び出されるので、この中で指でスクロールした時と同じ処理を行う必要がある。スクロール位置を決めるのに -[UIScrollView scrollRectToVisible:animated:] を使ってみたが、動作が怪しくなったので UIScrollView.contentOffset の指定に切り替えた。このままだとアニメーションしないので +[UIView beginAnimations:context:] で囲ってやる。
[UIView beginAnimations:nil context:nil];
 self.scrollView.contentOffset = CGPointMake(
   self.contentOffsetIndex*size.width, 0);
 [UIView commitAnimations];

ソースコードは GitHub からどうぞ。
EasyGallery at 2010-09-29 from xcatsan's iOS-Sample-Code - GitHub


参考情報


UIPageControl の扱いは下記が参考になった。

簡易スライドビューア [12] 隣の画像が見えるモード追加(改良)

2010年9月28日火曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

前回のコードだと画像をめくった時にスクロールが完了するまで隣の画像が表示されなかった。


これはスクロールが完了した後、隣の画像を用意しているため。表示させるにはスクロール前にあらかじめ2つ先の画像を用意する必要がある。現在は3つの UIScrollView を横に並べているが、数を増やして5つにする。

すると出るようになった。


隣の画像が見えない場合は無駄ができるが、大きなものではないのでとりあえずこのまま行こう。

ソースコードは GitHub からどうぞ。
EasyGallery at 2010-09-28b from xcatsan's iOS-Sample-Code - GitHub

簡易スライドビューア [11] 隣の画像が見えるモード追加

2010年9月27日月曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

プロパティを追加
@property (nonatomic, assign) BOOL showcaseModeEnabled;

YES にすると隣の画像が見えるようになる。

拡大もOK。
画面回転もOK。

※iPad でも動作確認済み。

ソースは GitHub からどうぞ。
EasyGallery at 2010-09-27 from xcatsan's iOS-Sample-Code - GitHub


- - - -
EasyGalleryは1枚絵を見ることが主目的で、隣が見える動作はどちらかと言えばおまけ的な機能。ちょっとしたトリックっぽい処理で実現しているので、隣の画像はフリックに反応しない。横に画像を並べてみせる U/I は別途作った方がいい。

モックアップ作り - MockApp

2010年9月26日日曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

iOSアプリ開発で使えるモックアップ作成ツール(パーツ)を探している。

いろいろあるようだ。
モックアップ作成サービス&ソフトウェア 25選 at Cool Coding


探しているうちに見つけたのがこれ。

MockApp


Keynote と PowerPoint 用に画像パーツを提供している。
利用にあたっては次の3つの内どれかを行う必要がある。

  1. twitterでURLを紹介
  2. ブログでURLを紹介
  3. 3人の友人に知らせる

またダウンロード時にはユーザ登録が必要(無料)。

- - - -
他に illustrator(*.ai) や photoshop(*.psd) 形式のものもあったが、どちらも持っていないので当面 MockAppを使ってみる。

簡易スライドビューア [10] バグフィックスなど

2010年9月25日土曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: 簡易スライドビューア [9] ライブラリ化へ一歩

前回 GitHub に入れたコードはコンパイルできなかった。。他、いくつかバグを見つけたので修正した。

ソースコード
xcatsan's iOS-Sample-Code at 2010-09-25 - GitHub


ビューの大きさは画面いっぱいである必要はなく、こんな感じにもできる。
ちゃんとスクロールも働く。

回転するとこう。


なおピンチによる拡大縮小はビューが画面中央にある時だけ働く。

- - - -
ソースコードの公開していますが後ほどライセンスを付与して無料で自由に使えるようにする予定。
ライセンスはどういうのが便利なんだろう。

簡易スライドビューア [9] ライブラリ化へ一歩

2010年9月24日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

後々使いわしができるように UIViewController 内に実装していたコードを別のクラスへまとめた。

XCGalleryView


新しく XCGalleryView というクラスを作った。
@class XCGalleryView;
@protocol XCGalleryViewDelegate

-(NSInteger)numberViewsInGallery:(XCGalleryView*)galleryView;
-(UIImage*)galleryImage:(XCGalleryView*)galleryView filenameAtIndex:(NSUInteger)index;

@end


@interface XCGalleryView : UIView <UIScrollViewDelegate> {

 NSInteger currentImageIndex_;
 
 UIScrollView* scrollView_;
 NSInteger contentOffsetIndex_;
 
 NSMutableArray* imageScrollViews_;
 
 CGSize previousScrollSize_;
 
 CGFloat spaceWidth_;
 
 id <XCGalleryViewDelegate> delegate_;
}

@property (nonatomic, assign) NSInteger currentImageIndex;

@property (nonatomic, retain) UIScrollView* scrollView;
@property (nonatomic, assign) NSInteger contentOffsetIndex;

@property (nonatomic, retain) NSMutableArray* imageScrollViews;

@property (nonatomic, assign) IBOutlet id <XCGalleryViewDelegate> delegate;

@property (nonatomic, assign) CGFloat spaceWidth;
@end

合わせて XCGalleryViewDelegateというプロトコルを定義した。UITableViewDataSourceのように表示する画像情報を取得するのに使う。

実装はソースコードを参照のこと。


利用


InterfaceBuilderで UIViewを貼り付けた後、クラスを XCGalleryView に変え、File's Owner をdelegate先にしておく。


そして XCGalleryViewDelegate の2つのメソッドを実装する。
-(NSInteger)numberViewsInGallery:(XCGalleryView*)galleryView
{
 return [self.imageFiles count];
}

-(UIImage*)galleryImage:(XCGalleryView*)galleryView filenameAtIndex:(NSUInteger)index
{
 return [UIImage imageWithContentsOfFile:[self.imageFiles objectAtIndex:index]];
}

これで終わり。


ソースコード


GitHubからどうぞ。
EasyGallery at 2010-09-24 from xcatsan's iOS-Sample-Code - GitHub


参考情報


ライブラリ化にあたっては下記サイトのコードが参考になった。
iPhone/iPad – AppStore like UIScrollView with paging and preview | blog.sallarp.com

簡易スライドビューア [8] 画像間に空白を入れる

2010年9月23日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

以前検証した画像間に空白を入れるやつを簡易スライドビューアへ組み込んだ。

[参考] Cocoaの日々: UIScrollView - ページスクロールで空白を挟む


空白あり版


修正内容はその時の検証結果を反映しただけ(コード解説は割愛)。

実行してみよう。
スクロールさせるとちゃんと空白が出てる。(※わかりやすいように灰色にしてある)

拡大しても問題なし。

横に回転しても問題なし。よさそうだ。


ソースコード


GitHubからどうぞ。
EasyGallery at 2010-09-23 from xcatsan's iOS-Sample-Code - GitHub



参考情報


夜景 - フリー写真素材 (無料壁紙画像) Futta.NET

UIScrollView - 隣の画像も表示する

2010年9月22日水曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: UIScrollView - ページスクロールで空白を挟む

前回のブログのコメントで KatokichiSoft さんから面白い情報をいただいた。

iPhone/iPad – AppStore like UIScrollView with paging and preview | blog.sallarp.com

UIScrollView を使って AppStore のような画像表示をする方法について書かれている。サンプルをダウンロードして実行するとこんな感じ。


これはなかなかいい。真似してみよう。


clipsToBounds = NO


ソースコードを読んでわかったポイントは次の2つ。

1. UIScrollView を画面より小さくする
2. UIScrollView.clipsToBounds = NO とする

1. は例えば 320x460 の画面の場合、この領域いっぱいにするのではなく 240x380 などと小さくする。その上で clipsToBounds=NO すると本来表示されない UIScrollView.frame の外側にサブビューが描画される。

なるほど。その手があったか。前回のサンプルに組み込んでみよう。


サンプル実装


前回まではこんな感じ。
scrollView.frame と画面の大きさが一致していた(青い点線)。
これを下の様に変える。

scrollView.frame はそのままだが、画面の大きさ(赤い点線)よりも小さくする。

変更したのは先に上げたポイントの2つだけ。

まず Interface Builder で UIScrollView の大きさを小さくした。

以前は画面いっぱいに広げていたのを CGRect(40,40,240,380)とした。

次にコードを1文追加。
self.scrollView.clipsToBounds = NO;
これで終わり(※実際にはピクセル数値を直接記述したところがあったのでそれは直した)。

実行してみよう。

隣が表示された。スクロールしても問題なし。


ソースコード


GitHub からどうぞ。
ScrollViewPaging at 2010-09-22 from xcatsan's iOS-Sample-Code - GitHub


- - - -
紹介してもらったソースコードはその他、ライブラリ化するにあたっての方法についても参考になった(デリゲートの導入と、UIViewController ではなく カスタムUIViewをベースとするなど)。なおそのソースでは画像間の隙間はプログラム的に作っているのではなく、単にビューよりも小さな画像を表示させていることによる。この為、大きな画像を表示させると表示が崩れる(サンプルだから別にいいのだが、隙間を入れる処理は入っていないということで)。

UIScrollView - ページスクロールで空白を挟む

2010年9月21日火曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加

UIScrollView.pagingEnabled = YES とするとページスクロールが可能になる。この場合、写真同士がぴったりとくっついたようになる。

しかし標準の写真アプリだとフリックした時、写真と写真の間に黒い空白(40ピクセル)が入る。一工夫しているようだ。

写真アプリの方が見やすい。これを真似してみよう。


スペースを入れる


通常の UIScrollView ではこんな感じで内部のビューがぴったりと配置されている。

そこで SPACE_WIDTH(40ピクセル)分だけ間を開けてみた(実際にはビューの両側に SPACE_WIDTH/2.0分開けてある)。

1ページ毎に異なった色で塗りつぶしてスクロールが確認できるサンプルアプリを作ってみた。
初期状態。

フリックすると隙間(灰色)が見える。
ページスクロールが完了したところ。SPACE_WIDTHの分だけずれてる。
スクロールを繰り返すとズレ幅が大きくなっていく。

多分こんなふうになっている。
フリックすると frameの大きさだけスクロールされている。
だからズレる。

うーむ。


UIScrollViewの幅を広げる


リファレンスUIScrollView - pagingEnabledによればページスクロールは UIScrollViewの bounds が単位になると書いてある。
If the value of this property is YES, the scroll view stops on multiples of the view bounds when the user scrolls. The default value is NO.

ということは bounds の幅を SPACE_WIDTH分だけ広げてやればいいのでは?

そこでこんな風にしてみた。
scrollView.frame を (x=0, width=320) から (x=-SPACE_WIDTH/2, wdith=320+SPACE_WIDTH) とした。つまり可視範囲をはみ出して設定した。これによって bounds の幅が 320+SPACE_WIDTHとなり、ページスクロール時にスペースを考慮してスクロールが起こるようになるはず。


実装


実装してみよう。まずカスタムビューを定義しておく。
@interface CustomView : UIView {
 UIColor* color;
}
@end

初期化時にランダムもどきな色を決めてその色で塗りつぶす。
@implementation CustomView

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        // Initialization code
  CGFloat red = (rand()%255) / 255.0;
  CGFloat green = (rand()%255) / 255.0;
  CGFloat blue = (rand()%255) / 255.0;
  color = [UIColor colorWithRed:red
        green:green
         blue:blue
        alpha:1.0];
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
 
 CGRect rect1 = CGRectMake(0, 0, 320, 460);
 CGContextRef context = UIGraphicsGetCurrentContext();
 
 [color set];
 CGContextFillRect(context, rect1);
 [[UIColor whiteColor] set];
 CGContextSetLineWidth(context, 5);
 CGContextStrokeRect(context, rect1);
}


次にスクロール処理のメイン。
@interface ScrollViewPagingViewController : UIViewController  {

 UIScrollView* scrollView;
}
@property (nonatomic, retain) IBOutlet UIScrollView* scrollView;
@end

5つの CustomViewを UIScrollView内に配置してページスクロールさせる。
#define SPACE_WIDTH 40
#define NUMBER_OF_VIEWS 5
- (void)viewDidLoad {
    [super viewDidLoad];

 CGRect scrollViewFrame = self.scrollView.frame;
 scrollViewFrame.origin.x -= SPACE_WIDTH/2;
 scrollViewFrame.size.width += SPACE_WIDTH;
 self.scrollView.frame = scrollViewFrame;
 self.scrollView.contentSize = CGSizeMake((320+SPACE_WIDTH)*NUMBER_OF_VIEWS, 460);
 self.scrollView.pagingEnabled = YES;

 CGFloat x = 0;

 for (int i=0; i < NUMBER_OF_VIEWS; i++) {
  
  // left space
  x += SPACE_WIDTH/2.0;

  // content
  CGRect rect = CGRectMake(x, 0, 320, 460);
  CustomView* view = [[[CustomView alloc] initWithFrame:rect] autorelease];
  [self.scrollView addSubview:view];
  x += rect.size.width;

  // right space
  x += SPACE_WIDTH/2.0;
 }
}
ポイントは、UIScrollViewの frameを可視範囲をはみ出すように設定していることと、CustomViewの両側に SPACE_WIDTH/2.0 分のスペースをいれていること。


さて実行してみよう。まず初期画面。

フリックすると灰色の空白が確認できる。

ページスクロール終了。ぴったりと意図した境界で止まる。
スクロールを繰り返してもズレは起きない。


ソースコード


GitHubからどうぞ。
ScrollViewPaging at 2010-09-21 from xcatsan's iOS-Sample-Code - GitHub

- - - -
わかってみたら簡単だったが、最初は scrollViewDidEndDecelerating: を使って強制的に位置を補正したりなんかしていた(これだと計算が面倒)。

簡易スライドビューア [7] iPad対応〜ユニバーサルアプリを作る

2010年9月20日月曜日 | Published in | 4 コメント

このエントリーをはてなブックマークに追加

[前回]

ユニバーサルアプリにしてiPadに入れてみた。

iPad対応


このサイトが参考になった。
3時間でiPhoneアプリをiPad対応にした : 管理人@Yoski

以下、記録。


1. ターゲットを iPad用にアップグレード


ターゲット上で右クリックして「現在のターゲットを iPad 用にアップグレード...」を選ぶ。
ユニバーサルアプリ(1つでiPhone/iPadに対応)にするのか、デバイス毎に別々のアプリとするのかを聞かれる。今回は「One Universal application」を選択。
すると "Resource-iPad" というグループが作成された。ただ中身は何も入っていなかった。

2. XIBを iPad用に作成


EasyGallery では2つのXcodeが作成した2つの XIBファイルを使っている。
MainWindow.xib
EasyGalleryViewController.xib
これらを iPad用に新規に作成する。

まず MainWindow.xib から。InterfaceBuilderでファイルを開いた後、「File」メニューから「Create iPad Version」を選択する。
すると MainWindow.xib をコピーした新しい XIBファイルが生成される。
名前を MainWindow-iPad.xib として保存する。この名前は Info.plist の設定と一致させておく必要がある。1. でターゲットをアップグレードした時に Info.plist にはデフォルトで "Main nib file base name (iPad)" が追加されている。値は "MainWindow-iPad"。

同様にして EasyGalleryViewController.xib も iPad用に新規作成する。名前は後ろに "-iPad" をつけて EasyGalleryViewController-iPad.xib とした。

なお「File」メニューで「Create iPad Version Using Autoresizing Masks」を選ぶと、Autoresizing Masksが iPad用に自動的に摘要される。大抵の場合、ビューのサイズを iPad用に拡大するのでこれは便利。

これで完了。


実機で実行


あっさり動いた。


横にすればちゃんと回転する。拡大時の回転も問題なし。


これはちょっと嬉しい。


その他


EasyGalleryViewController-iPad.xib はソースコード上に名前が現れない。また新規に作った MainWindow-iPad.xib の NIB Name は "EasyGalleryViewController" のまま。
自動的に"-iPad"が付くファイルを探してXIBを読み込んでいるようだ。画像等と同じく暗黙のルールがあるのだろうか。リファレンスを探したがこれについの説明は見つけられなかった。

10/8追記)iPhone用の XIBが使われていたことが判明。やっぱりこの設定を変える必要がある。


ソースコード


GitHubからどうぞ。
EasyGallery at 2010-09-20 from xcatsan's iOS-Sample-Code - GitHub


- - - -
わかってはいたけれど同じソースで iPhone/iPad 両方が動くのはすごいな。実際にアプリを作るときには作業量が増えるので大変だとは思うけれど。

人気の投稿(過去 30日間)