0

I'm trying to follow this answer to create a paging scrollview that shows the next and previous image.

I created a custom UIView class, and added the UIScrollView as a subview. I'm having two problems.

  1. I want the view to work with IB so I implemented initWithCoder and tried to pass the frame to my init after the call to the superclass initWithCoder. But the frame is always 0 width and height.
  2. To get around this I just used the screen width in my initView method. But my scrollview (or rather the images within) is not displaying. I changed the background colors of the custom view (red) and the scrollview (blue), and all I see is the red background. I've checked the frame rect of the scrollview and it looks reasonable (59, 0, 201, 135), so I'm not sure why I can't get the scrollview to display.

Any thoughts would be appreciated.

ModeSelectView.m

#import "ModeSelectView.h"

@implementation ModeSelectView


- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self initView:frame];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:(aDecoder)];
    if (self) {
        CGRect frame = self.frame;
        [self initView:self.frame];
    }
    return self;
}

- (void)initView:(CGRect)frame
{
    // Initialization code
    // Create an array of images for the different modes
    UIImage *imgTowerOnlyMode = [UIImage imageNamed:@"tower_only_mode_icon.png"];
    UIImage *imgLocalMode = [UIImage imageNamed:@"local_mode_icon.png"];
    UIImage *imgHowToPlay = [UIImage imageNamed:@"how_to_play_icon.png"];
    NSArray *modeSelectIcons = @[imgTowerOnlyMode, imgLocalMode, imgHowToPlay];

    int iconSize = 115;
    // Center to center icon spacing
    int viewSpacing = 115 * 1.75;
    int frameWidth = 2*viewSpacing;
    int contentWidth = 4*frameWidth;
    int pageWidth = viewSpacing;
    int verticalPadding = 10;
    int pageHeight = iconSize + 2*verticalPadding;
        //int viewWidth = frame.size.width;
    int viewWidth = [[UIScreen mainScreen] applicationFrame].size.width;
    int scrollViewX = (viewWidth - pageWidth)/2;

    // Create the scrollview, setting it to be page size in width the icon height plus padding
    CGRect scrollViewFrame = CGRectMake(scrollViewX, 0, pageWidth, pageHeight);
    self.scrollModeSelect = [[UIScrollView alloc] initWithFrame:scrollViewFrame];

    // Now iterate over the array creating a view for each
    // The first view will be offset in X to allow it to be
    // centered in the page
    int imageOffset = (frameWidth-iconSize)/2;
    for (int i = 0; i < [modeSelectIcons count]; ++i) {
        // Get the origin x value for the image view within the scroll view
        int viewOriginX = i*frameWidth + imageOffset;

        // Initialize the image view
        UIImageView *ivModeSelect = [[UIImageView alloc]
        initWithFrame:CGRectMake(viewOriginX , verticalPadding/2,
                                 iconSize, iconSize)];

        // Set the image
        ivModeSelect.image = (UIImage *)modeSelectIcons[i];

        // Tell the parent view to scale the iamge, preserving aspect ratio, to
        // fit the parent view.
        ivModeSelect.contentMode = UIViewContentModeScaleAspectFit;

        // Add the image view to the scroll view
        [self.scrollModeSelect addSubview:ivModeSelect];
    }

    [self.scrollModeSelect setContentSize:CGSizeMake(contentWidth, pageHeight)];
    // Turn off clipping so we can see the adjacent icons
    [self.scrollModeSelect setClipsToBounds:FALSE];

    // Add the scrollview as a subview
    [self addSubview:self.scrollModeSelect];

    [self.scrollModeSelect setBackgroundColor:[UIColor blueColor]];
    [self setBackgroundColor:[UIColor redColor]];
}


/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/

@end
Community
  • 1
  • 1
museofwater
  • 409
  • 5
  • 9

1 Answers1

0

It turns out that you can't really do any view sizing in initWith methods because the application frame hasn't been determined yet. So to do this you need to setup your views in your view hierarchy with default sizes. Then you need to override layoutSubviews to do your sizing. In layoutSubviews you can access your view frame using self.frame. So here is the same code as above, but using the layoutSubviews.

- (void)initView:(CGRect)frame
{
    // Initialization code
    self.ivModeSelectArray = [[NSMutableArray alloc] init];

    // Create an array of images for the different modes
    UIImage *imgTowerOnlyMode = [UIImage imageNamed:@"tower_only_mode_icon.png"];
    UIImage *imgLocalMode = [UIImage imageNamed:@"local_mode_icon.png"];
    UIImage *imgHowToPlay = [UIImage imageNamed:@"how_to_play_icon.png"];
    NSArray *modeSelectIcons = @[imgTowerOnlyMode, imgLocalMode, imgHowToPlay];

    // Create the scrollview, initially setting it to 0 size.  We'll resize it
    // in layoutSubviews
    CGRect scrollViewFrame = CGRectMake(0,0,200,110);
    self.scrollModeSelect = [[UIScrollView alloc] initWithFrame:scrollViewFrame];

    // Now iterate over the array creating a view for each, intially set to 0
    // size.  We'll resize them and reposition them in layoutSubviews
    for (int i = 0; i < [modeSelectIcons count]; ++i) {
        UIImageView *ivModeSelect =
                 [self addModeIcon:[modeSelectIcons objectAtIndex:i]];

        // Add the image view to the scroll view
        [self.scrollModeSelect addSubview:ivModeSelect];
    }

    // Turn off clipping so we can see the adjacent icons
    [self.scrollModeSelect setClipsToBounds:FALSE];

    // Turn on paging
    [self.scrollModeSelect setPagingEnabled:TRUE];

    // Add the scrollview as a subview
    [self addSubview:self.scrollModeSelect];

//    self.scrollModeSelect.backgroundColor = [UIColor blueColor];
//    self.backgroundColor = [UIColor redColor];
}

- (void)layoutSubviews
{
    int iconSize = 115;
    // Center to center icon spacing
    CGFloat viewSpacing = 115 * 1.4;
    int frameWidth = viewSpacing;
    int contentWidth = 4*frameWidth;
    int pageWidth = viewSpacing;
    int verticalPadding = 10;
    int pageHeight = iconSize + 2*verticalPadding;
    int viewWidth = self.frame.size.width;
    int scrollViewX = (viewWidth - frameWidth)/2;

    // Now iterate over the array configuring the size and offset for each view
    // The first view will be offset in X to allow it to be centered in the page
    int imageOffset = (frameWidth-iconSize)/2;
    for (int i = 0; i < [self.ivModeSelectArray count]; ++i) {
        // Get the origin x value for the image view within the scroll view
        int viewOriginX = i*viewSpacing + imageOffset;

        // Size the image view
        UIImageView *ivModeSelect = [self.ivModeSelectArray objectAtIndex:i];
        [ivModeSelect setFrame:CGRectMake(viewOriginX , verticalPadding/2,
                                          iconSize, iconSize)];

    }

    [self.scrollModeSelect setFrame:CGRectMake(scrollViewX, 0,
                                               pageWidth,pageHeight)];
    [self.scrollModeSelect setContentSize:CGSizeMake(contentWidth, pageHeight)];
}
museofwater
  • 409
  • 5
  • 9