注意:用浏览器编写的代码;可能不完全准确,但它应该给出一般的想法。
我有一堆意见,如下:
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。事实证明他们都给出了相同的结果,但它有点过时了。
希望澄清图片:
答案 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];
表示层对象表示当前在屏幕上显示的图层的状态。如果涉及动画,这可以帮助避免计时问题。
刚刚注意到我作曲时出现的评论:是的,我用它来说明与你描述的类似的旋转变换。