如何在超级视图转换后找到UIView的中心?

时间:2014-07-18 00:51:35

标签: ios uiview cgaffinetransform

注意:用浏览器编写的代码;可能不完全准确,但它应该给出一般的想法。

我有一堆意见,如下:

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

这里有一些代码给出了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。事实证明他们都给出了相同的结果,但它有点过时了。

希望澄清图片:

enter image description here

2 个答案:

答案 0 :(得分:2)

您可以使用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中的接收者:呼叫。

答案 1 :(得分:1)

当我需要在不同层之间转换点时,我尝试让iOS为我做重任务。

CGPoint point = v3.center;
CGPoint ctr3 = [v3.layer.presentationLayer convertPoint:point toLayer:self.layer.presentationLayer];

表示层对象表示当前在屏幕上显示的图层的状态。如果涉及动画,这可以帮助避免计时问题。

刚刚注意到我作曲时出现的评论:是的,我用它来说明与你描述的类似的旋转变换。