scrollview仅显示最后添加的子视图

时间:2013-04-22 23:03:20

标签: ios objective-c uiscrollview

我对UIScrollView子视图的行为很奇怪,我的想法是以编程方式创建UIView的实例,其中包含一个自定义的nib文件,在我的情况下是一个表单,用来自a的数据填充该表单模型类,并将其添加为我的UIScrollView的子视图。 问题是当我处理多个子视图时,UIScrollView仅保留最新的子视图,因此如果我创建了三个子视图,则scrollview将仅显示第三个(最新的)子视图。虽然页面控件设置为核心数量的子视图(三个)。

项目太长了,所以我会尝试用相关的代码解释我的问题:

- (void)viewDidLoad {

    NSArray *sorted = [appArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];//this array contains the data from model, I debugged that to make sure I got the exact data, no more no less :)


    //Loop all NSManaged objects, for example let's say I have 3 model objects, don't worry about how I get data etc, because I debugged all and maked sure all data objects number are exact, etc.
    for (App_Table *_appTable in sorted) {
    //This looped 3 times as expected, I debugged that also and maked sure on each iteration I got the data I expected to have
    //App_Table is a subclass of NSManagedObject, it's my model class and get its data from coredata file
    [self addMoreView];//Call this method will create a new subview and add it as subview to the UIScrollView, it will also update the page control, update the content size property, etc.

    AppTableView *_appTableView = (AppTableView *) [[self.scrollView subviews] lastObject];//Remember addMoreView method create a new instance of AppTableView and add it as subview for the UIScrollView property, then I get that subview to fill it with data here

    _appTableView.txtADDRESS.text = _appTable.address;//Fill in the form, no need to write all the form fields code because it's the same way.

    // Scroll To First Page...
    self.pageControl.currentPage = 0;
    [self.scrollView scrollRectToVisible:CGRectMake(0, 0, viewWidth, viewHeight) animated:YES];

    self.scrollView.contentSize = CGSizeMake(viewWidth*noOfItems, viewHeight);//Set the content size to the sum of subviews width, I also debugged that to check it's correct
    self.scrollView.delegate = self;

    [super viewDidLoad];
}

好的,所以当我有三个子视图时,滚动视图将加载三个子视图的宽度,如上面的行计算:

self.scrollView.contentSize = CGSizeMake(viewWidth*noOfItems, viewHeight);//Set the content size to the sum of subviews width, I also debugged that to check it's correct

我可以滚动到3个移动(这是子视图的数量),UIPageControl也设置为三个点,但只有一个子视图可见,只有最新的一个我可以看到,其他两个子视图消失了,滚动视图计算了它们的内容大小但是它们不可见。有什么想法吗 ?感谢名单。

修改

值得注意的是,第一次编辑视图时,一切顺利,当我处理3个子视图时,它们都是可见的,但是当我转到另一个视图并返回到此视图时,只有最后一个子视图是可见的。

另外,我正在研究一个具有拆分视图的iPad项目。

修改 这是为UIScrollView

绘制新子视图的方法代码
 -(IBAction) addMoreView
    {

        NSArray *arr = [[NSBundle mainBundle] loadNibNamed:@"AppTableView" owner:self options:nil];

        AppTableView *aView = [arr objectAtIndex:0];
        [aView setFrame:CGRectMake(startX, 0, aView.bounds.size.width, aView.bounds.size.height)];
        [self.scrollView addSubview:aView];
        self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width+aView.frame.size.width
                                             , self.scrollView.contentSize.height);


        startX = startX + aView.frame.size.width;//Update the X position, first 0, then 600, 1200, and so on.
        [self.scrollView scrollRectToVisible:aView.frame animated:YES];
        NSLog(@"%f",self.scrollView.contentSize.width);
        NSLog(@"%f",self.scrollView.contentSize.height);

    }

假设我有3个子视图,上面的方法将被调用3次,因为它放在for循环中。所以这是上述方法NSLogs的结果:

NSLog(@"%f",self.scrollView.contentSize.width);
NSLog(@"%f",self.scrollView.contentSize.height);

    First iteration:

    600.000000

    0.000000

    Second iteration:

    1200.000000

    0.000000

    Third iteration:

    1800.000000

    0.000000

修改

rob mayoff建议的命令让我知道为什么会这样:

   |    |    |    | <AppTableView: 0x1eef4700; frame = (0 18; 600 430); autoresize = LM+RM+TM+BM; tag = 990; layer = <CALayer: 0x1eef4790>>

   |    |    |    | <AppTableView: 0x1ee3f380; frame = (0 18; 600 430); autoresize = LM+RM+TM+BM; tag = 991; layer = <CALayer: 0x1ee3f410>>

   |    |    |    | <AppTableView: 0x1ee56910; frame = (0 18; 600 430); autoresize = LM+RM+TM+BM; tag = 992; layer = <CALayer: 0x1ee3f410>>

所有三个子视图都在同一帧中绘制,因此它们在彼此之上,但是当我在运行时使用断点调试时,x正在改变,第一次是0,然后是600然后是1200,这使我认为这是正确的。如何修复,特别是x值正在递增,那么问题是什么以及为什么它们仍然在相同的x坐标上绘制?

7 个答案:

答案 0 :(得分:2)

首先,您应该将[super viewDidLoad]电话放在- (void)viewDidLoad方法的顶部,而不是在底部。

鉴于您不清楚实际看到的内容以及您希望看到的内容,提供问题的最小工作示例作为可下载项目将有助于我们为您提供帮助。如果您只是尝试在不与托管对象交互的单独视图控制器中重现这一点,而是使用一些静态提供的数据,则其他人将能够自己重现并调试它。或者你也可以在这个过程中自己弄明白。

答案 1 :(得分:1)

我回来的时间有点晚了,但最后我找到了解决问题的方法,所以认为分享它可以节省别人的时间。

对于我的情况,scrollview是nib文件中的自定义视图。因此,通过左侧和顶部激活其自动调整大小的掩码,错误已得到修复。

enter image description here

答案 2 :(得分:0)

-addMoreView中的这段代码是问题所在:

AppTableView *aView = [arr objectAtIndex:0];
[aView setFrame:CGRectMake(startX, 0, aView.bounds.size.width, aView.bounds.size.height)];
[self.scrollView addSubview:aView];

如果startX永远不会改变,您可以在同一位置添加所有这些视图。

答案 3 :(得分:0)

当然,您没有正确设置3个项目的内容大小:

self.scrollView.contentSize.width+aView.frame.size.width

应该是

self.scrollView.contentSize.width+ ( aView.frame.size.width * NUMBER_OF_SUBVIEWS)

我认为当你在滚动视图上水平滚动时,内容大小只允许一个子视图有足够的空间吗?

答案 4 :(得分:0)

使用了一个静态变量,在加载时重新初始化为0,然后它会增加子视图的宽度以开始绘制新的X位置。

答案 5 :(得分:0)

尝试在addMoreView方法中将aView的autoresizingMask设置为UIViewAutoresizingNone

答案 6 :(得分:0)

created a project在姐妹帖子中使用你的代码,它的工作正常。我在自动调整掩码上添加了几个测试,如下所示。我建议你把它与你正在做的事情进行比较。当子视图或scrollView上的蒙版未设置为绑定到顶部/左侧时,会发生奇怪的事情。

我修改过的代码:

NSArray *colors = @[ [UIColor redColor], [UIColor greenColor], [UIColor blueColor] ];

UIViewAutoresizing mask;
mask = [self.scrollView autoresizingMask];
//assert(!self.scrollView.autoresizesSubviews); // has no affect here

if((mask & (UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)) != mask) NSLog(@"scrollView MASK WRONG");

for (int i=0; i<3; ++i) {

    NSArray *arr = [[NSBundle mainBundle] loadNibNamed:@"AppTableView" owner:self options:nil];

    NSLog(@"scrollView frame: %@", NSStringFromCGRect(self.scrollView.frame));
    if((mask & (UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)) != mask) NSLog(@"aView MASK WRONG");

    AppTableView *aView = [arr objectAtIndex:0];
    assert([aView isKindOfClass:[AppTableView class]]);
    NSLog(@"orig aView frame: %@", NSStringFromCGRect(aView.frame));
    UIViewAutoresizing mask = [aView autoresizingMask];
    if((mask & (UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)) != mask) NSLog(@"aView MASK WRONG");


    aView.frame = CGRectMake(startX, 0, aView.bounds.size.width, aView.bounds.size.height);
    NSLog(@"changed aView frame: %@", NSStringFromCGRect(aView.frame));
    aView.backgroundColor = colors[i];

    [self.scrollView addSubview:aView];
    self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width+aView.frame.size.width
                                             ,self.scrollView.contentSize.height);
    startX = startX + aView.frame.size.width;

   //AppTableView *_appTableView = (AppTableView *) [[self.scrollView subviews] lastObject];

    //_appTableView.txtADDRESS.text = _appTable.address;//Fill in the form, no need to write all the form fields code because it's the same way.
}
NSLog(@"scrollView frame: %@", NSStringFromCGRect(self.scrollView.frame));
NSLog(@"scrollView contentOffset: %@", NSStringFromCGPoint(self.scrollView.contentOffset));