Adding custom UIViews to a UIScrollview - how to c

2019-07-22 00:36发布

问题:

As an iOS newbie I'm trying to develop a (yet another) word game.

I have a UIScrollView holding an UIImageView with the board image.

The UIScrollView can be zoomed by double tap and pinch gestures:

Underneath the UIScrollView I have 7 draggable UIViews representing letter tiles.

The implementation in Tile.m handles dragging with touchesBegan, touchesMoved and posts a notification in touchesEnded.

The single view controller ViewController.m observes this notification and adds/removes the tile to/from the UIScrollView by the following code:

- (void) handleTileMoved:(NSNotification*)notification {
    Tile* tile = (Tile*)notification.object;

    if (tile.superview != _scrollView && 
        CGRectIntersectsRect(tile.frame, _scrollView.frame)) {

        [tile removeFromSuperview];
        [_scrollView addSubview:tile];
        tile.frame = CGRectMake(tile.frame.origin.x + _scrollView.contentOffset.x,
                                tile.frame.origin.y + _scrollView.contentOffset.y,
                                kTileWidth * _scrollView.zoomScale,
                                kTileScale * _scrollView.zoomScale);

    } else if (tile.superview == _scrollView &&
               !CGRectIntersectsRect(tile.frame, _scrollView.frame)) {

        [tile removeFromSuperview];
        [self.view addSubview:tile];
        [self adjustFrames];
    }
}

This kind of works, but I have 2 problems -

Problem 1: How to calculate the position and size of the letter tile, when I am adding it to the scroll view?

Are there any comfortable functions provided by iOS for that purpose or do I have to calculate those values manually (as shown in my code above)?

Problem 2: When I zoom the image view (the game board), then the letter pieces placed on it don't zoom. Probably because of this method?

- (UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView
{
    return _imageView;
}

How to fix this problem? I can't return several objects by the above method

UPDATE:

I have branched my app on GitHub and inserted a contentView between the scrollView and imageView (here fullscreen):

Zooming the image and the tiles works then, but I can't scroll anymore.

I've printed out the contentSize and it seem to be okay with 1000x1000:

-[ViewController viewDidLoad]: image {1000, 1000}
-[ViewController viewDidLayoutSubviews] contentOffset={0, 0} contentSize={1000, 1000}
tile: N 9 {2, 433} {45, 45}
tile: V 1 {47, 433} {45, 45}
tile: L 9 {92, 433} {45, 45}
tile: R 4 {137, 433} {45, 45}
tile: B 7 {182, 433} {45, 45}
tile: B 8 {227, 433} {45, 45}
tile: M 5 {272, 433} {45, 45}
-[ViewController adjustZoom]: scrollView origin={0, 0} size={320, 431} minScale=0.320000 zoomScale=0.640000 maxScale=0.640000
-[ViewController adjustZoom]: imageView origin={0, 0} size={1000, 1000}
-[ViewController adjustZoom]: contentView origin={0, 0} size={640, 640}

I've tried changing _scrollView.canCancelContentTouches and _scrollView.translatesAutoresizingMaskIntoConstraints.

Also I've tried changing the interactivity checkbox of the UIImageView in Interface Builder, but it hasn't helped.

I couldn't figure out the problem by using Reveal app either (here fullscreen):

回答1:

Problem 2: Use your new contentView as superview for the board and the pieces. That way the position and the size of the pieces in the board coordinates will be independent of the zoom and pan applied to the contentView.

Problem 1: There is no longer problem 1!



回答2:

for the problem 1:

there is two property of UIScrollView

 UIScrollView* sc = [[UIScrollView alloc] init];
 CGPoint pt = sc.contentOffset;
 CGFloat scale = sc.zoomScale;

and for the second problem I recommend scaling the letterImage while dragging and when it comes to placing on board place it with original size scrollview will show it good