質問

私はiPhoneを使用していくつかの基本的なアプリ/ユーティリティ/ゲームに取り組んでおり、より良いグリップを取得しています。

現在、a CGRect 指が動くところならどこでも動きますが、私は望んでいません CGRect 外に出る boundsview.

元の方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startLocation = [touch locationInView:self];
    if (startLocation.x < 33){
        touchLocation.x = 33;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    if (startLocation.x > 288){
        touchLocation.x = 288;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    if (startLocation.y < 84){
        touchLocation.y = 84;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    if (startLocation.y > 460){
        touchLocation.y = 460;
            //NSLog(@"Touch At:%f, %f", touchLocation.x, touchLocation.y);
        [self setNeedsDisplay];
    }
    else {
        touchLocation = startLocation;
        [self setNeedsDisplay];
    }
}

問題

私はこれのいくつかの異なる方法を試しましたが、 && そして、それを1つのステートメントにします。 boundaries 明らかにハードコード化されており、手動で設定するかどうかはわかりません touchLocation それを維持するための最良の方法です bounds.

これは私が簡単にできるとき、私にとってはすべて愚かなように思えます self.view.bounds そして、境界を取得します CGRect. 。どうすれば利用できますか bounds これをする?設定以外に発生するのを防ぐためのより良い方法はありますか touchLocation 手動で?代わりに、どういうわけかハードリミットを配置できますか?

a switch 声明?それは試みられたよりもうまくいくでしょうか -ifs?


試み

私は今、以下に掲載されている@BradGossの方法を利用しようとしていますが、それは機能していませんか?

Touch Started: (319.000000,350.000000)
Touch Result: (319.000000,350.000000)
Boundaries calculated: X:(0.000000,288.000000) Y(0.000000,328.000000)

開始されたタッチは、実際のスタートタッチです。タッチ結果は変更された結果である必要があります。

上記のログは、定義されたものの外側にそれを示しています bounds, 、別名、機能していません。まったく同じだから彼が書いたコードを再投稿するつもりはありません。


問題を試みます

問題を発見しました。これは上記と同じタイプの状況ですが、個々の値が設定されているためにログを記録すると。

Touch Started: (293.000000,341.000000)
min x:288.000000
max x:293.000000
min y:328.000000
max y:341.000000
Touch Result: (293.000000,341.000000)
Boundaries calculated: X:(0.000000,288.000000) Y(0.000000,328.000000)

私はそれを理解していません、私はそれを発見したらすぐにここにそれを投稿しました。そうでなければ、更新するのを忘れてしまいます。

私は戻って、それぞれの可能な状況で何が起こっているのかを正確に見るつもりです。


間違い

別の問題、計算するコードを見つけました boundaries subtracts から maximums, 、しかしそうではありません addminimums. 。これは重要です boundary のためであり、停止するためです rect 画面から外れることから。

maxX = b.origin.x + b.size.width/* - [box bounds].size.width */;
minX = b.origin.x/* + [box bounds].size.width */;
maxY = b.origin.y + b.size.height/* - [box bounds].size.height */;
minY = b.origin.y?/* + [box bounds].size.height */;

これが修正されていると、元の問題に取り組み続けることができます。


ミス2

さて、私は別の問題を修正しました。私はに追加していました y 表示されているときの値。この新しいコードに追加することを忘れていました/言及しました。コードは次のようになりました:

maxX = b.origin.x + b.size.width/* - [box bounds].size.width */;
minX = b.origin.x/* + [box bounds].size.width */;
maxY = b.origin.y + b.size.height/* - [box bounds].size.height + 20*/;
minY = b.origin.y/* + [box bounds].size.height + 20*/;

表示されている円のサイズは 64px CGRect, 、 それで 20px 親指のすぐ上に円を表示するのに十分でした。これは修正されていますが、まだ元の問題を解決するのに役立ちませんでした。

左上隅:

Touch Started: (14.000000,20.000000)
min x:14.000000
max x:32.000000
min y:20.000000
max y:84.000000
Touch Result: (32.000000,84.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

それは必要に応じて機能しますが、私は正しい値が出てくる理由について混乱しています MAX それ以外の MIN. 。ここで何かが混ざり合っています。

右上隅:

Touch Started: (303.000000,21.000000)
min x:288.000000
max x:303.000000
min y:21.000000
max y:84.000000
Touch Result: (303.000000,84.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

それは私が画面の上部から外れることを妨げています。 MAX それ以外の MIN. 。上記のように、私はまだ右から飛ぶことができます。

右下隅:

Touch Started: (317.000000,358.000000)
min x:288.000000
max x:317.000000
min y:276.000000
max y:358.000000
Touch Result: (317.000000,358.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

両方向で失敗しています。今、実際の値はから来ています MAX, 、そして最大値はから来ています MIN. 。 wtf?

左下隅:

Touch Started: (8.000000,354.000000)
min x:8.000000
max x:32.000000
min y:276.000000
max y:354.000000
Touch Result: (32.000000,354.000000)
Boundaries calculated: X:(32.000000,288.000000) Y(84.000000,276.000000)

予想通り、最小値でのみ機能しました。これらの機能が何をすべきかについて、私はまだ非常に混乱しています。洞察は大歓迎です!


解決した!

ありがたいことに、私たちの長い道のりは近づきます。だから、私には手がかりがなかったので、ここに何がありますか MINMAX 行う。混乱が起こったため、当初は私には明らかではありませんでした。

MAX(x,y) will output the larger of the two numbers
// MAX(13,37) = 37
MIN(x,y) will output the smallest of the two numbers
// MIN(13,37) = 13

したがって、これは、この状況でこれらの機能を正しく利用するためにあなたがしなければならないことです。

1. xおよびyの最大値と最小値を計算します。

それぞれの最低値は、として計算されます

view.origin + keepOnScreenRect.width  

それぞれの最高値は、として計算されます

view.origin + view.size.height/width - keepOnScreenRect.height/width

指のオフセットを忘れないでください!
あなたが私がしたことをしていて、keepOnscreentをユーザーの指のわずかに上に配置する場合、yの最小値は画面/ビューの下部であるため、yの最大値に追加のオフセットを追加するだけです。物理的には0より低くなることができません。

なぜこれが完了したのか疑問に思っているなら、それはユーザーが指を通して見ることができないからです。

2.タッチの場所を取得します touchesBegan:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startTouchLocation = [touch locationInView:self];
    NSLog(@"Touch Started: (%f,%f)", startTouchLocation.x, startTouchLocation.y);

3.数学的制約を適用します。

最初に、 MAX, 、または私たちの限界に応じて可能な最低値の両方の最高値、 minX, 、 と startTouchLocation, 、 為に X. 。これにより、画面の左側の制限が計算されます。この結果はに設定されています currentTouchLocation.

currentTouchLocation.x = MAX(minX, startTouchLocation.x);

第二に、 MIN, 、または最低値、私たちの限界に応じて可能な限り最高の値の両方で、 maxX, 、 と currentTouchLocation, 、 為に X. 。元のタッチの場所を使用していませんが、代わりに結果の場所を使用していることに注意してください。 MAX 使用した機能。この値はすでに画面の左側をチェックされているため、右をチェックします。

currentTouchLocation.x = MIN(maxX, currentTouchLocation.x);

それは私たちに与えます X 私たちの限界内にあることが保証されている場所。その後、同じことを実行します Y.

currentTouchLocation.y = MAX(minY, startTouchLocation.y);
currentTouchLocation.y = MIN(maxY, currentTouchLocation.y);

これがすべて完成したことで、私たちは今、それ自体を再描画するという見解を伝えることができ、もはや私たちの素敵な小さな長方形が何らかの形で遮断されることを恐れることはありません。

[self setNeedsDisplay];

完成品

/* Generates the limits based on the view's size, taking into account 
   the width/height of the rect being displayed in it. This should only
   be run once, unless the size of the view changes, in which case limits
   would have to be recalculated. The same goes for if you were to change
   the size of the displaying rect after calculation */

- (void)boundsCalculation {
    CGRect viewBounds = [self bounds];

        // calculate constraints
    maxX = viewBounds.origin.x + viewBounds.size.width - 32;
    minX = viewBounds.origin.x + 32;
    maxY = viewBounds.origin.y + viewBounds.size.height - 32;
    minY = viewBounds.origin.y + 84;
    NSLog(@"Boundaries calculated: X:(%f,%f) Y(%f,%f)", minX, maxX, minY, maxY);
}

/* Magic goodness that happens when the user touches the screen.
   Note that we don't calculate the bounds every time the user touches
   the screen, that would be silly. */

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startTouchLocation = [touch locationInView:self];
    NSLog(@"Touch Started: (%f,%f)", startTouchLocation.x, startTouchLocation.y);

        // apply constraints
            // highest x value between the lowest allotted x value and touch
    currentTouchLocation.x = MAX(minX, startTouchLocation.x);
            // lowest x value between the highest allotted x value and touch
    currentTouchLocation.x = MIN(maxX, currentTouchLocation.x);
            // highest y value between the lowest allotted y value and touch
    currentTouchLocation.y = MAX(minY, startTouchLocation.y);
            // lowest y value between the highest allotted y value and touch
    currentTouchLocation.y = MIN(maxY, currentTouchLocation.y);
           // NSLog(@"Touch Result: (%f,%f)", currentTouchLocation.x, currentTouchLocation.y);

           // If you don't do this you won't see anything
    [self setNeedsDisplay];
}

今日は学ぶのに良い日でした。

役に立ちましたか?

解決

あなたは間違いなくその監督の境界を使用して、その動きを制約したいと考えています。

頻繁にsetneedsdisplayに電話しないでください。メソッドの最後に一度呼び出します。あなたは潜在的に不必要に再描画しています。

これを達成するために次のようなものを使用します。

// define these variables where ever you'd like
static float maxX = 0.;
static float maxY = 0.;
static float minX = 0.;
static float minY = 0.;

- (void)setupView {
    CGRect b = [self bounds];

    // calculate constraints
    maxX = b.origin.x + b.size.width/* - [box bounds].size.width */;
    minX = b.origin.x;
    maxY = b.origin.y + b.size.height/* - [box bounds].size.height */;
    minY = b.origin.y;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    startLocation = [touch locationInView:self];

    // apply constraints
    touchLocation.x = MIN(maxX, startLocation.x);
    touchLocation.x = MAX(minX, startLocation.x);
    touchLocation.y = MIN(maxY, startLocation.y);
    touchLocation.y = MAX(minY, startLocation.y);

    [self setNeedsDisplay];
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top