我正在与iPhone一起开发一些基本的应用程序/实用程序/游戏,以便更好地掌握它。
我目前有一个设置,CGRect在手指移动的任何位置移动,但是我不希望CGRect位于view的bounds之外。
原始方法
- (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的方法发布在下面,但是它不起作用吗?
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的代码,但是没有从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*/;所显示的圆圈的大小在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和currentTouchLocation这两个最高值的限制,得到X的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];
}今天是学习的好日子。
发布于 2009-12-17 17:41:03
你肯定想要利用它的超级视图的界限来限制它的运动。
不要经常这样称呼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];
}https://stackoverflow.com/questions/1922748
复制相似问题