• ベストアンサー

iPhone アプリ 通過後処理

iPhone アプリ作成に関してですが UIButtonの画像付きボタンをドラッグさせた際 指定した座標を通過もしくはその座標の点の上にボタンが来たらアクションを実行 ということは可能でしょうか? また、座標ではなく、表示されているUIImageもしくはUIButtonの上を通過したら実行 という処理も可能でしょうか? 作成しているアプリでは、通過する座標は同じなのですが表示されているUIButtonがその前の処理で異なるので 個人的には後者の処理を行いたいです

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

  • ベストアンサー
  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.7

> 私が思い当ったコードは > CGPoint pt = [[touches anyObject] locationInView:self.superview]; > self.center = pt; > で、タッチした際UIImageViewが少し下にずれるようなことがたまにあったので他によい方法はないのか それは、タッチした場所と、Viewのセンター位置の差分を、調節しないと、そういうことになるでしょうね。いい方を変えると、調節すれば、なんの問題もありませんね。いちいち他人にアドバイスを仰ぐようなことではないと思います。 私だったら、どういうコードを書くかということですが、私はUITouchではなく、UIPanGestureRecognizerを使います。 ジェスチャーのStateが「UIGestureRecognizerStateBegan」(画面をタッチして、移動を始めた瞬間)のときに、「setTranslation:inView:」でViewのcenterを登録し、ジェスチャーのState「UIGestureRecognizerStateChanged」(タッチを移動している間」、「translationInView:」で取得されるCGPointに、Viewのcenterをセットしてやると、Viewがぴったり指に追従します。 UITouchを使うケースで、もうすこしアドバイスすることが残っているとしたら、ひとつは「previousLocationInView:」というメソッドを活用することです。 「touchesMoved:withEvent:」メソッドは、タッチを移動しているあいだ、なんども繰り返して呼び出されると、前に説明しましたが、前回呼び出し時のタッチ位置が「previousLocationInView:」で取得できるので、タッチ移動量を計算することが可能になります。 サンプルコード: 記述場所:UIViewControllerのサブクラス targetObj:指で動かすオブジェクト。UIViewのサブクラス。 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; ~ // タッチ開始時の処理 } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if ([touch.view isEqual: targetObj]) { // targetObjをタッチしたのなら CGPoint pt = targetObj.center; CGPoint prevPt = [touch previousLocationInView: self.view]; CGPoint newPt = [touch locationInView: self.view]; float gapX = newPt.x - prevPt.x; // タッチ移動量を計算 float gapY = newPt.y - prevPt.y; targetObj.center = CGPointMake(pt.x + gapX, pt.y + gapY); } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; ~ // タッチ終了時の処理 } タッチイベントを処理するメソッドを、UIViewController(のサブクラス)に記述している点に注目してください。それがもうひとつのアドバイスです。UIViewControllerは、UIResponderを継承しているので、タッチイベントの処理が可能です。 「レスポンダチェーン」(Responder Chain)という言葉を覚えてください。いかにもオブジェクト指向的なメカニズムです。 画面を指でタッチすると、タッチイベントが発生しますが、タッチした場所にあるViewがまずタッチイベントを受け取ります。もしそのViewにタッチイベントの処理が用意されていなかったら、そのViewはイベントをSuperviewに譲り渡します。Superviewにイベント処理が用意されていたら、代わって処理を行いますが、SuperviewはみずからのSuperviewにタッチイベントを譲り渡します。このようにイベントは次々にView間を渡っていき、UIWindowに渡され、最終的にUIApplicationに渡されます。どこでもイベントに対する処理がなければ、けっきょくなにも起きずにイベントは消滅します。このイベント受け渡しの経路をレスポンダチェーンと呼びます。経路にあるUIResponderサブクラスなら、プログラム上つごうのいい場所で、イベント処理を記述することができます。 Viewがコントローラ(UIViewController)を持っている場合、タッチイベントは、Superviewに渡される前に、コントローラに渡されます。サンプルコードはこの受け渡しの規則を利用して、UIViewControllerのサブクラスにタッチイベントの処理を記述しています。 タッチイベントを最初に受け取ったViewは、UITouchのプロパティ「view」で取得することができます。

nosuke5614
質問者

お礼

詳しい説明ありがとうございます 最初の質問から主旨少しズレてしまいすみませんでした それでも最後までつきあっていただき感謝します 次はUIPanGestureRecognizerで作成をしてみようと思います たびたび質問して来ると思いますが機会があればまたよろしくお願いします

その他の回答 (6)

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.6

> これでよろしかったでしょうか? あなたの書いたプログラム全体を把握できないので、その質問には答えられません。しかし、その書き換えであなたの意図どおりの動作になったのなら、正しいと判断していいのではありませんか? いちど、そのプログラムから離れて、1週間ほど忘れてしまうことです。そのあと、そのプログラムを読み返せば、客観的な判断ができるようになるでしょう。人間は本質とその構造として、進歩し成長するようになっている。人間は自分自身を客観的に把握する能力を有する。このふたつのことを信じる価値があります。

nosuke5614
質問者

補足

そうですね。 できればharawoさんが考えたコードをお聞きしたくて よろしかったですか?と尋ねました 私が思い当ったコードは CGPoint pt = [[touches anyObject] locationInView:self.superview]; self.center = pt; で、タッチした際UIImageViewが少し下にずれるようなことがたまにあったので他によい方法はないのか harawoさんならどのように書くかというのが知りたくて捕捉させていただきました

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.5

> このようにしたところ当然UIImageは動きませんがマウスでAのUIButtonの位置まで持っていくと LogにINと表示されました > 原因は下から3行目と4行目の箇所ですがなぜいけないのか > どうすればいいのか、というのが分かりません 「UIImage」は動きませんよ。UIViewのサブクラスではありませんからね。UIImageは、オフスクリーンバッファという考え方をクラス化したものです。プログラムが動くたび、画面を書き換えていると、人間の目にはちらつきに見えて、不快になったり疲れさせたりするので、画面表示データと、プログラムの対象のイメージデータを別にし、ある程度書き換えが完了したら、一気に画面表示データと置き換えるというテクニックで使われます。 あなたがいいたいのは「UIImageView」ですね?かんたんにUIImageを画面表示させるための、UIViewのサブクラスです。UIImageとUIImageViewを、意図して書き分けできずに、混同してしまうのは、UIKitというフレームワークを、理解できていないからにほかならないでしょう。 UIViewサブクラスの位置は「マウス」では動かせませんよね?iOSシミュレータ上では、たしかにマウスで動かしますが、実機では指のタッチで動かしますよね?さきほど「ドラッグ」という言葉の使い方を例にとって、GUIを意識したプログラムをするようアドバイスしたつもりなのですが、こちらの意図を理解していたら、こういう混同もしないのでしょうに。 UIViewの位置情報は、「center」という、読み書きのできる便利なプロパティが用意されているのですから、「uiviewsubclass.frame.origin.x」などと、いちいち記述せずに、centerを使いましょう。 UIViewサブクラスのインスタンスuiviewsubclassの位置を、CGPoint「distance」の分だけ動かすには、こう書きます。 uiviewsubclass.center = CGPointMake(uiviewsubclass.center.x + distance.x, uiviewsubclass.center.y + distance.y); さて、本題の質問に対してですが、取得する座標の基準、メソッド「locationInView:」の引数となるViewは、「self」で正しいんですか?私は違うと思いますが?

nosuke5614
質問者

補足

間違った語句が多くてすみません touchesMoved内を CGPoint pt = [[touches anyObject] locationInView:self.superview]; self.center = pt; このように変えたらUIImageViewを動かすことができした。 これでよろしかったでしょうか?

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.4

> touchesBegan:にコードは書き込みました touchesBegan:withEvent:メソッドは、指を画面にタッチした瞬間に、1回だけ呼ばれます。タッチした指を、画面から離さずに移動する間の処理は、「touchesMoved:withEvent:」メソッドに記述します。ここにNSLog()を書くと、指を動かしている間、連続して繰り返しこのメソッドが呼ばれることがわかります。 タッチイベントのメソッドは、「touchesBegan:withEvent:」「touchesMoved:withEvent:」「touchesEnded:withEvent:」「touchesCancelled:withEvent:」の4つがセットと考え、処理を行ってください。ひとつだけ取り出して処理しても、期待どおりにならないことのほうが多いでしょう。ちなみに、touchesCancelled:withEvent:メソッドは、iPhoneで途中電話がかかってきたなど、外的要因でタッチイベントが中断されたときに呼び出されます。 > if (CGRectContainsPoint(A.frame, pt)){ >  NSLog(@"TEST"); > } > と書き込んでみましたが表示されませんでした 条件に一致しないときも、なにかしら出力しなければ、ちゃんと判断できませんよ。 if (CGRectContainsPoint(A.frame, pt)){  NSLog(@"IN"); } else { NSLog(@"OUT"); }

nosuke5614
質問者

補足

原因が判明しました elseも書き行ったところtouchesMoved内のに問題があることが判明しました(少し長くなりますが) - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { startLocation = [[touches anyObject] locationInView:self]; [[self superview] bringSubviewToFront:self]; } - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { CGPoint pt = [[touches anyObject] locationInView:self]; CGRect frame = [self frame]; if (CGRectContainsPoint(A.frame, pt)){ NSLog(@"IN"); }else{ NSLog(@"OUT");; } // frame.origin.x += pt.x - startLocation.x; // frame.origin.y += pt.y - startLocation.y; [self setFrame:frame]; } このようにしたところ当然UIImageは動きませんがマウスでAのUIButtonの位置まで持っていくと LogにINと表示されました 原因は下から3行目と4行目の箇所ですがなぜいけないのか どうすればいいのか、というのが分かりません できればもう少しアドバイスをいただきたいです

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.3

> ドラッグのclassに > CGPoint pt = [[touches anyObject] locationInView:self]; > CGRect frame = [self frame]; > if (CGRectContainsPoint(A.frame, pt)){ > [処理]; > } > とやってみたのですが処理は実行されませんでした 「なにを」は書かれていても、「どこに」(メソッド)が書かれていないので、なんともコメントのしようがありません。 処理のコードを書いていても、それを呼び出すイベントが発生しなければ、また発生したイベントを、メソッドが受け取らなければ、処理は実行されません。 イベントが発生しているか、あるいは発生したイベントを、メソッドが受け取っているかを調べるには、NSLog()を使った、簡易デバッグが有効でしょう。 そして、冷静に、客観的にプロジェクトを観察すれば、タッチイベントがどのオブジェクト(UIResponderのサブクラス)で受け止められているか、調べるのは容易なはずです。いちど自分のプロジェクトを俯瞰してみてはいかがですか? (まさか、「touchesMoved:withEvent:」メソッドに書いていないなんてことはありませんよね?) ※「ドラッグ」という言葉は、厳密な定義に従えば、マウスボタンを押したままの状態で、マウスを動かす行為を指します。iPhoneのようなタッチパネル式のインターフェイスでは、使うべき用語とはいえません。Appleの用語では、Touch Moveや、Pan(UIPanGestureRecognizer)が使われます。

nosuke5614
質問者

補足

説明が足りませんでしたね (ドラッグの件も気をつけます) touchesBegan:にコードは書き込みました NSLog(@"TEST");とtouchesBegan:の処理内に書き込んだところ表示はされたのでこちらは問題ないのですが if (CGRectContainsPoint(A.frame, pt)){  NSLog(@"TEST"); } と書き込んでみましたが表示されませんでした 発生自体はしているはずなのですがメソッドが受け取ってくれていないのだと思います。 TouchMoveの処理がDragView.hに 通過させたいUIButtonの処理がMainViewController.hに書かれているのでController.h内のIBOutlet UIButtonがしっかり認識されてないのが原因でしょうか?

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.2

> どういったクラス?を使用すればよいのかなどのアドバイスをいただきたいですね 「UIButtonの画像付きボタンをドラッグ」するのに、UITouchクラスか、UIGestureRecognizerクラスを利用していると思いますが、それらどちらかのメソッドで処理するのが、自然な流れではないでしょうか? 参考: bool CGRectContainsPoint ( CGRect rect, CGPoint point ); ある座標(タッチしているポイント)が、ViewなどのCGRectの内側にあるのか、調べるC言語の関数です。これで判別できます。 > (ちなみにプログラムのサンプルを書いてもらうにはおいくらですか?) 公共の掲示板を使って、営利行為をしたら、まずいですよ。冗談でその質問をなさっているのだと思いますが、こちらの言葉も本気で「金をくれ」といっているのではないことを、誤解しないでください。

nosuke5614
質問者

補足

DragView.mを作成しドラッグ用のUIButtonを作成し MainViewController.mにAというUIButtonを作成 ドラッグのclassに CGPoint pt = [[touches anyObject] locationInView:self]; CGRect frame = [self frame]; if (CGRectContainsPoint(A.frame, pt)){ [処理]; } とやってみたのですが処理は実行されませんでした .hを読み込ませたり、DragView.hにもUIButtonのAを作成してInterfaceBuilderでコネクトさせてみたりといろいろやってみましたがうまくいきませんでした。 (上記のコードだけでは決定的な原因がわかりづらいですね) できればもう少しアドバイスをお願いしたいです >誤解しないでください こちらも冗談のつもりで()を付けて書いたので気にしないでください

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.1

Yes or Noの二択回答を求めていらっしゃるなら、回答は「Yes」です。 もし、具体的にそういうプログラムを書いてくれという要求でしたら、お答えしません。(お金がもらえるなら、いくらでもプログラムを書きますけどね。) ヒントなり、方向性をアドバイスして欲しいということでしょうか?

nosuke5614
質問者

補足

返答ありがとうございます そうですね どういったクラス?を使用すればよいのかなどのアドバイスをいただきたいですね 教えていただけたらこちらでも調べますし、うまくいかない点があったらまた新しく質問を投稿させてもらいます (ちなみにプログラムのサンプルを書いてもらうにはおいくらですか?)

関連するQ&A

  • iPhone アプリ タップ 拡大

    iPhoneアプリの作成に関しての質問です。 アプリ起動後、画像ボタンをタップするとその画像が拡大(1.5倍ほど)されて表示 拡大後、そのボタンの周りに設置されたボタンを押すことができるようになり 中央をタップすると縮小してもとに戻る こういったアクションを加えたいのですがどうすればよいでしょうか?

  • iPhone 画像 表示 非表示

    iPhoneアプリに関する質問です。 アクションの間のみ画像を表示させる、というものを作成したいです。 UIView beginAnimationsでボタンにアニメーションを追加し タップ(if)後、画像(ボタン)を指定の座標に表示 タップ(else)後、画像を消す(画像が動いていた場合、非表示にしてから座標を初期に戻す) こういったメソッドを作成したいです。

  • Phoneアプリ とあるプログラムの質問です。

    IB上で、UIButtonにて、ボタンをタッチして離した時に、UIImageの画像Aを画像Bに切り替えるプログラムは分かるのですが、さらにボタンをタッチして離した時に再度、画像Aに切り替えるためには、初めの切り替えに使ったUIButtonの上に別のUIButtonを作って、そこに別のIBActionを設定するしかないでしょうか。 完全な回答ではなくアドバイスやヒントでもかまいません。 どなたかご教授いただけたら幸いです。

  • [iPhoneアプリ開発]オブジェクトの制御

    iPhoneアプリ開発初心者です。 わからないところがあるので質問します。 xcodeのstoryboardとかで配置されたUILabelやUIButtonを制御するViewControllerというクラスがありますが、自前のクラスでViewContorollerと同じ(似た)処理をさせることは可能でしょうか。 例えば複数のオブジェクト(UILabelとか)を作成しボタンが押されたらアニメーションさせるクラス(ここではMyClassとします)なんかです。 自分の考えではボタンを制御するのはViewControllerクラスで、それが押されたらMyClassクラスのインスタンスに「アニメーションを実行させよ」というメッセージを送る、といった感じです。 ViewControllerで処理を一括するのもありですが、アニメーションさせたいオブジェクトを実行時にランダムに作りたいので、処理がややこしくなると思い別のクラスにまかせたほうがいいと思いました。 一応objective-cの知識として、「デリゲード」や「カテゴリ」といった言葉を知っていますがどう使えばいいかわかりません。 疑問の丸投げになりますが、いろいろ試してもできなかったので今回ここで質問しようと思いました。 よろしくお願いします。

  • Objective-C if

    iPhone アプリ開発での質問です if文で条件をつける際 3つの条件が整ったらアクションを実行というようにさせたいのですがどうすれば良いのでしょうか? hiddenで隠していたUIButtonが表示されていた場合、実行とすると if(XXX.hidden){ }else{表示なのでここに処理} というようになりますよね? これで指定した3つが表示されていた場合実行というようにしたいです

  • iPhone アプリ ドラッグ

    iPhoneアプリ作成で iPhoneのロック画面解除で画像を右へスライドさせてロックを解除する このようなアクションを作成したいのですがどうすればよいのでしょうか? 画像のドラッグだとA点(初期)からB点(目的地)までいろんな経路で行くことができますが そうではなく、A点からB点までを一直線で結んで その線の上しか移動することができないようにしたいです (画像を放した際、初期の場所に戻らなくていいです) どうすればよいでしょうか?

  • iPhone Objective-C ドラッグ

    iPhoneアプリで画像のドラッグはYouTube等の動画サイトで 説明付きのものもあり 作成することはできたのですが 画像ではなく ボタンの場合だとどうすればよいのでしょうか? Interface Builderですでに他のアクションとコネクト済みのボタンをドラッグさせることは可能でしょうか?

  • UIに関する記述について(iphone)

    知り合いにiphoneアプリを作成して頂きました。プログラマが記述した 拡張子がmのファイルを見たのですがUIに関する記述が見当たりません。ボタンのあるアプリなのでUIbuttonとかあると思っていたのですが…、UIに関する記述は一体どこにあるのですか。教えて下さい。

  • Objective-c ボタンの動的配置

    ボタンを以下のように、動的に配置していますが、画像がぼやけて表示されてしまいます。 調べると、座標の指定が整数値でない場合、この問題が起こったりするようなのですが、 整数値にしても奇麗に表示されません。。 どなたか、お分かりになる方教えて下さい。 myButton = [UIButton buttonWithType:UIButtonTypeCustom]; UIImage *myImage = [UIImage imageNamed:[NSString stringWithFormat:@"test.png"]]; [myButton setImage:myImage forState:UIControlStateNormal]; [myButton] setFrame:CGRectMake(100,100,200,200)]; [myButton addTarget:self action:@selector(test:) forControlEvents:UIControlEventTouchUpInside]; [scrollView addSubview:myButton ];

  • CGRectContainsPoint 一度処理

    またこちらで質問させていただきます iPhone Objective-Cに関する質問です CGRectContainsPointで指定したUIButtonの内側にtouchesMovedで動かしている UIImageViewが存在すると指定したcafをAVAudioPlayerで再生させる というコードを書きました しかしこれだと UIButtonの内側で動作があると何回も音声が再生されてしまいます UIButtonのサイズが大きいとUIImageViewがUIButton上を通過 させている間に何回も再生されます これを一度だけ再生させるようにするにはどうすればよいでしょうか? 1.UIButton上に来たら一度だけ再生 2.UIButton上から外れたら一度だけ再生という処理を解除 3.外れた後、UIImageViewをもう一度UIButtonの内側に持ってきたらまた1の処理 このようにしたいです。