简体   繁体   English

UIView范围之外的用户交互

[英]User interaction outside the UIView bounds

What i'm trying to do is "navigating" into a bigger UIView with buttons and controls positioned in different places. 我正在尝试做的是“导航”到更大的UIView,其中的按钮和控件位于不同的位置。 I've made the size of the main UIView twice bigger than the usual. 我已经使主UIView的大小比平时大了两倍。 It is 640x480 instead of 320x480. 它是640x480,而不是320x480。

After clicking a button in the first part of the screen i've made a moving translation of -320px in the x-direction to show the second "hidden" part of the screen where other functions will reveals to the user. 单击屏幕第一部分中的按钮后,我在x方向上移动了-320px,以显示屏幕的第二个“隐藏”部分,其他功能将向用户显示。 Everything works perfect apart the fact i can't get the UIView back to the original position. 除了我无法将UIView恢复到原始位置的事实之外,一切工作都很完美。 It seems that the button i use to get back to the original position and that is "outside the bounds" of the 320px, doesn't work. 看来我用来返回原始位置的按钮不起作用,它在320px的“边界之外”。

My UIView is referenced as "introScreen", and the following is the function i call to translate the screen through the x direction: 我的UIView被称为“ introScreen”,以下是我调用的用于通过x方向平移屏幕的函数:

- (void)secondPartOfTheScreen {

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.15];
        introScreen.transform = CGAffineTransformMakeTranslation(-320, 0);
        [UIView commitAnimations];

}

Calling this function my UIView moves correctly, but when my button appear in this part of the screen, it doesn't get any user interaction. 调用此函数,我的UIView可以正确移动,但是当我的按钮出现在屏幕的此部分时,它不会引起任何用户交互。 If i move that button in the first part of the screen, it works correctly. 如果我在屏幕的第一部分中移动该按钮,它将正常工作。 It have something to do with the screen bounds? 它与屏幕范围有关吗? It is possibile to solve it? 有可能解决吗?

Thanks in advance! 提前致谢!

You should try to subclass your UIView and override its pointInside:withEvent: method so that also a point outside its bounds is recognized as belonging to the view. 您应该尝试对UIView进行子类化,并重写其pointInside:withEvent:方法,以便将超出其范围的点也识别为属于视图。 Otherwise, there is no chance that user interaction outside of the view bounds are handled as you would like to. 否则,就不可能按照您的意愿处理视图范围之外的用户交互。

This is what the Event Handling Guide say: 这是事件处理指南所说的:

In hit-testing, a window calls hitTest:withEvent: on the top-most view of the view hierarchy; 在命中测试中,一个窗口在视图层次结构的最顶层视图上调用hitTest:withEvent:。 this method proceeds by recursively calling pointInside:withEvent: on each view in the view hierarchy that returns YES, proceeding down the hierarchy until it finds the subview within whose bounds the touch took place. 此方法通过在返回YES的视图层次结构中的每个视图上递归调用pointInside:withEvent:来继续进行下去,直到在找到发生触摸的子视图内找到子视图为止。 That view becomes the hit-test view. 该视图将成为命中测试视图。

You could use something like this in your custom UIView : 您可以在自定义UIView使用类似这样的内容:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    for (UIView* view in self.subviews) {
      if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
        return YES;
      }
    }
    return NO;
}

You could do with this: 您可以这样做:

@interface MyView: UIView
@end

@implementation MyView

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    for (UIView* view in self.subviews) {
      if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
        return YES;
      }
    }
    return NO;
}
@end

add this class definition to the beginning of the .m file where you are using the view. 将该类定义添加到使用视图的.m文件的开头。 (You could also use separate .h/.m files, but for the sake of testing if everything works, it is enough). (您也可以使用单独的.h / .m文件,但是为了测试是否一切正常,就足够了)。 Then, replace UIView with MyView in the instantiation of your current UIView , and it should work. 然后,在当前UIView的实例化中用MyView替换UIView ,它应该可以工作。

You're not using the transform property properly, you should take into account the previous value of the property like this: 您没有正确使用transform属性,应考虑该属性的先前值,如下所示:

introScreen.transform = CGAffineTransformConcat(introScreen.transform, CGAffineTransformMakeTranslation(-320, 0));

Hope this helps, and check Apple's UIView documentation and CGAffineTransform documentation for more details. 希望对您有所帮助,并查看Apple的UIView文档CGAffineTransform文档以获取更多详细信息。

2 things. 2件事。

First why would you use transform when you are merely moving the object. 首先,为什么只移动对象时要使用变换。 You can set the frame just as easily. 您可以轻松设置框架。

CGRect frame = introScreen.frame;
frame.origin.x -= 320;
introScreen.frame = frame;

(Yes this will work inside an animation) (是的,这将在动画中起作用)

second, if you translate a view its contents should be within its bounds regardless of the size you want displayed in the first place. 其次,如果您翻译视图,则其内容应在其范围之内,而不管您要首先显示的大小如何。

therefore your container view (the one with the buttons) should be a size so that all contained pieces are within its bounds. 因此,您的容器视图(带有按钮的视图)应具有一定的大小,以便所有包含的块都在其范围之内。 Anything outside its bounds will not function. 任何超出其范围的内容均将不起作用。 Having the main view twice its size is not as useful as having the contained view at twice its size. 使主视图的大小是其两倍,不如使包含视图的大小为其两倍。

Think of it like this. 这样想吧。

Your table should be able to hold whatever your looking at. 您的桌子应该能够容纳您所看的东西。 If you have a map you want to display you would slide it around on the table. 如果您有要显示的地图,则可以在桌子上滑动它。 the table does not need to be as big as the map but the map needs to be big enough to present you with all of its contents. 表格的大小不必与地图一样大,但是地图必须足够大以向您展示其所有内容。 if the map was say too short to display the poles and you would be without the information. 如果说地图太短而无法显示极点,那么您将没有信息。 No matter how much you transformed the map you would not be able to use the north or south poles.. 无论您变换了多少地图,都将无法使用北极或南极。

To ensure the app reflects this you can turn on clip subviews on all the views in question, then if its outside the bounds it will not be visible. 为了确保应用程序能够反映这一点,您可以在所有有问题的视图上打开剪辑子视图,然后,如果它在边界之外,则将不可见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM