1

画面を拡大すると、uipangesturerecognizerに問題があります。

私のアプリには、uiviewを備えたuiviewcontrollerがあります。

このビューでは、画面境界全体のほぼ半分であるキャレイヤーがあります。

このcalayerには、ユーザーがドラッグ(uipangesture)、追加(uitapgesture)、および削除(doubletapgesture)できるいくつかのサブレイヤーがあります。より正確にドラッグするために、uiviewにuipinchgestureメソッドを追加してズームインおよびズームアウトしました。

この時点で、ズームインしてサブレイヤーを移動(パンジェスチャ)しようとした場合を除いて、すべてが正常に機能します。動作する場合もありますが、通常は動作しません(ズームインしないと常に正常に動作します)。

コードに何か問題があるのか​​、それともこれがその方法ではないのかわかりません。私が見逃しているものはありますか?

私はSDK4.2の下にいます。

これらは私のコードです:

    -(id)initWithFrame:(CGRect)frame
    {{
        [スーパーinitWithFrame:frame];
        (…)
        perfil = [[CALayer alloc] init]; //uiviewのcalayer
        [perfil setBounds:CGRectMake(0、0、wide、heigth / 2)];
        [[自己層]addSublayer:perfil];

        //ユーザーが「編集ボタン」に触れたときにサブレイヤーを「危険」レイヤーに追加します。これは正常に機能します

        // UIGsture Recognizers
        UITapGestureRecognizer * singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapFrom :)];
        UITapGestureRecognizer * doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTapFrom :)];
        UIPinchGestureRecognizer * pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchFrom :)];
        UIPanGestureRecognizer * panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom :)];
        [panGestureRecognizer setMinimumNumberOfTouches:1];
        [panGestureRecognizer setMaximumNumberOfTouches:1];
        [singleTapRecognizer setNumberOfTapsRequired:1];
        [singleTapRecognizer setCancelsTouchesInView:NO];
        [doubleTapRecognizer setNumberOfTapsRequired:2];

        [自己addGestureRecognizer:singleTapRecognizer];
        [自己addGestureRecognizer:doubleTapRecognizer];
        [自己addGestureRecognizer:pinchGestureRecognizer];
        [自己addGestureRecognizer:panGestureRecognizer];

        [singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
        singleTapRecognizer.delegate = self;
        doubleTapRecognizer.delegate = self;
        pinchGestureRecognizer.delegate = self;
        panGestureRecognizer.delegate = self;

        //ここにいくつかの他の異なるもの
    }

    -(void)handlePanFrom:(id)sender
    {{
        CGPointポイント=[(UIPanGestureRecognizer *)sender locationInView:self];
        boxLayer = [[self perfil] hitTest:point];
        [自己becomeFirstResponder];

        if([(UIPanGestureRecognizer *)sender state] == UIGestureRecognizerStateBegan)
        {{
            numberOfSublayer = 1000; //UIView.hでintとして宣言されています

            for(CALayer * [perfil sublayers]の要素)
            {{   
                if([boxLayer isEqual:elements])
                {{
                    numberOfSublayer = [[perfil sublayers] indexOfObject:elements];
                    壊す;
                }
            }
        }
        (…)//サブレイヤーを見つけたらさらにいくつかの操作
    }

    -(void)handlePinchFrom:(id)sender
    {{   
        if([(UIPinchGestureRecognizer *)sender state] == UIGestureRecognizerStateEnded)
        {{
            lastScale = 1.0;
            戻る;
        }

        if([(UIPinchGestureRecognizer *)sender state] == UIGestureRecognizerStateBegan ||
            [(UIPinchGestureRecognizer *)送信者の状態] == UIGestureRecognizerStateChanged){

            CGFloat currentScale = [[[sender view] .layer valueForKeyPath:@ "transform.scale"] floatValue];

            const CGFloat kMaxScale = 4.0;
            const CGFloat kMinScale = 1.0;

            CGFloat newScale = 1-(lastScale-[(UIPinchGestureRecognizer *)sender scale]);
            newScale = MIN(newScale、kMaxScale / currentScale);   
            newScale = MAX(newScale、kMinScale / currentScale);
            CGAffineTransform transform = CGAffineTransformScale([[sender view] transform]、newScale、newScale);
            [送信者ビュー].transform=変換;

            if([perfil sublayers])
            {{
                for(CALayer * [perfil sublayers]の要素)//ここでは、サブレイヤーへのズームを調整しようとしています
                {{
                    //これが最初のアプローチの1つです
                    // CGAffineTransform transformELS = CGAffineTransformScale([elements affineTransform]、7 /(newScale + 6)、7 /(newScale + 6));
                    // [elements setAffineTransform:transformELS];

                    //これが2番目のアプローチです
                    [elements setBounds:CGRectMake(0、0、elements.bounds.size.width * 7 /(newScale + 6)、elements.bounds.size.height * 7 /(newScale + 6))];
                }           
            }

            lastScale = [(UIPinchGestureRecognizer *)sender scale];
            (…)//ここに他のいくつかの異なるもの
    }

どうもありがとうございます。

4

2 に答える 2

1

最後に、私の問題に対する答えを見つけました。この投稿はまったく同じ問題を説明しており、その解決策は私にとって完璧に機能しました UIPanGestureRecognizer starting point is off . ありがとう。

于 2012-06-23T11:01:26.817 に答える
0

サブレイヤーのヒットテストコードを見ずに言うのは本当に難しいですが、親ビュー/レイヤーを再スケーリングするときにサブレイヤーを再スケーリングしているのは本当に奇妙に思えます。

親レイヤーをスケーリングするだけで、すべての子が順番にスケーリングされます。

ピンチコードとパンコードを手動で生成することはすべて危険に満ちています。それはできますが、スパゲッティになってしまいます。

ビューをUIScrollViewに配置し、ビューのピンチとパンの作業を実行させperfilます。

UIScrollViewのパンとズームの例は10億あります。Te GoogleとSOは、あなたがまだ知らないかどうかを知っています。

代わりに、親ビューのtouchBeganイベントでサブレイヤーのパンをキャプチャすることを期待します。

これは、サブレイヤーでヒットをキャプチャするために使用するものです

- (CALayer *)hitTest:(CGPoint)thepoint
{
    //
    CGPoint cpoint = [self convertPoint:thepoint fromLayer:self.superlayer];

    if (CGRectContainsPoint([self bounds], cpoint)) {
        NSLog(@"hitme!");
        return self;
    }

    return nil;

}

そして、これは親ビューのtouchesBegan/touchesMovedにあります。(スクロールビューへの弱参照を保持します)

// Handles the start of a touch
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{


    NSUInteger tcount = [touches count];
    if(tcount == 1)
    {

    UITouch* touch = [touches anyObject];
    CGPoint tpoint = [touch locationInView:self];
    location = [perfil convertPoint:tpoint fromLayer:view.layer];

    hitsublayer = [self hitTest:location];       
    if([hitsublayer isKindOfClass:[MySubBoxThing class]]){
        //ensure that scroll view doesn't capture the event  
        scrollview.canCancelContentTouches = NO;
    }
    else {
        hitsublayer = nil;
        //or something else to do wit not touching a sublayer.
    }

}

// Handles the continuation of a touch.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{   
    NSUInteger tcount = [touches count];
    if (tcount == 1 && hitsublayer) {

    UITouch* touch = [touches anyObject];
    CGPoint tlocation = [touch locationInView:self];
    location = [perfil convertPoint:tpoint fromLayer:view.layer];        

    NSLog(@"new loc = %@",[NSValue valueWithCGPoint:location]);
    hitsublayer.position = location;            

    }       

}

// Handles the end of a touch event when the touch is a tap.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    //NSLog(@"touches ended");
    scrollview.canCancelContentTouches = YES;
    hitsublayer = nil;
    //any other actions once finished drag of object


}

そのコードは完全でもバグチェックでもありませんが、あなたを近づけるはずです。

于 2012-06-10T11:47:38.277 に答える