views:

130

answers:

2

I'm using a UIScrollView to hold a varying number of images sized at 80x80, and when a user taps one I want it to launch into a modal view showing it fullscreen etc. The problem I'm having is detecting touches on the images inside the scrollview. I've tried two ways so far, but each one has an issue. I'm posting both ways but I only need an answer to one of them.

I have an array of images and loop through it, this is the first method I tried using a UIImageView for each one:

for (i=0; i<[imageArray count]; i++) {
    // get the image
    UIImage *theImage = [imageArray objectAtIndex:i];

    // figure out the size for scaled down version
    float aspectRatio = maxImageHeight / theImage.size.height;
    float thumbWidth = theImage.size.width * aspectRatio;
    float thumbHeight = maxImageHeight;

    lastX = lastX+10;

    // Scale the image down
    UIImage *thisImage = [theImage imageByScalingProportionallyToSize:CGSizeMake(thumbWidth, thumbHeight)];

    // Create an 80x80 UIImageView to hold the image, positioned 10px from edge of the previous one
    UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(lastX, 10, 80, 80)];
    image.clipsToBounds = YES;
    image.contentMode = UIViewContentModeTopLeft;
    image.image = thisImage;
    image.userInteractionEnabled = YES;

    // add to the scroller
    [photoScroller addSubview:image];

    // release
    [image release];

    // set variables ready for the next one
    //lastWidth = thisImage.size.width;
    lastWidth = 80;             // we're using square images so set to 80 rather than the width of the image
    lastX = lastX+lastWidth;
}

The problem this causes is that after this loop I have to set userInteractionEnabled to NO on the UIScrollView so I can override touchesBegan and detect touches, but doing this of course disables scrolling so the user can only see the first 6 images or so.

Is there a way I can re-enable scrolling so to speak? photoScroller.scrollEnabled = YES; has no effect since user interaction has been disabled.

...

The second way I tried was using a UIButton for each image, the code for the loop in this case is as follows:

for (i=0; i<[imageArray count]; i++) {
    // get the image
    UIImage *theImage = [imageArray objectAtIndex:i];

    // figure out the size for scaled down version
    float aspectRatio = maxImageHeight / theImage.size.height;
    float thumbWidth = theImage.size.width * aspectRatio;
    float thumbHeight = maxImageHeight;

    lastX = lastX+10;

    // Scale the image down
    UIImage *thisImage = [theImage imageByScalingProportionallyToSize:CGSizeMake(thumbWidth, thumbHeight)];

    // Create an 80x80 UIButton to hold the image, positioned 10px from the edge of the previous one
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(lastX, 10, 80, 80)];
    button.clipsToBounds = YES;
    button.contentMode = UIViewContentModeTopLeft;
    [button setImage:thisImage forState:UIControlStateNormal];
    [button setImage:thisImage forState:UIControlStateHighlighted];
    [button addTarget:self action:@selector(tapImage:) forControlEvents:UIControlEventTouchUpInside];

    // add to the scroller;
    [photoScroller addSubview:button];

    // release
    [button release];

    // set variables ready for the next one
    //lastWidth = thisImage.size.width;
    lastWidth = 80;             // we're using square images so set to 80 rather than the width of the image
    lastX = lastX+lastWidth;
}

Now this code works almost perfectly, the only problem is that the user can only scroll if they touch in whitespace.

Is there a way I can make it so if a user is dragging on the UIButton it will still scroll the UIScrollView?

+1  A: 

The UIScrollView has a property called delaysContentTouches. This is set to YES by default, which results in the behaviour that you want: dragging always works, even if you tap on for example a UIButton.

So, if you do not see that behaviour then maybe you have set delaysContentTouches to NO?

Also, instead of using UIImageViews in your scrollview, and overriding their touchedBegan: and friends, it is probably much easier to simply use UIButtons instead.

You can simply set the button's image to whatever you want, and you do not have to subclass them. Simply use addTarget: to make the buttons do a callback to your viewcontroller when they are clicked. (This is the same as making a connection to an IBAction using Interface Builder)

St3fan
A: 

Turned out to be a bit of a non-issue in the end, I used UIButtons in case anyone was wondering, all seems to work as expected and as I wanted it to.

The issue I had with scrolling the UIScrollView appeared to fix itself after altering some of the code, not entirely sure what was causing the problem - it wasn't even an issue when used on an actual device.

ChrisJP