CATiledLayer gets a incorrect frame & contextCTM.a value (zoomScale)
following WWDC2010 Session 104 I just created a CATiledLayer within a UIScrollView
for a 10000 x 8078 px image.
I am troubled with the frame & zoomScale
when the view is first shows at its top level
- like in sess开发者_运维问答ion 104 I defined
levelsOfDetail
as 4 - in my drawRect I call
CGFloat lScale = CGContextGetCTM(lContext).a;
Strangely at runtime lScale is assigned 0.124907158, not 0.125 as expected.
As well the rect
passed to drawRect
has floatpoint values, such as
- rect.origin.x = 4099.04443
- rect.origin.y = 6144
- rect.size.width = 2049.52222
- rect.size.height = 2048
Most irritating for me is that the frame of the CATiledLayer
shows an origin 0 x 26.93 even though I created the tiledImageView using initWithFrame
using a 0x0 origin.
Any ideas where I can find the calculation that is responsible for this?
EDIT: I found the source for the wierd frame position, which is the ScrollView bounds being incorrectly set at 450 px. that should be 420 px. The layoutSubview routine in the UIScrollView has a center view routine that inadvertently adjusted the y coordinate.
I found a cure to this.
The WWDC 2010 session 104 sample has two UIScrollView
methods that control the view behaviour.
The first is configureForImageSize
that I mentioned in my previously posted answer where the zoomscales are set.
Due to the explained float-point difference the imageView-bounds get generated with the decimals as highlighted before (see wx/hx or wy/hy).
To get clean this up I used the override of layoutSubviews
where I calculate the view frame:
- (void) layoutSubviews {
[super layoutSubviews];
CGSize lBoundsSize = self.bounds.size;
CGRect lFrameToCenter = imageView.frame;
// cure to the decimals problem
lFrameToCenter.size.width = roundf(lFrameToCenter.size.width);
lFrameToCenter.size.height = roundf(lFrameToCenter.size.height);
if (lFrameToCenter.size.width < lBoundsSize.width)
lFrameToCenter.origin.x = (lBoundsSize.width - lFrameToCenter.size.width) / 2;
else
lFrameToCenter.origin.x = 0;
if (lFrameToCenter.size.height < lBoundsSize.height)
lFrameToCenter.origin.y = (lBoundsSize.height - lFrameToCenter.size.height) / 2;
else
lFrameToCenter.origin.y = 0;
imageView.frame = lFrameToCenter;
if ([imageView isKindOfClass:[tileView class]]) {
imageView.contentScaleFactor = 1.0;
}
}
Note that I round the frame size before doing anything else with it!
I got a little further in my bug analysis.
Having an mImageSize of 10000x8078 and 320x450 Bounds in the UIScrollView
I used the configureForImageSize
calculations from the session 104 example as follows:
- (void) configureForImageSize:(CGSize)mImageSize {
CGSize lBoundsSize = [self bounds].size;
// set up our content size and min/max zoomscale
CGFloat lXScale = lBoundsSize.width / mImageSize.width; // the scale needed to perfectly fit the image width-wise
CGFloat lYScale = lBoundsSize.height / mImageSize.height; // the scale needed to perfectly fit the image height-wise
// debug values
float wx = mImageSize.width * lXScale;
float wy = mImageSize.width * lYScale;
float hx = mImageSize.height * lXScale;
float hy = mImageSize.height * lYScale;
...
}
The debugger shows the following values:
* mImageSize = width 10000 height 8078
* bounds size: width 320 height 450
* lXScale = 0.0396137647
* lYScale = 0.0450000018
* wx = 320
* wy = 363.51001
* hx = 396.137634
* hy = 450.000031
so I gather the image size in relation to the bounds leads to a floatpoint calculation difference. When the CATiledLayer
is generated the bounds are alway floatpoint values.
If that is the cause, how can I get a mathematical way out of this without having to resize the image (ugly thought)???
精彩评论