iOS坑:UIView的frame和transfrom

econi發表於2013-09-17

最近一直在做photoGrid的iOS版本的開發,遇到過很多問題。
目前我的UIView裡有一個UIImageView。
這裡的UIImageView的狀態初始是這樣的:

_imageView = [[UIImageView alloc] init];
_imageView.frame = self.bounds;
_imageView.contentMode = UIViewContentModeScaleAspectFill;
_imageView.autoresizingMask = (UIViewAutoresizingFlexibleHeight |
                               UIViewAutoresizingFlexibleWidth  |
                               UIViewAutoresizingFlexibleTopMargin |
                               UIViewAutoresizingFlexibleLeftMargin|
                               UIViewAutoresizingFlexibleRightMargin |
                               UIViewAutoresizingFlexibleBottomMargin);

因為這個是拼圖軟體,座標都是計算轉換出來的,難免有浮點,而iOS支援的座標最小是 0.5f 的精度。在對外面的UIView和內部的ImageView的座標都進行設定後,我們發現圖片和圖片之間會有明顯的縫隙,這是為什麼呢?

系統會對UIImageView的座標進行優化,會成為整型,這樣我們就看到了Image和Image之間的明顯的縫隙了。

那麼如何解決呢?
很簡單,設定一下UIImageView的frame

_imageView.frame = self.bounds;

但是這樣做帶來了別的問題。

因為我在這裡有對這個UIImageView的仿射矩陣做(transform)變換以達到位移、放縮等效果。如果在設定了frame之後再對這個UIImageView做改變仿射矩陣操作,你會發現之前的效果被重置了,如果此時你再去做放縮等操作,都是在原來的基礎上再做的變化。
比如,之前你縮小到0.5倍,然後你會發現圖片會重置到ScaleAspectFit,然後再縮小到0.5倍,此時的仿射矩陣的倍率值(transform.a)就是0.25了,而肉眼觀察到的則是0.5倍的縮放。
哪兒有問題呢?

最後終於在API Document裡面找到這麼一小段話

// animatable. do not use frame if view 
// is transformed since it will not correctly 
// reflect the actual location of the view. use bounds + center instead.

// 動畫屬性。不要在view變形之後使用frame
// 否則會導致其不能正確的對映出view的真實位置。用bounds + center 代替

好吧,一切釋然了,我檢查了好久的bug居然只是一句小小的註釋就解決了。

//_imageView.frame = self.bounds;
_imageView.bounds = self.bounds;
_imageView.center = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);

OK,正常了!

相關文章