我正在使用 iPhone 开发一些基本的应用程序/实用程序/游戏,以便更好地掌握它。
我目前有一个设置,CGRect
可以让手指移动到任何地方,但是我不CGRect
希望bounds
.view
原始方法
- (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];
}
}
问题
我尝试了几种不同的方法,包括使用&&
并使其只是一个语句。显然是硬编码的boundaries
,我不确定手动设置touchLocation
是保持它的最佳方式bounds
。
当我可以轻松self.view.bounds
获得边界时,这一切对我来说似乎很愚蠢CGRect
。我如何利用bounds
来做到这一点?touchLocation
除了手动设置之外,有没有更好的方法来防止它发生?我可以以某种方式对其施加硬性限制吗?
一份switch
声明呢?这会比尝试if
的效果更好吗?
试图
我现在正在尝试使用下面发布的@Brad Goss 的方法,但是它不起作用?
Touch Started: (319.000000,350.000000)
Touch Result: (319.000000,350.000000)
Boundaries calculated: X:(0.000000,288.000000) Y(0.000000,328.000000)
Touch Started 是实际的开始触摸。触摸结果应该是更改后的结果。
上面的日志显示它在定义之外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
,但不add
计算minimums
. 这很重要,因为这就是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*/;
正在显示的圆圈的大小在 a 内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
。怎么回事?
左下角:
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)
可以预见的是,它只适用于最小值。对于这些功能应该做什么,我仍然很困惑。洞察力将不胜感激!
解决了!
幸运的是,我们漫长的道路即将结束。所以,因为我不知道,这里是做什么MIN
和MAX
做什么。由于发生了混乱,最初对我来说并不明显。
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
不要忘记手指的偏移量!
如果您正在做我所做的事情,并且将 keepOnScreenRect 定位在用户手指的上方,那么您应该只将额外的偏移量添加到 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];
}
今天是学习的好日子。