簡體   English   中英

如何在超級視圖轉換后找到UIView的中心?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM