子视图相对于父 UIView 的起源

Posted

技术标签:

【中文标题】子视图相对于父 UIView 的起源【英文标题】:Origin of subviews relative to parent UIView 【发布时间】:2014-04-14 07:34:30 【问题描述】:

我在父视图中定位两个子视图时遇到了麻烦。它们旨在包含一个基本的动画条形图,并且动画部分似乎运行良好。同样,相应的条形似乎准确地反映了数据。

但是,我试图将两个视图的原点基于父视图的下边缘(屏幕截图中的灰色区域),结果似乎是随机的。我希望它不是真正随机的,但我无法确定它。

代码如下:

-(void) makeBarChart

RiserBar *thisRiser;

for(int i=0; i<2; i++)

    thisRiser = [[RiserBar alloc] initWithFrame:CGRectZero];
    thisRiser.tag = i+1;
    [self.chartView addSubview:thisRiser];
//    [self placeAndAnimateThisBar];


int barWidth = self.chartView.bounds.size.width /((2 * 2) -1);
int focusBarEndHeight = (self.chartView.bounds.size.height-20) * (focusActivityPercent / 100);
int benchmarkBarEndHeight = (self.chartView.bounds.size.height-20) * (benchmarkActivityPercent / 100);

for (thisRiser in self.chartView.subviews)

    switch (thisRiser.tag)
    
        case 1:
         [UIView animateWithDuration:1
                                  delay:.2
                                options: UIViewAnimationCurveEaseOut
                             animations:^
             
                 thisRiser.frame = CGRectMake(20, self.chartView.frame.origin.y, barWidth, 0);
                 thisRiser.backgroundColor = [UIColor blackColor];
                 thisRiser.frame = CGRectMake(20, self.chartView.frame.origin.y, barWidth, -focusBarEndHeight);
                 thisRiser.backgroundColor = [UIColor redColor];
             
                             completion:^(BOOL finished)
             
                 NSLog(@"Done!");
             ];
        
            break;
        case 2:
        
            [UIView animateWithDuration:1
                                  delay:.2
                                options: UIViewAnimationCurveEaseOut
                             animations:^
             
                 thisRiser.frame = CGRectMake(barWidth + 40, self.chartView.frame.origin.y, barWidth, 0);//load frame from data
                 thisRiser.backgroundColor = [UIColor blackColor];
                 thisRiser.frame = CGRectMake(barWidth + 40, self.chartView.frame.origin.y, barWidth, -benchmarkBarEndHeight);
                 thisRiser.backgroundColor = [UIColor blueColor];
             
                             completion:^(BOOL finished)
             
                 NSLog(@"Done!");
             ];
        
            break;
        case 3:
            //do something to the view
            break;
            //and so on...
        default:
            break;
    



以及生成的屏幕截图:

我应该提到,红色和蓝色条的意图是从灰色父视图的底部开始并上升。我并不完全清楚为什么我必须反转.heightproperty 的极性来实现这一点。鉴于此代码,为什么原点位于父视图中间附近?

谁能指出我的错误?

谢谢!

根据答案 2 中 @Rob 的温和指导进行编辑:

这是我代码相关部分的更改,也受到this slideshow 中信息的影响,我强烈推荐给像我一样喜欢图片而不是详细解释的任何人:

switch (thisRiser.tag)

    case 1:
     [UIView animateWithDuration:1
                              delay:.2
                            options: UIViewAnimationCurveEaseOut
                         animations:^
         
             thisRiser.frame = CGRectMake(20, self.chartView.frame.size.height, barWidth, 0);
             thisRiser.backgroundColor = [UIColor blackColor];
             thisRiser.frame = CGRectMake(20, self.chartView.frame.size.height, barWidth, -focusBarEndHeight);
             thisRiser.backgroundColor = [UIColor redColor];
         
                         completion:^(BOOL finished)
         
             NSLog(@"Done!");
         ];
    
        break;
    case 2:
    
        [UIView animateWithDuration:1
                              delay:.2
                            options: UIViewAnimationCurveEaseOut
                         animations:^
         
             thisRiser.frame = CGRectMake(barWidth + 40, self.chartView.frame.size.height, barWidth, 0);//load frame from data
             thisRiser.backgroundColor = [UIColor blackColor];
             thisRiser.frame = CGRectMake(barWidth + 40, self.chartView.frame.size.height, barWidth, -benchmarkBarEndHeight);
             thisRiser.backgroundColor = [UIColor blueColor];
         
                         completion:^(BOOL finished)
         
             NSLog(@"Done!");
         ];
    
        break;
    case 3:
        //do something to the view
        break;
        //and so on...
    default:
        break;

这就是它现在的样子(图中条形高度的差异是由于不同的数据):

再次感谢罗伯!

【问题讨论】:

【参考方案1】:

您有几行类似于以下内容:

thisRiser.frame = CGRectMake(20, self.chartView.frame.origin.y, barWidth, -focusBarEndHeight);

在为其子视图设置框架的上下文中使用frame.origin.yframe.origin.y 是没有意义的。一个与另一个无关。立管的framechartView 内是相对的,与chartVieworigin 无关。

如果您希望thisRiser 位于chartView 的底部,高度为focusBarEndHeight,我可能会这样做:

thisRiser.frame = CGRectMake(20, self.chartView.frame.size.height - focusBarEndHeight, barWidth, focusBarEndHeight);

【讨论】:

谢谢罗伯。您的陈述不太清楚“立管的框架在图表视图中是相对的......”相对于什么?请纠正我,但我认为子视图是贴在窗口上的 PostIt 便笺,其位置由窗口的位置决定。根据您的回答,显然不是,但快速查看文档并没有解决问题。我会学习更多,但如果您有时间,将非常感谢您提供插图。 会尝试你的建议,但我现在远离我的 MBP。 @TimJones 使用您的“PostIt”笔记类比,PostIt 的frame 是它在窗口窗格中的位置。但是窗口的frame 指示窗扇的位置(即窗口是打开还是关闭)。但是您的 PostIt(即立管)的位置是引用窗口(即chartView)的frame.origin.y(即窗口的打开程度)。 PostIt 的位置与窗口的打开程度无关。您只希望它位于窗格的底部,因此您只需要知道窗格的高度和 PostIt 的高度。【参考方案2】:

子视图的实际位置也取决于父视图的 autoresizingmask。 您在定位子视图时也需要考虑同样的问题,或者您可以

【讨论】:

谢谢,山姆。我将研究自动调整大小方面。请参阅上面的更新以解决我的直接问题。

以上是关于子视图相对于父 UIView 的起源的主要内容,如果未能解决你的问题,请参考以下文章

相对于父视图的底部定位 UIView?

找出子视图相对于视图的位置

中心子 QMainWindow 相对于父 QMainWindow

动画起源 iOS

咖啡的起源与传说

子对象相对于父对象的旋转