[英]How to find the center of a UIView after superviews have been transformed?
注意:用瀏覽器編寫的代碼; 可能不完全准確,但它應該給出一般的想法。
我有一堆意見,像這樣:
CGRect theFrame = CGRectMake(0, 0, 10, 10);
UIView *v1 = [UIView alloc] initWithFrame: theFrame];
UIView *v2 = [UIView alloc] initWithFrame: theFrame];
UIView *v3 = [UIView alloc] initWithFrame: theFrame];
// Set all the background colors, so I can see them: snip
// set all the clipsToBounds = NO, so I can place however I want: snip
v2.center = CGPointMake(100, 80);
[v1 addSubview: v2];
v3.center = CGPointMake (57, 42);
[v2 addSubview: v3];
v1.center = CGPointMake (193, 44);
[self.view addSubview: v1];
// etc., time passes, user presses TEST button
CGAffineTransform sXfrm = CGAffineTransformMakeScale(3.5, 4.7);
CGAffineTransform rXfrm = CGAffineTransformMakeRotation(M_PI / 3.);
v1.transform = CGAffineTransformConcat(sXfrm, rXfrm);
// etc., rotate & scale v2, while we're at it. snip
// Leave v3 unrotated & unscaled.
好的,此時,所有內容都完全按照需要顯示在屏幕上。 我的問題是:
哪里(即:在v3.center
的坐標空間中的v3.center
)是v3.center
?
這里有一些代碼給出了CLOSE答案,但不是很正確,我似乎無法弄清楚它有什么問題:
CGRect testRect = CGRectMake(0, 0, 20, 20);
UIView *testView = [[UIView alloc] initWithFrame: testRect];
testView.backgroundColor = [UIColor greebColor];
[self.view addSubview: testView];
CGPoint center = v1.center;
#if 1 // Apply Transform
CGPoint ctr2 = CGPointApplyAffineTransform(v2.center, v1.transform);
#else // use layer
CGPoint ctr2 = CGPointMake ((v2.layer.frame.origin.x + (v2.layer.frame.size.width / 2.)),
(v2.layer.frame.origin.y + (v2.layer.frame.size.height / 2.)) );
ctr2 = CGPointApplyAffineTransform(ctr2, v1.transform);
#endif
center.x += ctr2.x;
center.y += ctr2.y;
CGPoint ctr3 = CGPointApplyAffineTransform(v3.center, CGAffineTransformConcat(v2.transform, v1.transform));
center.x += ctr3.x;
center.y += ctr3.y;
testView.center = center; // I want this to lay on top of v3
[self.view addSubview: testView];
注意:在我的實際代碼中,我在所有中間中心放置了測試視圖。 我得到的是:testView1(中心)是正確的,testView2(ctr2)稍微關閉,testView3(ctr3)關閉了一點。
#if
是因為我正在嘗試使用ApplyAffine vs layer。 事實證明他們都給出了相同的結果,但這有點過時了。
希望澄清圖像:
您可以使用UIView的轉換點方法:
convertPoint:toView:
convertPoint:fromView:
convertRect:toView:
convertRect:fromView:
但是,一旦你應用了轉換,你應該停止使用框架並使用中心+邊界(這可能是你的代碼不起作用的原因),來自apple docs(for frame):
警告:如果transform屬性不是identity變換,則此屬性的值未定義,因此應忽略。
您必須要注意的唯一另一件事是,自結果發生變化以來,哪個視圖會將轉換設置為其他視圖。 (源坐標系 - >目標坐標系。)
編輯:
感謝這個答案和Chiquis在問題中的評論,我的(Olie's)最終(工作)代碼如下所示:
CGRect testRect = CGRectMake(0, 0, 20, 20);
UIView *testView[3];
for (int ii = 0 ; ii < 3 ; ++ii)
{
testView[ii] = [[UIView alloc] initWithFrame: testRect];
testView[ii].backgroundColor = [UIColor redColor];
[self.view addSubview: testView[ii]];
}
testView[0].center = v0.center;
testView[1].center = [v0 convertPoint: v1.center toView: self.view];
testView[2].center = [v1 convertPoint: v2.center toView: self.view];
為了澄清一些,v1是v0的子視圖,v2是v1的子視圖; 這決定了covertPoint中的接收者:呼叫。
當我需要在不同層之間轉換點時,我嘗試讓iOS為我做繁重的工作。
CGPoint point = v3.center;
CGPoint ctr3 = [v3.layer.presentationLayer convertPoint:point toLayer:self.layer.presentationLayer];
表示層對象表示當前在屏幕上顯示的圖層的狀態。 如果涉及動畫,這可以幫助避免計時問題。
剛剛注意到我在編寫時出現的評論:是的,我使用它來考慮類似於你描述的旋轉變換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.