「動くUIImageViewでタッチイベントを検出するにはどうすればよいですか?」を調査するとき 私はいくつかの答えに出くわし、それらを自分のアプリに実装しようとしました。私が遭遇したものは何も機能していないようです。私がやろうとしていることを説明してから、コードを投稿します。ご意見、ご提案、コメント、または回答をお待ちしております。
私のアプリには、左から右に画面全体に浮かぶカードがいくつかあります。これらのカードはさまざまな色で、ゲームの目的はカードを同じ色の対応するコンテナにドラッグすることです。ユーザーがカードを十分な速さでタッチしてドラッグしないと、カードが画面から外れてしまい、ポイントが失われます。正しいコンテナに含まれるカードが多いほど、スコアが高くなります。
カードが左から右にフロートするように、コア アニメーションを使用してコードを記述しました。これは機能します。ただし、カードに触れてコンテナに向かってドラッグしようとすると、カードの UIImageView に触れていることが正しく検出されません。
カードを移動するコードが適切に実装されているかどうかをテストするために、動かないカードの移動を可能にするコードもいくつか書きました。この場合、私のタッチが検出され、それに応じて動作します。
動かないカードしか操作できないのはなぜですか? これをかなり調査した後、コードは次のようです。
options:UIViewAnimationOptionAllowUserInteraction
私の動くUIImagesを検出するための重要な要素です。しかし、私はこれを試してみましたが、効果はないようです。
私が間違っているかもしれないもう1つの重要なことは、正しいプレゼンテーションレイヤーを適切に利用していないことです。このようなコードをプロジェクトに追加しました。また、動かないオブジェクトでのみ作業します。
UITouch *t = [touches anyObject];
UIView *myTouchedView = [t view];
CGPoint thePoint = [t locationInView:self.view];
if([_card.layer.presentationLayer hitTest:thePoint])
{
NSLog(@"You touched a Card!");
}
else{
NSLog(@"backgound touched");
}
これらのタイプのことを試した後、私は立ち往生しています。これをもう少し完全に理解するための私のコードは次のとおりです。
#import "RBViewController.h"
#import <QuartzCore/QuartzCore.h>
@interface RBViewController ()
@property (nonatomic, strong) UIImageView *card;
@end
@implementation RBViewController
- (void)viewDidLoad
{
srand(time (NULL)); // will be used for random colors, drift speeds, and locations of cards
[super viewDidLoad];
[self setOutFirstCardSet]; // this sends out 4 floating cards across the screen
// the following creates a non-moving image that I can move.
_card = [[UIImageView alloc] initWithFrame:CGRectMake(400,400,100,100)];
_card.image = [UIImage imageNamed:@"goodguyPINK.png"];
_card.userInteractionEnabled = YES;
[self.view addSubview:_card];
}
次のメソッドは、画面左側のランダムな場所からカードを送り出し、コア アニメーションを使用してカードを画面上でドリフトさせます。カードの色とドリフトの速度もランダムに生成されることに注意してください。
-(void) setOutFirstCardSet
{
for(int i=1; i < 5; i++) // sends out 4 shapes
{
CGRect cardFramei;
int startingLocation = rand() % 325;
CGRect cardOrigini = CGRectMake(-100,startingLocation + 37, 92, 87);
cardFramei.size = CGSizeMake(92, 87);
CGPoint origini;
origini.y = startingLocation + 37;
origini.x = 1200;
cardFramei.origin = origini;
_card.userInteractionEnabled = YES;
_card = [[UIImageView alloc] initWithFrame:cardOrigini];
int randomColor = rand() % 7;
if(randomColor == 0)
{
_card.image = [UIImage imageNamed:@"goodguy.png"];
}
else if (randomColor == 1)
{
_card.image = [UIImage imageNamed:@"goodguyPINK.png"];
}
else if (randomColor == 2)
{
_card.image = [UIImage imageNamed:@"goodGuyPURPLE.png"];
}
else if (randomColor == 3)
{
_card.image = [UIImage imageNamed:@"goodGuyORANGE.png"];
}
else if (randomColor == 4)
{
_card.image = [UIImage imageNamed:@"goodGuyLightPINK.png"];
}
else if (randomColor == 5)
{
_card.image = [UIImage imageNamed:@"goodGuyBLUE.png"];
}
else if (randomColor == 6)
{
_card.image = [UIImage imageNamed:@"goodGuyGREEN.png"];
}
_card.userInteractionEnabled = YES; // this is also written in my viewDidLoad method
[[_card.layer presentationLayer] hitTest:origini]; // not really sure what this does
[self.view addSubview:_card];
int randomSpeed = rand() % 20;
int randomDelay = rand() % 2;
[UIView animateWithDuration:randomSpeed + 10
delay: randomDelay + 4
options:UIViewAnimationOptionAllowUserInteraction // here is the method that I thought would allow me to interact with the moving cards. Not sure why I can't
animations: ^{
_card.frame = cardFramei;
}
completion:NULL];
}
}
次のメソッドは、CALayer とヒット テスト情報を配置する場所です。これを正しく行っているかどうかはわかりません。
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
UIView *myTouchedView = [t view];
CGPoint thePoint = [t locationInView:self.view];
thePoint = [self.view.layer convertPoint:thePoint toLayer:self.view.layer.superlayer];
CALayer *theLayer = [self.view.layer hitTest:thePoint];
if([_card.layer.presentationLayer hitTest:thePoint])
{
NSLog(@"You touched a Shape!"); // This only logs when I touch a non-moving shape
}
else{
NSLog(@"backgound touched"); // this logs when I touch the background or an moving shape.
}
if(myTouchedView == _card)
{
NSLog(@"Touched a card");
_boolHasCard = YES;
}
else
{
NSLog(@"Didn't touch a card");
_boolHasCard = NO;
}
}
次の方法で図形を移動できるようにします。動かない形状でのみ機能します。多くの回答は、タッチでカードがどのクラスのものかを尋ねるように言っています。現在、すべてのカードが同じクラス (viewController クラス) にあります。カードを独自のクラスにしようとしたときに、そのビューをメインのバックグラウンド コントローラーに表示するのに問題がありました。これが機能するには、さまざまなクラスのさまざまなカードが必要ですか、それともそうする必要なく機能させることができますか?
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if([touch view]==self.card)
{
CGPoint location = [touch locationInView:self.view];
self.card.center=location;
}
}
この次のメソッドは、ユーザーがカードを動かし始めてからカードを持ち上げると、カードの動きをリセットします。
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(_boolHasCard == YES)
{
[UIView animateWithDuration:3
delay: 0
options:UIViewAnimationOptionAllowUserInteraction
animations: ^{
CGRect newCardOrigin = CGRectMake(1200,_card.center.y - 92/2, 92, 87);
_card.frame = newCardOrigin;
}
completion:NULL];
}
}
@end