1

サブビューとしていくつかのビューを追加し、UILongPressGestureRecognizer (これは、UI 要素に指を置いたことを認識するための正しいジェスチャーですか??) と UIPanGestureRecognizer を処理して、画面内のビューを移動します (アイデアを得るには、前の質問を参照してください)。私が構築しているものの -> SO )

指を置いたときにアニメーションを追加し(フリップ、小さなズームのように)、ビューを移動して他のビューを再配置し、最後に配置してビューを並べ替えたいと思います。

私の最初の問題は、ビューを長押しするとジェスチャが認識されるが、このジェスチャが終了していない間はビューを画面に移動して再配置できないことです。どうすればこれを解決できますか?UI要素(UIMyView)を長押しすると、このイベントのアニメーションが実行され、指を離さずに、PanGestureがすでに機能しているように動き始めます。

UIView サブクラスを作成し、目的の UIGestureRecognizers を追加しました。

NSNotificationCenter を使用して、ジェスチャーが発生したことを MainViewController に通知して、ビューのレイアウトを変更できるようにしました (これは正しいアプローチですか、または、イベントを次のレスポンダーにプッシュするなど、このジェスチャーが別の方法で発生したことをスーパービュー コントローラーにプッシュできます)。 ?

drawTextInRect メソッドを使用して文字をビューのサイズに描画します。そのため、その中のビューのレイアウトを変更することはできません。

MainViewController で、特定のビューの NSNotification オブザーバー セレクターで setNeedsDisplay を呼び出しますが、必要に応じてビューが変更されたがまだ表示されていないように、ドラッグ中に空の白いビューが表示されるだけで機能しません。スレッドの一時停止の原因またはなにか。

PanGesture が終了すると、MainViewController に再度通知し、setNeedsDisplay を再度呼び出しますが、設定した (そして設定されている) 背景色以外は機能し、ドラッグ中に表示されるはずの以前の状態のままですが、キャラクターは再び正しく描画されます。

心が糸を引く!?

[編集] いくつかのコード サンプル:

   // Inside the UIMyView
-(void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
     [[NSNotificationCenter defaultCenter] postNotificationName:@"MyViewNotification" object:self];
    // Here I will put my animations, not yet proceed with them
    // Code for lastLocation
    isViewTouched = YES;
    [self setNeedsDisplay];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
     // code for moving the View with finger
}

-(void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
  isViewTouched = NO;
  [self setNeedsDisplay];
}

-(void) drawLayout
{
  UILabel* labelToDraw = [[UILabel alloc] init];
  labelToDraw.text = @"1";
  labelToDraw.font = [self getFont];
  labelToDraw.textcolor = [UIColor blackColor];
  self.backgroundColor = [UIColor whiteColor];
  [labelToDraw drawTextInRect:self.bounds];
}
// The same method with other color values and text exist for another layout.
// Called inside of drawRect:(CGRect)rect when calling setNeedsDisplay as I know and it is

-(void) drawRect:(CGRect)rect
{
  if (isViewTouched) [self drawLayout];
  else [self drawLayoutMoving];
}
    //Superview Controller notified
-(void) handleMyViewNotification:(NSNotification*)notification
{
  myViewMoving = [notification object];
  [self performSelectorInbackground:@selector(manageArrayOfMyViews) withObject:nil];
}

-(void) manageArrayOfMyViews
{
  // animate and reorder the array of views not touched
}

私はObjective-Cが初めてなので、ここで何かが欠けています。私のアプローチが一般的に正しいかどうかを知りたいです。

ありがとうございました。

4

1 に答える 1

1

Gesture Recognizer は、問題を解決する最も簡単な方法ではないようです。使ってみて

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

タッチの開始を検出し、開始アニメーションを再生します。それで

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

ビューをドラッグします。と

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

指が画面上にないときに、最終設定を行います。

例えば:

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
   UITouch *touch = [touches anyObject];
   if ([touch.view isKindOfClass: [MyView class]]) {
      //play animation on touch.view
      lastLocation = [touch locationInView: self.view];
   }
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
   UITouch *touch = [touches anyObject];
    if ([touch.view isKindOfClass: [MyView class]]) {
       CGPoint location = [touch locationInView: self.view];

       CGFloat xDisplacement = location.x - lastLocation.x;
       CGFloat yDisplacement = location.y - lastLocation.y;

       CGRect frame = touch.view.frame;
       frame.origin.x += xDisplacement;
       frame.origin.y += yDisplacement;
       touch.view.frame = frame;
   }
}

[編集]

あなたのコードから推測するように、移動したいビューの上に数字の付いたラベルを描画しようとしています。カスタム drawRect メソッドを実装する必要はなく、タスクはより簡単に実行できます。後でドラッグするビューを作成するときは、UILabel をサブビューとして追加し、必要に応じてカスタマイズします。

UIView* viewToDrag = [[UIView alloc] initWithFrame: // your frame];
UILabel* subLabel = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, viewToDrag.frame.size.width, viewToDrag.frame.size.height)];
 subLabel.tag = 0xff; // example tag, you can define it 
 [self customizeStaticLabel: subLabel]; //subroutine to customize your usual label appearance: set text, font, etc
[viewToDrag addSubview: subLabel];
[self.view addSubview: viewToDrag];

//insert release calls for subLabel and viewToDrag if you're NOT using ARC

以上で、ラベルはドラッグ可能なビューの子になりました。また、通知は必要なく、setNeedsDisplay を呼び出す必要もありません。

ビューをドラッグすると、ビューの subLabel が変更されます。

UILabel* labelToChange = (UILabel*)[touch.view viewWithTag: 0xff]; //this will get a subview label
[self customizeDraggedLabel: labelToChange];

touchesEnded では、ラベルを通常の状態に戻す必要があるため、

UILabel* labelToChange = (UILabel*)[touch.view viewWithTag: 0xff];
[self customizeStaticLabel: labelToChange];

ラベルの外観を変更するためのサブルーチン、たとえば:

-(void) customizeStaticLabel: (UILabel*) label{
   label.textColor = [UIColor redColor];
}

-(void) customizeDraggedLabel: (UILabel*) label{
   label.textColor = [UIColor blackColor];
}
于 2012-07-12T13:37:32.130 に答える