简体   繁体   中英

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. I've made the size of the main UIView twice bigger than the usual. It is 640x480 instead of 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. Everything works perfect apart the fact i can't get the UIView back to the original position. 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.

My UIView is referenced as "introScreen", and the following is the function i call to translate the screen through the x direction:

- (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. 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. 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; 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. That view becomes the hit-test view.

You could use something like this in your custom 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. (You could also use separate .h/.m files, but for the sake of testing if everything works, it is enough). Then, replace UIView with MyView in the instantiation of your current UIView , and it should work.

You're not using the transform property properly, you should take into account the previous value of the property like this:

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

Hope this helps, and check Apple's UIView documentation and CGAffineTransform documentation for more details.

2 things.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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