Frage

Ich arbeite an ein paar grundlegenden Apps/Dienstprogrammen/Spielen mit dem iPhone, um es besser zu machen.

Ich habe derzeit ein Setup, bei dem a CGRect bewegt sich wo immer der Finger bewegt, aber ich will das nicht CGRect außerhalb der bounds des view.

Originalmethode

- (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];
    }
}

Problem

Ich habe einige verschiedene Methoden davon ausprobiert, einschließlich der Verwendung && und es nur zu einer Aussage machen. Das boundaries sind offensichtlich hart codiert, und ich bin mir nicht sicher, ob das manuell die manuell einstellen touchLocation ist der beste Weg, um es zu behalten bounds.

Das alles scheint mir albern, wenn ich leicht kann self.view.bounds und die Begrenzung bekommen CGRect. Wie benutze ich von bounds um dies zu tun? Gibt es einen besseren Weg, um zu verhindern, dass es sich nicht einstellen, als einzustellen? touchLocation manuell? Kann ich stattdessen irgendwie eine harte Begrenzung geben?

Was ist mit switch Aussage? Würde das besser funktionieren als die versuchten?ifs?


Versuchen

Ich versuche jetzt, die unten veröffentlichte Methode von @Brad Goss zu verwenden, aber es funktioniert nicht?

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

Berührung begonnen ist der tatsächliche Startakt. Touch -Ergebnis sollte das geänderte Ergebnis sein.

Das obige Protokoll zeigt es außerhalb des definierten bounds, auch bekannt als nicht arbeitet. Ich werde den Code, den er geschrieben hat, nicht neu veröffentlichen, weil er genau dasselbe ist.


Versuchsproblem

Ich habe das Problem entdeckt. Dies ist die gleiche Typsituation wie oben, jedoch mit der Anmeldung für die einzelnen Werte, die sie festgelegt sind.

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)

Ich habe es nicht herausgefunden, ich habe es hier gepostet, sobald ich es entdeckt habe. Ansonsten würde ich vergessen, überhaupt zu aktualisieren, Heh hinzuzufügen.

Ich werde zurückgehen und genau sehen, was in jeder der möglichen Situationen vor sich geht.


Fehler

Fand ein anderes Problem, den Code, der das berechnet boundaries subtracts von dem maximums, aber nicht add zum minimums. Dies ist wichtig, da dies das ist, was das ist boundary ist für, um das zu stoppen rect vom Bildschirm ausgehen.

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 */;

Mit diesem fest kann ich weiter an dem ursprünglichen Problem arbeiten.


Fehler 2

Okay, ich habe ein anderes Problem behoben. Ich fügte dem hinzu y Wert, wenn es angezeigt wurde. Ich habe vergessen, es in diesen neuen Code hinzuzufügen/ihn zu erwähnen. Der Code sieht jetzt so aus:

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*/;

Die Größe des angezeigten Kreises befindet sich innerhalb von a 64px CGRect, Also 20px war ausreichend, um den Kreis direkt über dem Daumen anzuzeigen. Obwohl dies festgelegt ist, hat es immer noch nicht geholfen, unser ursprüngliches Problem zu lösen.

Obere linke Ecke:

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)

Es funktioniert so wie es sollte, aber ich bin verwirrt darüber, warum die richtigen Werte herauskommen MAX Anstatt von MIN. Hier ist etwas durcheinander.

Obere rechte Ecke:

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)

Es hindert mich daran, wieder von der Spitze des Bildschirms zu gehen MAX Anstatt von MIN. Ich bin immer noch in der Lage, nach rechts abzufliegen, wie oben gezeigt.

Rechte untere Ecke:

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)

Es scheitert in beiden Richtungen. Jetzt kommen die tatsächlichen Werte von MAX, und die maximalen Werte kommen von MIN. WTF?

Untere linke Ecke:

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)

Vorhersehbar funktionierte es nur für den Mindestwert. Ich bin immer noch sehr verwirrt darüber, was diese Funktionen tun sollen. Einsicht wäre sehr geschätzt!


Gelöst!

Unsere lange Straße zieht zum Glück zu Ende. Also, weil ich keine Ahnung hatte, hier ist was MIN und MAX tun. Es war mir aufgrund der Verwirrung, die stattgefunden hatte, anfangs anfangs offensichtlich.

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

Dies ist also, was Sie tun müssen, um diese Funktionen in dieser Situation korrekt zu nutzen:

1. Berechnen Sie die maximalen und minimalen Werte für x und y.

Der niedrigste Wert für jeden wird berechnet als

view.origin + keepOnScreenRect.width  

Der höchste Wert von jedem wird berechnet als

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

Vergessen Sie nicht den Offset für den Finger!
Wenn Sie das tun, was ich getan habe, und die KeeponScrect -Sichtweise etwas über dem Finger des Benutzers positionieren lassen, sollten Sie den zusätzlichen Offset nur zum Maximalwert von y hinzufügen, da der Mindestwert von y der untere Bildschirm/die untere Ansicht ist, welche Sie sind physisch nicht in der Lage, niedriger als 0 bei zu gehen.

Wenn Sie sich fragen, warum dies geschehen ist, liegt es daran, dass der Benutzer nicht durch seinen Finger sehen kann.

2. Holen Sie sich den Standort der Berührung an 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. Wenden Sie die mathematischen Einschränkungen an:

Erstens bekommen wir das MAX, oder höchstem Wert, sowohl vom niedrigstmöglichen Wert gemäß unseren Grenzen, minX, und startTouchLocation, zum X. Dies berechnet die Grenze für die linke Seite des Bildschirms. Das Ergebnis davon ist auf currentTouchLocation.

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

Zweitens bekommen wir das MIN, oder niedrigster Wert, sowohl vom höchstmöglichen Wert gemäß unseren Grenzen, maxX, und currentTouchLocation, zum X. Beachten Sie, dass wir den Ort der ursprünglichen Berührung nicht verwenden, sondern den daraus resultierenden Ort der MAX Funktion, die wir gerade verwendet haben. Dieser Wert wurde bereits auf die linke Seite des Bildschirms überprüft, sodass wir die rechte überprüfen.

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

Das gibt uns eine X Ort, der garantiert in unseren Grenzen liegt. Wir führen dann das gleiche auf Y.

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

Mit all dem beendet können wir jetzt die Aussicht erkennen, sich neu zu zeichnen und keine Angst mehr zu haben, unser hübsches kleines Rechteck in irgendeiner Weise abzuschneiden.

[self setNeedsDisplay];

Fertiges Produkt

/* 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];
}

Heute war ein guter Tag zum Lernen.

War es hilfreich?

Lösung

Sie möchten auf jeden Fall die Grenzen der Übersicht verwenden, um seine Bewegung einzuschränken.

Rufen Sie SetNeedsDisplay nicht so oft an. Nennen Sie es am Ende der Methode einmal. Sie zeichnen möglicherweise unnötig neu.

Ich würde so etwas wie das Folgende verwenden, um dies zu erreichen.

// 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];
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top