スクロールの上にある画像をフリックで変える方法

このQ&Aのポイント
  • 画像を左右にスクロールさせる方法と画像を上下にフリックする方法を実装しています。
  • UIViewControllerにスクロールのメソッドを書き、もう一つのUIScrollViewを親に持つPageViewに画像の拡大縮小と上下のフリックのメソッドを書いています。
  • PageViewでの上下のフリックの操作によって、UIViewController上のスクロールに乗っている画像を変更したいのですが、方法が分かりません。
回答を見る
  • ベストアンサー

スクロールの上にある画像をフリックで変える方法とは

今、画像を左右に数枚スクロールさせ、かつ、その画像を上や下にフリックすると各々、上や下に他の画像がでてきて、さらに拡大縮小もできるようなコードを書いています。 ViewContorller(以下、VC)にスクロールのメソッドを書き、 もう一つのPageView(UIScrollVIewクラスを親にもつ。以下、PV)に画像が拡大縮小するようなメソッドと上下のフリックのメソッドを書いています。 このPVの中で行う上下のフリックの操作によって、VCにあるスクロールの上に乗っている画像を変えたいのですが、色々と試したのですがその方法が一向にわかりません。もし宜しければ、ご教授ください。宜しくお願い致します。 xcodeは5.0です。 以下、スクロールとその上に画像をのせているpageがあるVC.mのコードです。 このpageにのっている画像をPVのほうのフリック操作で変更させたいと思っています。 - (void)viewDidLoad { [super viewDidLoad]; UIScrollView *scrollView = [[UIScrollView alloc] init]; scrollView.frame = self.view.bounds; scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 3, self.view.frame.size.height); scrollView.pagingEnabled = YES; [self.view addSubview:scrollView]; //AppdelegateでValueというプロパティをつくり、PVでのフリック操作によってこの数値が変動したら、currentpageに反映して、それに対しての画像がでてくるようにしたいつもりです。 AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; //PageViewにて、画像をいれるメソッドをsetImageでつくっています。 for (int i=1;i<4;i++) { PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; [page setImage:[NSString stringWithFormat:@"%d.%d",currentpage,i]]; page.frame = CGRectMake( self.view.frame.size.width * (i-1), 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.8

> 今回、delegateを、sampleMethodメソッドの中のpageのところの下に書いたのですが(前回教えて頂いたのをヒントに)、delegateのサンプルで教えて頂いた例のようにdelegateをsampleMethodメソッドの外でつなげてなくても大丈夫でしょうか? No.6のお礼のソースは、sampleMethodメソッド内にdelegateを設定する処理がなくて、 外で設定しようとしていたのですね。元々のviewDidLoad内のPageView生成処理を そのままsampleMethod内に移したのだと思いこんでいて、気付いていませんでした。 No.7のお礼のソース通り、sampleMethodメソッド内にdelegateを設定するので 問題ありません。これが正しいです。 delegateの設定は、そのオブジェクトの初期化処理の1つと考えればよいです。 重要なのはオブジェクト生成後、極力すぐにdelegateを設定することです。 最初に示した逆引きObjective-Cサイトのサンプルは、Sampleクラスをalloc/init した直後にdelegateを設定していたと思います。 今回のPageViewは、sampleMethod内で新しいPageViewオブジェクトをalloc/init していますから、同様にその直後にdelegateを設定するのが正しいです。 ただ、delegateで呼び出されるメソッドの処理で注意しなければならないのは、 呼び出し元のオブジェクトに悪影響を与える処理をしないことです。 (呼び出し元に悪影響がある処理って、具体的に何なのかあまりはっきりしない 場合が多いので、これに気付くのは結構難しくて、実際に動かして問題に ぶつかってやっと気付くケースが多いです) 実は今回の質問を受けて気がついたのですが、今回のdelegateメソッドは PageViewのtouchesEndedの延長で呼び出されます。そして、delegateメソッド内で 呼び出し元のPageViewをremoveFromSuperviewで削除してしまいます。 つまり、タッチイベント処理中にそのビューが画面から削除されてしまいます。 これが実際に悪影響となる問題を引き起こさないか、私も似たようなものを 作って検証してみましたが、特に具体的な問題は見つけられませんでした。 (タッチイベント処理の延長にそのビューがなくなるのは、UIKitとしても 想定内の動作なのかもしれません。) でも、もし心配なら、ここはperformSelectorOnMainThreadを使って 一旦メインスレッドに処理を回して、タッチイベントが終了してから 改めてPageViewを削除する方法をとることもできます。 具体的には、sampleMethodの処理を [self performSelectorOnMainThread:@selector(updateImageSet) withObject:nil waitUntilDone:NO]; という一行だけにして、 もともとsampleMethodに書いてあった処理を updateImageSetという新しいメソッドに移せばいいです。

niconico7chan
質問者

お礼

Lchan0211bさん、何度もご丁寧に教えて頂きまして、本当にありがとうございます!(涙) お陰さまで、delegateの使い方も少しずつわかるようになってきました。 教えて頂きましたperformSelectorOnMailメソッドのコードもいれて、サクサク動くようになりました。 お時間をとって頂き、検証までして頂き、本当に一言では言い尽くせないほど感謝しております。 今回、独学でプログラミングをやりはじめて、全くわからないなか孤独な毎日でしたが、 Lchan0211bさんのお陰で、最初の質問時の画面遷移からどれだけ助けて頂いたかと思うくらいです。 もっと勉強して精進するように致します。 本当、重ね重ねありがとうございました。

その他の回答 (7)

回答No.7

「画像を切り替える」というのは、元の画像(view)を一旦削除してから 新しいviewを追加するということです。 削除にはremoveFromSuperviewを使います。 ネットにいい例がなかったので、もうコーディングを書いてしまいますが、 ----------------------------------------------------------- // self.view内のviewを全て削除 for (ScrollView *scrollView in self.view.subviews) { for (PageView *page in scrollView.subviews) { // PageView削除 [page removeFromSuperview]; } // ScrollView削除 [scrollView removeFromSuperview]; } ----------------------------------------------------------- をsampleMethodの先頭に書けばself.view内のviewが一旦全て削除 されますので、その後、従来通りの方法でaddSubviewすればよいと 思います。 これにより、UIScrollviewの*scrollViewとPageViewの*pageを @interfaceで宣言する必要はなく、従来通りメソッド内の ローカル変数宣言でいいと思います。 あと、 > page=[[PageView alloc] initWithFrame:self.view.bounds]; > page.delegate = self; > [page test]; の3行も意味がわかりませんでした。 不要だと思います。

niconico7chan
質問者

お礼

Lchan0211bさん、本当にいつもありがとうございます。 お陰さまで、教えて頂いたコードと、delegateをsampleMetodメソッドの中に書いたらできるようになりました。 ただ一点だけ、どうしても理解できないところがありまして、お伺いさせて頂けたらと思いますが、 今回、delegateを、sampleMethodメソッドの中のpageのところの下に書いたのですが(前回教えて頂いたのをヒントに)、delegateのサンプルで教えて頂いた例のようにdelegateをsampleMethodメソッドの外でつなげてなくても大丈夫でしょうか? もしかしたら、これも、ViewDIdLoadと同じく、うまくいっているようにみえて実は駄目なコードの書き方かと思いまして。。 何度も、素人な質問をして申し訳ございませんが、良かったらまたご指導頂けたら幸いです。 - (void)viewDidLoad { [self sampleMethod]; } - (void)sampleMethod { NSLog(@"sampleMethodが呼ばれた");   for (UIScrollView *scrollView in self.view.subviews) { for (PageView *page in scrollView.subviews) { [page removeFromSuperview]; } [scrollView removeFromSuperview]; } UIScrollView *scrollView = [[UIScrollView alloc] init]; scrollView.frame = self.view.bounds; scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 3, self.view.frame.size.height); scrollView.pagingEnabled = YES; [self.view addSubview:scrollView]; AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; NSLog(@"secondviewdeha%d",currentpage); for (int i=1;i<4;i++) { PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; //前回教えて頂いたのをヒントに、メソッドでもここのところにdelegateをもってきています。 page.delegate=self; [page setImage:[NSString stringWithFormat:@"%d.%d",currentpage,i]]; NSLog(@"secondviewde2ha%d",currentpage); page.frame = CGRectMake( self.view.frame.size.width * (i-1), 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; } }

回答No.6

> 今回のように、最初からViewController.mにある-(void)ViewDidLoadメソッドをデリゲードで使っても支障はないのでしょうか? まずいと思います。 基本的に、viewDidLoadはViewControllerが初めて画面に読み込まれる時に 一度だけ実行されるメソッドであり、その前提で作られるものです。 今回の質問の最初にviewDidLoadメソッドの内容が書かれていますので、 それを元に具体的な問題点を指摘をすると、 1.[super viewDidLoad];の部分 本来のロード契機でないタイミングで[super viewDidLoad]の呼び出しを すると、なにか悪影響があるかもしれません。 2.[self.view addSubview:scrollView];の部分 ベースのviewにscrollViewをaddSubviewしていますが、初回に作った scrollViewが削除されないまま、その上にaddSubviewすることになります。 つまり、今の状況は新しい画像に切り替えているのではなく、元の 画像を残したまま、その上に新しい画像を置いています。 何度もフリック操作すると、画像を切り替えているつもりが、画像をどんどん 上に重ねて行くだけになっていて、やがてメモリ不足になると思います。 やはり、画像切り替え用のメソッドを別に作って、それをdelegateで呼び出し すべきと思います。それができたら、viewDidLoad内で最初に画像を生成する 処理をその画像切り替えメソッドの呼び出しに替えてもよいと思います。

niconico7chan
質問者

お礼

いつも本当に助けて頂きましてありがとうございます。 ご指摘頂きましたように、フリックしてからスクロールした際に、スクロールの端のほうから下の画面がかすかにみえてました。。できた嬉しさから見落としてました。 >画像切り替え用のメソッドを別に作って、それをdelegateで呼び出し すべきと思います。それができたら、viewDidLoad内で最初に画像を生成する 処理をその画像切り替えメソッドの呼び出しに替えてもよいと思います。 ご指導頂きましたことを旨に、 とりあえず、一回目の画面のときと、フリック時の画面のときに共通で使えるようにUiscrollviewの*scrollviewと、PageViewの*pageを宣言してから、 スクロールとその上に画像を乗せるメソッドを別に作り、viewdidLoadのところで、使うようにしたのですが、 一度目の画面はでるのですが、フリック時のデリゲートの書き方がまた間違っているのか、なかなか、画面の切り替えという動きになりません。(重ねるのはでてきます) いつも大変お時間をとっていただきまして本当に恐縮しますが、またご指導頂けましたら幸いです。 以下、コードです。 @interface ViewController () //前回まで、メソッドの中に書いていた二つをここで宣言しました。 { UIScrollView *scrollView; PageView *page; } - (void)viewDidLoad { [super viewDidLoad]; //ここで下に書いてあるsampleMethodメソッドを使いました。これは表示されました。 [self sampleMethod]; //この下の書き方を色々としてみたのですが、重ねるのはできても、切り替わるというデリゲートにはならない状態です。 page=[[PageView alloc] initWithFrame:self.view.bounds]; page.delegate = self; [page test]; } //以前はviewdidLoad の中に書いていたのをメソッドにしました。 - (void)sampleMethod { NSLog(@"sampleMethodが呼ばれた"); scrollView = [[UIScrollView alloc] init]; scrollView.frame = self.view.bounds; scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 3, self.view.frame.size.height); scrollView.pagingEnabled = YES; [self.view addSubview:scrollView]; AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; NSLog(@"%d",currentpage); for (int i=1;i<4;i++) { page = [[PageView alloc] initWithFrame:self.view.bounds]; [page setImage:[NSString stringWithFormat:@"%d.%d",currentpage,i]]; page.frame = CGRectMake( self.view.frame.size.width * (i-1), 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; }} 重ね重ね、本当にいつもありがとうございます。

回答No.5

No.1です。 > [PageView sampleMethod]: unrecognized selector このメッセージから、やはりPageViewクラスのsampleMethodを 呼び出そうとして失敗していますよね。 delegateプロパティにちゃんとVCを設定していますか? (delegateプロパティを設定しているところと 参照しているところで何が入っているかデバッガで 確認してください) 特に気になるのは以下の2点です。 1.VCクラスのviewDidLoad内の PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; の直後(forループ内)に page.delegate = self; と書いて、delegateプロパティにちゃんとVCを設定していますか? 2.余計なところでdelegateプロパティを設定していませんか? PageViewクラスの全体構造について情報をもらってないので、 以下ほとんど推測ですが、おそらくPageViewクラスは UIScrollViewのサブクラスになっていて、画像の拡大縮小処理 のためにUIScrollViewのdelegateメソッドである viewForZoomingInScrollViewをPageViewクラスの中に書いていて、 それを呼び出すためにPageViewクラスのviewDidLoad内に self.delegate = self; とか書いているんじゃないかなと思います。 もしそうだっら、それを削除して、 viewForZoomingInScrollViewメソッドはVCに書いてください。 もしまだ解決できなくて次に質問することがあったら、 PageViewクラスの全体構造をきちんと教えてください。 特に ・PageViewクラスの基本クラスは何か?(@interface行の記載内容を教えてください) ・viewForZoomingInScrollViewはどこでどのように処理しているか? を教えてください。

niconico7chan
質問者

お礼

Lchan0211bさん、本当に、本当にいつもありがとうございます(涙) お陰さまで、VCのメソッドをPVでデリゲードできるようになりました! ご指摘頂いた2点が、そのまま当てはまりました。 本当に感謝しております。 そこで、今回の質問時の最初に教えて頂いた >そのフリック検出をViewController(VC)にでも伝えて、VCから各PageViewに新しいイメージをsetImageするか あるいは新しいPageViewに入れ替えるかすればよいだけ に取り組んだのですが、 その際に、VCに定義してある-(void)ViewDidLoadメソッドをそのままPageViewのフリックのところでデリゲードして使い、 (その際に、VCとPVの共有で使えるようにAppDelegateで宣言したプロパティのvalueを使いフリック時に数字を変え、ページ数に当てはめる) 今回の目的でもある上下のフリック操作でVCのスクロールの上にのっている画像が変わるようになったのですが、 今回のように、最初からViewController.mにある-(void)ViewDidLoadメソッドをデリゲードで使っても支障はないのでしょうか? うまくいくようになったのですが、本当に大丈夫なのかと思いまして。。 素人すぎる質問で恐縮しますが、もし宜しければご指導頂けたら幸いです。 具体的には、フリックの中をこのようにしてみました。 if (distanceHorizontal > distanceVertical) { if (pointEnded.x > _pointBegan.x) { // message = @"右フリック"; } else { // message = @"左フリック"; } } else { if (pointEnded.y > _pointBegan.y){ AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; currentpage=currentpage+1; NSLog(@"pageviewdeha%d",currentpage); appdelegate.Value=currentpage; [self.delegate sampleMethod]; //予め、sampleMethodと同じく定義しておき、ここでViewControllerのViewdidLoadをデリゲードしてみました。 [self.delegate viewDidLoad]; } else { AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; currentpage=currentpage-1; NSLog(@"pageviewdeha%d",currentpage); appdelegate.Value=currentpage; [self.delegate sampleMethod]; [self.delegate viewDidLoad]; }

回答No.4

No.1です。 > これをPageView(PV)でのフリック操作のときのメソッドで行う場合は、PVにあるフリックの > メソッドのところで、デリゲード先のVC内に書いてあるメソッドを呼ぶようにするという > 考え方で宜しいのでしょうか? そうですよ。 No.1補足に書かれているソースなら NSLog(@"上フリックのpageviewでは%d",currentpage); や NSLog(@"下フリックのpageviewでは%d",currentpage); のところに、 [self.delegate sampleMethod]; と書けばフリック検出時にVCのsampleMethodを呼び出せるはずです。 それで呼び出せないんだったら、どういう動作になるのか (呼び出しが無視されているように見えるのか、 それとも呼び出し先がないというエラーになっているのか) コンソールにメッセージが出ているなら、そのメッセージも 含めて説明すれば、なにかアドバイスできるかもしれません。

niconico7chan
質問者

お礼

いつもお時間を割いて頂きまして、本当にありがとうございます。 教えて頂きました [self.delegate sampleMethod]; をフリックメソッドのところに書きますと、build suceededと出てきまして、フリックをしたときにエラーとなって以下のようにでてきます。 [4641:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PageView sampleMethod]: unrecognized selector sent to instance 0x8c078d0' *** First throw call stack: ( 0 CoreFoundation 0x017375e4 __exceptionPreprocess + 180 1 libobjc.A.dylib 0x014ba8b6 objc_exception_throw + 44 2 CoreFoundation 0x017d4903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275 3 CoreFoundation 0x0172790b ___forwarding___ + 1019 4 CoreFoundation 0x017274ee _CF_forwarding_prep_0 + 14 5 test94.9.5.1 0x00004096 -[PageView touchesEnded:withEvent:] + 790 6 UIKit 0x0026c0cd -[UIWindow _sendTouchesForEvent:] + 852 7 UIKit 0x0026cd34 -[UIWindow sendEvent:] + 1232 8 UIKit 0x00240a36 -[UIApplication sendEvent:] + 242 9 UIKit 0x0022ad9f _UIApplicationHandleEventQueue + 11421 10 CoreFoundation 0x016c08af __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 11 CoreFoundation 0x016c023b __CFRunLoopDoSources0 + 235 12 CoreFoundation 0x016dd30e __CFRunLoopRun + 910 13 CoreFoundation 0x016dcb33 CFRunLoopRunSpecific + 467 14 CoreFoundation 0x016dc94b CFRunLoopRunInMode + 123 15 GraphicsServices 0x036889d7 GSEventRunModal + 192 16 GraphicsServices 0x036887fe GSEventRun + 104 17 UIKit 0x0022d94b UIApplicationMain + 1225 18 test94.9.5.1 0x0000481d main + 141 19 libdyld.dylib 0x01d73725 start + 0 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb) 一応、ViewController(VC)に書いてあるsampleMethodを、PageView(PV)にも書いたらエラーなく動きましたが、NSLogの内容は、VCでの内容を引き継いでいるわけではなく、PV内のsampleMethodに別に書いた内容がでてきました。 いつもお手数かけて大変恐縮しています。また、ご指導頂けたら幸いです。

回答No.3

追伸です。 もし、PageViewがUIScrollViewのサブクラスとして 実装されているなら、UIScrollViewで既にdelegateが 定義されていますので、そのdelegateを引き継いで 拡張する形で実装する必要があります。 具体的には、delegateの定義を @protocol PageViewDelegate <UIScrollViewDelegate> のようにすればよいです。

niconico7chan
質問者

お礼

いつも本当にありがとうございます。 早速、教えて頂いたdelegateと、protocolの書き方、逆引きObjective-Cを参考にさせて頂いて、SampleClassをPVに書いてViewControllerで、NSLogに"sampleMethodが呼ばれた"をだせるようになりました。 これをPageView(PV)でのフリック操作のときのメソッドで行う場合は、PVにあるフリックのメソッドのところで、デリゲード先のVC内に書いてあるメソッドを呼ぶようにするという考え方で宜しいのでしょうか? まだ、VC内にフリック時の情報が伝えられずでして。。 お手数かけていつも申し訳ありませんが、また教えて頂けたら幸いです。

回答No.2

No.1です。 > 今回ご指摘して頂いてる、フリック検出をViewContollerに伝えるところがわからなくています。 あぁ、なるほど。 ViewControllerに伝えたいのに、どうやってViewControllerの居場所を得たらいいのか わからないということですね。 やり方はいろいろありますが、delegateを実装するのが一般的だと思います。 要するに通知先となるViewControllerをあらかじめPageViewに登録しておけば いいということなのですが、あまり深く考えずにそれをやると循環参照といった罠に 陥りやすいので、delegateというお作法に従って実装すればうまくいくということです。 http://www.objectivec-iphone.com/introduction/delegate/delegate.html が参考になると思います。 この説明のSampleクラスがPageViewクラスに相当していると思えばいいです。

回答No.1

> このPVの中で行う上下のフリックの操作によって、VCにあるスクロールの上に乗っている画像を変えたいのですが、色々と試したのですがその方法が一向にわかりません。 http://okwave.jp/qa/q8369983.html の質問の続きなのだと思いますが、 前回の質問で、上下フリックを検出して NSLogを出力するところまではできたのだろう と思います。 後は、そのフリック検出をViewController(VC)にでも伝えて、 VCから各PageViewに新しいイメージをsetImageするか あるいは新しいPageViewに入れ替えるかすればよいだけだと 思うのですが、何がわからないんでしょうか? 新しいイメージをsetImageしたはずなのに画像が変わらなくて 原因がわからず困っているのだったら、イメージを更新する処理の ソースを開示してアドバイスを求めた方がよいと思います。

niconico7chan
質問者

お礼

Lchan0211bさん、本当にいつもありがとうございます。 お陰さまで、PageViewにおいての上下フリックのNSLogの出力はできるようになりました。 今回ご指摘して頂いてる、フリック検出をViewContollerに伝えるところがわからなくています。 PageView(PV)のスーソコードのsetImageと上下フリックに関しては以下のように書いています。 いつも助けて頂きまして、本当に感謝しています。 またご教授頂けたら幸いです。 -(void)setImage:(NSString *)image{ NSString *path=[[NSBundle mainBundle] pathForResource:image ofType:@"png"]; imageView.image=[UIImage imageWithContentsOfFile:path]; [self adjustScrollView:NO]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch*touch=[touches anyObject]; _timestampBegan=event.timestamp; _pointBegan=[touch locationInView:self]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch*touch=[touches anyObject]; if ([touch tapCount]>1) { [self adjustScrollView:YES]; } static const NSTimeInterval kFlickJudgeTimeInterval = 0.3; static const NSInteger kFlickMinimumDistance = 10; UITouch *touchEnded = [touches anyObject]; CGPoint pointEnded = [touchEnded locationInView:self]; NSInteger distanceHorizontal = ABS(pointEnded.x - _pointBegan.x); NSInteger distanceVertical = ABS(pointEnded.y - _pointBegan.y); if (kFlickMinimumDistance > distanceHorizontal && kFlickMinimumDistance > distanceVertical) { return; } NSTimeInterval timeBeganToEnded = event.timestamp - _timestampBegan; if (kFlickJudgeTimeInterval > timeBeganToEnded) { NSString*message; //上下にフリックしたとき if (distanceHorizontal > distanceVertical) { if (pointEnded.y > _pointBegan.y) { //ここで、上にフリックでAppDelegateで作ったプロパティのValueの値を+1させて変更させることによってVCでの画像の変更を(2.1.png⇨3.1.png)のように変更させたいと思っています。 AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; currentpage=currentpage+1; NSLog(@"上フリックのpageviewでは%d",currentpage); } else { AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; appdelegate.Value=currentpage-1;           NSLog(@"下フリックのpageviewでは%d",currentpage);

niconico7chan
質問者

補足

本当にいつもありがとうございます。 お陰さまで、PageViewにおいての上下フリックのNSLogの出力はできるようになりました。 今回ご指摘して頂いてる、フリック検出をViewContollerに伝えるところがわからなくています。 PageView(PV)のスーソコードのsetImageと上下フリックに関しては以下のように書いています。 いつも助けて頂きまして、本当に感謝しています。 またご教授頂けたら幸いです。 -(void)setImage:(NSString *)image{ NSString *path=[[NSBundle mainBundle] pathForResource:image ofType:@"png"]; imageView.image=[UIImage imageWithContentsOfFile:path]; [self adjustScrollView:NO]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch*touch=[touches anyObject]; _timestampBegan=event.timestamp; _pointBegan=[touch locationInView:self]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch*touch=[touches anyObject]; if ([touch tapCount]>1) { [self adjustScrollView:YES]; } static const NSTimeInterval kFlickJudgeTimeInterval = 0.3; static const NSInteger kFlickMinimumDistance = 10; UITouch *touchEnded = [touches anyObject]; CGPoint pointEnded = [touchEnded locationInView:self]; NSInteger distanceHorizontal = ABS(pointEnded.x - _pointBegan.x); NSInteger distanceVertical = ABS(pointEnded.y - _pointBegan.y); if (kFlickMinimumDistance > distanceHorizontal && kFlickMinimumDistance > distanceVertical) { return; } NSTimeInterval timeBeganToEnded = event.timestamp - _timestampBegan; if (kFlickJudgeTimeInterval > timeBeganToEnded) { NSString*message; //上下にフリックしたとき if (distanceHorizontal > distanceVertical) { if (pointEnded.y > _pointBegan.y) { //ここで、上にフリックでAppDelegateで作ったプロパティのValueの値を+1させて変更させることによってVCでの画像の変更を(2.1.png⇨3.1.png)のように変更させたいと思っています。 AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; currentpage=currentpage+1; NSLog(@"上フリックのpageviewでは%d",currentpage); } else { AppDelegate *appdelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate]; currentpage=appdelegate.Value; appdelegate.Value=currentpage-1;           NSLog(@"下フリックのpageviewでは%d",currentpage);

関連するQ&A

  • 一つの画面でスクロールとフリックをする方法について

    今、画像を左右に数枚スクロールさせれて、かつ、その画像を上や下にフリックすると各々、上や下に他の画像がでてきて、さらに拡大縮小もできるようなコードを書いているのですが、 ViewContorller(以下、VC)にスクロールと上下のフリックのメソッドを書き、 もう一つのPageView(UIScrollVIewクラスを親にもつ。以下、PV)に画像が拡大縮小するようなメソッドをdelegateを使って書いています。 その際に、VCのほうに書いているスクロールのメソッドがフリックのメソッドを邪魔してうまくフリックのtouchメソッドを呼んでくれません。スクロールメソッドを消すと、フリックが使えますが、そうでないときは、スクロールと拡大縮小だけができます。 調べたところ、        scrollView.canCancelContentTouches=NO;        scrollView.delaysContentTouches=NO; を使うと良いというのでやってみたのですが、うまくいきません。 もし、お分かりになる方がいらっしゃいましたら、大変お手数かけますが、ご教授ください。 以下が VC.mです。 xcodeは5.0バージョンです。 - (void)viewDidLoad { [super viewDidLoad]; UIScrollView *scrollView = [[UIScrollView alloc] init]; //ここに先ほどのを入れてみました。 scrollView.canCancelContentTouches=NO; scrollView.delaysContentTouches=NO; scrollView.frame = self.view.bounds; scrollView.contentSize = CGSizeMake(self.view.frame.size.width * kPageNum, self.view.frame.size.height); scrollView.pagingEnabled = YES; [self.view addSubview:scrollView]; for (int i=0;i<kPageNum;i++) { PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; //setImageメソッドはPVのほうで定義しています。 [page setImage:[NSString stringWithFormat:@"%d.png", i]]; page.frame = CGRectMake( self.view.frame.size.width * i, 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; _timestampBegan = event.timestamp; _pointBegan = [touch locationInView:self.view]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { static const NSTimeInterval kFlickJudgeTimeInterval = 0.3; static const NSInteger kFlickMinimumDistance = 10; UITouch *touchEnded = [touches anyObject]; CGPoint pointEnded = [touchEnded locationInView:self.view]; NSInteger distanceHorizontal = ABS(pointEnded.x - _pointBegan.x); NSInteger distanceVertical = ABS(pointEnded.y - _pointBegan.y); if (kFlickMinimumDistance > distanceHorizontal && kFlickMinimumDistance > distanceVertical) { return; } NSTimeInterval timeBeganToEnded = event.timestamp - _timestampBegan; if (kFlickJudgeTimeInterval > timeBeganToEnded) { if (distanceHorizontal > distanceVertical) { if(pointEnded.x>_pointBegan.x) {} //上下のフリックだけなのでここには書いていません。 else{}} else{ if (pointEnded.y > _pointBegan.y) { NSLog(@"あ");//NSLogで反応の仕方をみてます。 } else { NSLog(@"い"); } 初心者のため色々と質問の内容から間違いがあるかもしれませんが、宜しくお願い申し上げます。

  • スクロールの上でラベルをドラッグする方法について

    現在、左右スクロールと上下フリックができるViewをタップすることでラベルがでてきて、そのラベルをドラッグできるようなコードを作っています。 具体的には、ViewController のViewの上に、画像を左右にScrollできるView(ScrollView)をのせ、その上に、それらの画像を上下にフリックすると別の画像がでてくるようなView(PageView、親クラスがUISrollView)を作成しています。 そこで、上下のフリック、スクロール、タップでラベルがでてくるのはできるようになったのですが、ラベルを認識してドラッグができる(UIPanGestureRecognizer)というのができません。 もし、おわかりになられる方がいらっしゃいましたら、お手数をおかけしますがご教授頂けたら幸いです。 以下、コードです。 xcodeは5.0です。 これらはViewContorllerの中に書いてあります。 //ScrollViewの上にPageViewクラスで作ったpageを乗せてスクロールしています。pageには画像をいれています。 for (int i=1;i<4;i++) { PageView *page = [[PageView alloc] initWithFrame:self.view.bounds]; page.delegate=self; [page setImage:[NSString stringWithFormat:@"%d",i]]; page.frame = CGRectMake( self.view.frame.size.width * (i-1), 0, self.view.frame.size.width, self.view.frame.size.height ); [scrollView addSubview:page]; //pageにタップしてproductLabelがでてくるようにしています。 [page addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrlTapREcotTap:)]]; NSLog(@"tap"); //ここでラベルのproductLabelだけに触れてドラッグできるようにしたいのですが、ドラッグができません。 UIPanGestureRecognizer *pan =[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)]; [productLabel addGestureRecognizer:pan]; NSLog(@"drag"); }} //ラベルをタップにより表示したり、非表示にしたりしています。 - (void)scrlTapREcotTap:(UITapGestureRecognizer *)gestureRecognizer { if(isTappFirstTime) { //put code of hide [UIView animateWithDuration:1 animations:^{ productLabel.alpha = 0; } completion: ^(BOOL finished) { productLabel.hidden = YES; }]; isTappFirstTime = NO; NSLog(@"非表示"); } else { // put code of show [UIView animateWithDuration:1 animations:^{ productLabel = [[UILabel alloc] init]; //UILabel *label = [[UILabel alloc] init]; productLabel.frame = CGRectMake(10, 10, 100, 50); productLabel.backgroundColor = [UIColor yellowColor]; productLabel.textColor = [UIColor blueColor]; productLabel.font = [UIFont fontWithName:@"AppleGothic" size:12]; productLabel.textAlignment = UITextAlignmentCenter; productLabel.text = @"hoge"; [scrollView addSubview:productLabel]; (NSLog(@"表示")); productLabel.alpha = 1; } completion: ^(BOOL finished) { productLabel.hidden = NO; }]; isTappFirstTime = YES; } } //productLabelだけがドラッグできるようにしています。 - (void) handlePanGesture:(UIPanGestureRecognizer*) sender { CGPoint location = [sender translationInView:productLabel]; CGPoint movedPoint = CGPointMake(productLabel.center.x + location.x, productLabel.center.y + location.y); productLabel.center = movedPoint; NSLog(@"dragmethod"); [sender setTranslation:CGPointZero inView:productLabel]; } お手数おかけしますが、宜しくお願いします。

  • iPhone: PageControlについて

    現在、iPhoneのホーム画面風アプリを制作しています。 PageControlとScrollViewを使用して、ページの移動はできるようになりましたが、 以下の問題が発生して困っています。 [問題] ・PageControlで2ページの画面を作っていますが、1ページ目に乗っている「UIButton」は正しく反応するのですが、2ページ目(スライドして表示)の上に乗っている「UIButton」がどうしても反応しません。。。 何か設定が必要なのでしょうか? ***PageControl & ScrollViewのコーディング(一部抜粋)*** (UIButtonの記述等は省略しています) [XXXViewController.h] @interface XXXViewController : UIViewController <UIScrollViewDelegate> { // 画面スクロール用 UIScrollView *scrollView; // PageControl [画面下方の白丸] UIView *pageView; UIPageControl *pageControl; @property (nonatomic, retain) IBOutlet UIScrollView *scrollView; @property (nonatomic, retain) IBOutlet UIView *pageView; @property (nonatomic, retain) IBOutlet UIPageControl *pageControl; [XXXViewController.m] - (void)viewDidLoad { [super viewDidLoad]; scrollView.pagingEnabled = YES; scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * 2, scrollView.frame.size.height); scrollView.showsHorizontalScrollIndicator = NO; scrollView.showsVerticalScrollIndicator = NO; scrollView.delegate = self; pageControl.numberOfPages = 2; pageControl.currentPage = 0; pageView.backgroundColor = UIColor.clearColor; [scrollView addSubview:pageView]; } - (IBAction)changePage:(id)sender { CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * pageControl.currentPage; frame.origin.y = 0; [scrollView scrollRectToVisible:frame animated:YES]; } - (void)scrollViewDidScroll:(UIScrollView *)sender { CGFloat pageWidth = scrollView.frame.size.width; pageControl.currentPage = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; }

    • ベストアンサー
    • Mac
  • Objective-c  画面遷移について

    毎回、初歩的な質問内容で申し訳ありませんが、困っているので教えて下さい。 「FirstViewController」はUIScrollViewでスクロールさせている画面で、タッチイベントを取得する為に UIScrollView のサブクラスを作っています。 そこでタッチすると、「SecondViewController」へ固定の画面で遷移するようにしたいのですが、「SecondViewController」の画面もそのままスクロール画面で表示されてしまいます。。。 「SecondViewController」をスクロールさせず、位置x=0 y=0で表示させるにはどうしたら良いのでしょうか? 詳しく教えて頂けると、大変助かります。。 ↓FirstViewController.h↓ @interface FirstViewController : UIViewController{   MyScrollview *controller; IBOutlet UIScrollView *scrollView; } ↓FirstViewController.m↓ - (void)viewDidLoad { controller = [[ MyScrollview alloc] initWithFrame:CGRectMake(0, 0, 1100, 1100)]; self.view = controller; [super viewDidLoad]; [super loadView]; scrollView.contentSize = controller.frame.size; [scrollView addSubview:controller]; } ↓MyScrollview .h↓ @interface MyScrollview : UIView<UIScrollViewDelegate>{ } @end ↓MyScrollview .m↓ -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{ SecondViewController *svc; svc = [[SecondViewController alloc] init]; [self addSubview:[svc view]]; }

  • FlashMXで横にスクロールする画像の速度について

    いつもお世話になっております。 Windows98SEでFlashMXを使い始めました。(CPU900Mhz、メモリ384程度だったと思います…) 手始めに今持っている画像で横にスクロールをさせる実験を行っているのですが、スクロールはするものの、動きがぎこちなく思えます。 ネット上で見かけるFlash広告やムービーは滑らかに横スクロールしている気がするので、おそらく自分の設定が悪いと思うのですが…綺麗にスクロールさせるためには、何か手段が別にあるのでしょうか。 お分かりの方、回答をお願いいたします。 なお、次のような形でファイルを作成しています。 サイズ:640*480 フレームレート:12fps 画像:写真画像のJPEG(1024*480)をライブラリに読み込んだもの1枚 レイヤーは1つで、1フレーム目にX=0,Y=0で画像を配置し、モーショントゥイーンを作成、15フレーム目をX=-150,Y=0にしてスクロールさせています。 ひょっとして、Flashでスクロールさせるには画像が大きすぎるのでしょうか。

  • アプリ起動画面を画像からxibに変更する

    私の質問を閲覧していただきありがとうございます。 早速以下にこちらの環境を書いていきたいと思います。不足している情報がありましたら適宜指摘してくださると幸いです。 Xcode5 simulator (iPhone Retina 4inch 64bit) iOS7 では早速本題に入っていきたいと思います。 本質問でみなさんにお尋ねしたい事は「スプラッシュ画面を動的に変更する手法」です。 本来スプラッシュ画面で表示されるのは画像になると思うのですが、その画像を、私が任意に変更できるxibへと変更したいのです。 ※変更の都度png作り直せばいいという類の回答は無しでお願い致します。 私が今回想定しているxibはデフォルトのself.view上に self.viewと同じサイズのimageViewを貼付け、 imageViewの上にUILabelを一つ貼付ける という構成になるのですが、このimageViewの背景画像とLabelのテキストをアプリ起動時ににappDelegateのdidFinishLaunchingWithOptions等で動的に変更し、変更したxibをスプラッシュ画面に表示したいです。 以上になります。 お時間有りましたらご助言いただけますと有り難いです。 追記 明けましておめでとうございます。 今年もどうぞ宜しくお願いいたします

  • Dreamweaverでoverflow画像の位置

    DreamweacerCS3です。 表示フレーム幅(1000px)よりも長い画像(2050px)をcssにてoverflow: auto に設定して、はみ出ることなく収めています。 水平スクロールバーをスライドすれば画像を全幅にわたって動かすことができています。 ページを開いたときは常にこの画像はスクロールバーが左端に寄った状態になっていますが、常時見るのは反対の右側なのでスクロールバーを右端に初期設定したいのですが方法がわかりません。ご伝授ください。  cssのプロパティを見ると100くらいのパラメータがあり、それらしきもの(float)を変えてみるのですが思うようになりません。 現在設定しているのはビューウィンドウのサイズ:(1000px, 410px)、overflow:autoのみです。

  • xcode 画像をランダムに並べ順番に押す

    初めてですが質問よろしくお願いします。 iphone開発初心者です。 数字の画像をランダムに5×5に並べ、1から25まで順番に押していく、 というアプリを制作中なのですが行き詰まっています。 現在下記コードのようになっています。 画像を表示まではできたのですが、下記3つ、できればソースコードをお聞きしたいです。 (1)画像25個をランダムに表示する記述がわかりません (今はとりあえずで同じ画像を1つ入れてます。(img1~img25のimg1を代入中)) (2)順番に押していく処理 (3)画像を押された時に音を出したい - (IBAction)image:(id)sender { AudioServicesPlaySystemSound(sound_1); } の部分をうまく入れこめばいいのかと思っていますが、その入れこみ方もわかりません。 AudioToolboxは追加済みです。 どなたかご教授よろしくお願いします。 #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSString *path = [[NSBundle mainBundle] pathForResource:@"btn_1" ofType:@"mp3"]; NSURL *url = [NSURL fileURLWithPath:path]; AudioServicesCreateSystemSoundID((CFURLRef)CFBridgingRetain(url), &sound_1); int yo = 5; for(int i = 0;i<yo; i++){ UIImageView *imageView = [UIImageView new]; imageView.frame = CGRectMake(15+60*i, 100, 60, 60); imageView.image = [UIImage imageNamed:@"img1.png"]; [self.view addSubview:imageView]; } int f = 25; for(int i = 0;i<f; i++){ UIImageView *imageView = [UIImageView new]; imageView.frame = CGRectMake(15+60*(i%5), 100+60*(i/5), 60, 60); imageView.image = [UIImage imageNamed:@"img1.png"]; [self.view addSubview:imageView]; } int rand = arc4random()%f; for(int i = 0; i<f; i++){ if(i == rand){ UIButton*button = [UIButton new]; button.frame = CGRectMake(15+60*(i%5), 100+60*(i/5), 60, 60); [button setImage:[UIImage imageNamed:@"img1.png"] forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchDown]; [self.view addSubview:button]; }else{ UIImageView *imageView = [UIImageView new]; imageView.frame = CGRectMake(15+60*(i%5), 100+60*(i/5), 60, 60); imageView.image = [UIImage imageNamed:@"img1.png"]; [self.view addSubview:imageView]; } } } - (IBAction)image:(id)sender { AudioServicesPlaySystemSound(sound_1); } -(void)buttonTapped{ } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end

  • FLASHでの画像無限スクロール基準点

    みなさん、ハジメマシテ。 現在マウスの位置によって画像が無限にスクロールするものを作っているのですが、ウィンドウサイズを変更しても基準点をセンターに持っていきたいのですが、サイズを変えた時の基準点が、最初に表示した時の基準点から変わりません。。 ソースは下記の通りです。 //初期化 function init() { w = content._width; x0 = Stage.width/2; cnt = Math.ceil(Stage.width/w)+4; scrollWidth = w*cnt; //ステージ幅に合わせてムービークリップを複製する for (i=1; i<=cnt; i++) { x = w*(i-2); y = content._y; props = {_x:x, _y:y}; //contentを複製する newMC = content.duplicateMovieClip("scrollMC"+i, i, props); //新しいムービークリップにイベントメソッドを設定する newMC.onEnterFrame = scrollxMC; } //複製元のムービークリップを隠す content._visible = false; } //ステージを横スクロールするメソッド function scrollxMC() { with (this) { if (_x<(-w)) { _x += scrollWidth; } else if (_x>(Stage.width+w)) { _x -= scrollWidth; } _x -= (_root._xmouse-x0)/10; } } //初期化の実行 init(); x0がここで言う基準点だと思うのですが、これをウィンドウサイズが変わってもセンターにくるようにするにはどうすればよろしいでしょうか?? お手数ですが、お力添えよろしくお願い致します。

  • Objective-c 画面遷移について

    やはり、画面遷移ではまっていますので、助けて下さい。 navigationControllerで作成しています。 (内容は以前に質問させて頂いているものとほぼ同じですが、) 「FirstViewController」はUIScrollViewでスクロールさせている画面で、タッチイベントを取得する為に UIScrollView のサブクラスを作っています。 そこでタッチすると、「SecondViewController」へ遷移するようにしたいのですが、下記のように単純にpushViewControllerを使ってサブクラスへ書くと、「Property 'navigationContoroller' not found on object of type 'MyScrollview'」というエラーが表示されてしまいます。 このクラスへ書いたらいけないというのは、なんとなく分かりますが、かと言って何からどう手をつければ良いのか分かりません…… 問題なく画面遷移させるにはどうしたらよいのでしょうか。 詳しく教えて頂けると、大変助かります。。 ↓FirstViewController.h↓ @interface FirstViewController : UIViewController{   MyScrollview *controller; IBOutlet UIScrollView *scrollView; } ↓FirstViewController.m↓ - (void)viewDidLoad { controller = [[ MyScrollview alloc] initWithFrame:CGRectMake(0, 0, 1100, 1100)]; self.view = controller; [super viewDidLoad]; [super loadView]; scrollView.contentSize = controller.frame.size; [scrollView addSubview:controller]; } ↓MyScrollview .h↓ @interface MyScrollview : UIView<UIScrollViewDelegate>{ } @end ↓MyScrollview .m↓ -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event{ ~省略~ SecondViewController *mvc = [[[SecondViewController alloc] initWithNibName:nil bundle:nil] autorelease]; [self.navigationController pushViewController:mvc animated:YES]; }