A very simple UIScrollView demo

I was tinkering with UIScrollView a while back, just doing a simple demo to understand how to use the API. Here’s a summary of what I learned (some with the help of Apple DTS).

I wanted to get the pinch scrolling to work so that I could pan around an image. For my sample graphic, I grabbed the Quartz sample code from another Apple sample, just to have something to draw. I dropped a UIScrollView onto my nib, and defined (in code) a StarView class to draw those graphics. At launch time (in applicationDidFinishLaunching), I create an instance of StarView and drop it onto the UISCrollView:

	starView = [[StarView alloc] initWithFrame:CGRectMake(0., 90., 500., 500.)];
	starViewScale = 1.0;
	[scrollView addSubview:starView];

02 -0700-1.png

When I zoomed in, the image was very blurry. It was being drawn at the same pixel resolution used when zoomed out:

39 -0700-1.png

I was missing a couple of key points. First, use a CATiledLayer as the layer class for my Starview:

@implementation StarView

+(Class)layerClass
{
	return [CATiledLayer class];
}

Second, I need to trigger a redraw of the image when the zoom level changes. Do this with levelsOfDetailBias and levelsOfDetail:

- (id)initWithFrame:(CGRect)frame {
	if (self = [super initWithFrame:frame]) {
		CATiledLayer *animLayer = (CATiledLayer *) self.layer;
		animLayer.levelsOfDetailBias = 4;
		animLayer.levelsOfDetail = 4;
	}
	return self;
}

Here’s the nice crisp rendering after those changes:

43 -0700-1.png

You can download the demo at http://www.mobilegeographics.com/dev/StarZoom2.zip. Note that that code is still not great. The zoom limits are fixed, but should be dynamic. And the view is completely redrawn each time a small subrectangle is requested, which defeats the purpose of the tiling, at least as far as speed goes.

You’ll also see a bug in my line width control:

	// Draw them with a 2.0 stroke width so they are a bit more visible.
	CGFloat width = 2. / [(AppDelegate *)[[UIApplication sharedApplication] delegate] starViewScale];

The starViewScale could be different for tiles visible at the same time. The line width should actually be pegged to the scale’s levelOfDetail/levelOfDetail bias. It should return discrete values based on powers of 2, and not be continuous as it is in the demo.

Finally, other authors have noted that there’s no way to control the scale of the view when it appears. The scale factor is always 1.0. I’ve tried setting the UIScrollView’s min/max zoom scale to a range that excludes 1.0, like this (from applicationDidFinishLaunching):

	scrollView.maximumZoomScale = 50.;
	scrollView.minimumZoomScale = 5.;

When I do that, the view appears with scale factor 1.0 and then jumps to 5.0 when I do the first pinch zoom. If you need to control the scale factor, you’ll have to use a shadow scale factor yourself, and then rescale everything by that shadow scale to accommodate a zoom scale of 1.0 on each view initialization.

Enjoy the sample.

About these ads

5 Responses to A very simple UIScrollView demo

  1. Thanks for the tutorial, it was a big help!

  2. Benjamin King says:

    In your last paragraph you mention setting up a “shadow scale.” Could you please provide some more details and give an example? I’m getting stuck with that same problem. My content view has a scaled of 0.4 and when you do the first pinch it scales it up to 1.0. Any help will be greatly appreciated. Thanks.

  3. Allen says:

    Thanks man, it helped a lot!

  4. meronix says:

    thanks for your tutorial.

    “… there‚Äôs no way to control the scale of the view when it appears …”

    for your startScale problem, i solved this way:

    starViewScale = 10.0;
    [scrollView addSubview:starView];
    scrollView.zoomScale = starViewScale;

    luca

Follow

Get every new post delivered to your Inbox.