简体   繁体   中英

touchEvent for subview in UIScrollView

All,

I have an issue and I have looked at all possible answers on StackOverflow (and other internet) but all solutions I try, nothing works....

I have a UIScrollView with a UIImageView as subview to create a board. I can zoom in and out, works fine. Also scrolling works fine!

Now, I want to drag & drop other UIImageViews (tiles) into the ScrollView and also OUT of the ScrollView. But when I drop the UIImageView in the ScrollView, I can not drag/drop the subview.

I have set the setCanCancelContentTouches:NO of the UIScrollView in the viewDidLoad.
I have created a subclass TileImageView and in the init I set the exclusiveTouch to YES.
NB: the boardImage is a 'normal' UIImageView', the tiles are with the subclass!

Addition: when I set the UserInteraction setting of the boardImage to NO, it the ScrollView zooms but touchBegan is not recorded. If I set it to YES, the ScrollView does not zoom, but the touchBegan is recorded..

So I leave it so I can zoom, but the Tiles are not draggable anymore once they are in the ScrollView.
What am I doing wrong? Or what am I missing?

PS: setting the delaysContentTouches property makes scrolling inactive, so that is also not a solution...

Code: RootViewController_iphone.m

@implementation RootViewController_iphone

@synthesize boardScrollView;
@synthesize dragObject;
@synthesize boardImage;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    UIImage *image = [UIImage imageNamed:@"greyblue_numbered_15x15_900x900.png"];
    self.boardImage = [[UIImageView alloc] initWithImage:image];
    self.boardImage.frame = (CGRect){.origin=CGPointMake(0.0f, 0.0f), .size=image.size};
    [self.boardScrollView addSubview:self.boardImage];

    self.boardImage.userInteractionEnabled = YES;

    self.boardScrollView.contentSize = image.size;
    self.boardScrollView.userInteractionEnabled = YES;
    self.boardScrollView.canCancelContentTouches = NO;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] == 1) {
    // one finger

    CGPoint touchPoint = [[touches anyObject] locationInView:self.view];

    for (UIImageView *iView in self.view.subviews) {
        if ([iView isMemberOfClass:[TileImageView class]]) {
            if (touchPoint.x > iView.frame.origin.x &&
                touchPoint.x < iView.frame.origin.x + iView.frame.size.width &&
                touchPoint.y > iView.frame.origin.y &&
                touchPoint.y < iView.frame.origin.y + iView.frame.size.height)
            {
                self.dragObject = iView;
                self.touchOffset = CGPointMake(touchPoint.x - iView.frame.origin.x,
                                               touchPoint.y - iView.frame.origin.y);
                self.homePosition = CGPointMake(iView.frame.origin.x,
                                                iView.frame.origin.y);
                [self.view bringSubviewToFront:self.dragObject];
            }
        }
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint touchPoint = [[touches anyObject] locationInView:self.view];

    CGRect newDragObjectFrame = CGRectMake(touchPoint.x - touchOffset.x,
                                           touchPoint.y - touchOffset.y,
                                           self.dragObject.frame.size.width,
                                           self.dragObject.frame.size.height);
    self.dragObject.frame = newDragObjectFrame;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
    NSString *tmp = touch.view.description;

    CGPoint touchPointScreen = [[touches anyObject] locationInView:self.view];
    CGPoint touchPointImage = [[touches anyObject] locationInView:self.boardImage];
    CGPoint touchPointBoard = [[touches anyObject] locationInView:self.boardScrollView];

    if (touchPointScreen.x > self.boardScrollView.frame.origin.x &&
        touchPointScreen.x < self.boardScrollView.frame.origin.x + self.boardScrollView.frame.size.width &&
        touchPointScreen.y > self.boardScrollView.frame.origin.y &&
        touchPointScreen.y < self.boardScrollView.frame.origin.y + self.boardScrollView.frame.size.height)
        {
        self.dragObject.frame = CGRectMake(touchPointImage.x - touchOffset.x,
                                           touchPointImage.y - touchOffset.y,
                                           self.dragObject.frame.size.width,
                                           self.dragObject.frame.size.height);

         [self.boardImage addSubview:self.dragObject]; // add to image


        }
}

Code: TileImageView.m

@implementation TileImageView:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.exclusiveTouch = YES;
    }
    return self;
}

You already have subclassed UIImageView, so you can do the following inside your subclass:
1- Override touchsBegan, didEnd, and didMove
2- inside these methods pass them to the superview which is UIScrollView : [ self.superview touchsBegan .... ]
3- If your UIImageView not receiving these messages then in init add self.userInteractionEnabled = YES; Hopefully this going to help you

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