开发者

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

  1. like in sess开发者_运维问答ion 104 I defined levelsOfDetail as 4
  2. 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)???

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜