代码之家  ›  专栏  ›  技术社区  ›  Sneakyness

使用view.bounds创建边界

  •  4
  • Sneakyness  · 技术社区  · 15 年前

    我正在用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 这是保持健康的最好方法 界限 .

    self.view.bounds . 我如何利用这些资源 界限 这样做?有没有更好的方法来防止它的发生,而不是设置 手动?我可以对它设定一个严格的限制吗?

    那一个呢 switch 陈述这会比尝试的方法更好吗- if S


    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: (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)
    


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

    修复此问题后,我可以继续处理原始问题。


    好的,我已经解决了另一个问题。我正在添加到 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)
    

    它阻止我离开屏幕的顶部,再次从 马克斯 . 如上图所示,我仍然能够从右侧飞出。

    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)
    

    它在两个方向上都失败了。现在实际值来自 马克斯 ,最大值来自 . 世界跆拳道联盟?

    左下角:

    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)
    

    可以预见,它只适用于最小值。我仍然很困惑这些函数应该做什么。非常感谢您的洞察力!


    解决了的!

    谢天谢地,我们漫长的道路即将结束。所以,因为我不知道,这里是什么 做由于当时的混乱,我一开始并不清楚。

    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。

    如果您想知道为什么要这样做,那是因为用户无法通过他的/她的手指看到。

    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.应用数学约束:

    首先,我们得到 ,或最高值,根据我们的限制,这两个值都是可能的最低值, minX ,及 startTouchLocation X currentTouchLocation .

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

    maxX ,及 当前接触位置 X . 请注意,我们使用的不是原始触摸的位置,而是最终触摸的位置 马克斯 我们刚才使用的函数。这个值已经在屏幕左侧检查过了,所以我们检查了右侧。

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

    今天是学习的好日子。

    1 回复  |  直到 15 年前
        1
  •  2
  •   Brad G    15 年前

    我将使用以下类似的方法来实现这一点。

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