5

我有一个 UIScrollView 动态添加到主视图中,我用小的 UIView 对象填充它。我将它的 contentSize 设置为大于设备分辨率的值,但在更改设备方向之前我无法滚动它。

如何在方向更改之前使其滚动?

稍后编辑:

我意识到问题来自我正在添加的某些子视图,更具体地说是为这些子视图添加了一些约束:

这是我添加子视图的代码(该方法被调用了大约 10-20 次):

-(void) addShelve:(NSInteger) index
{
FSShelf *shelf = [[FSShelf alloc] initWithFrame:CGRectMake(0, index * [FSConstants getShelfVerticalDistance], 0, 0)];
[shelves addObject:shelf];

[shelfView addSubview:shelf];
[shelf addShelfConstraints];
}

FSShelf 是 UIView 的子类,shelfView 是我的 UIScrollView 的子类。

以下是添加的约束addShelfContraints

    [self.superview addConstraint:[FSUtils getWidthConstraintFor:self.superview with:self constant: -2 * ([FSConstants getShelveMargin])]];
    [self addConstraint:[FSUtils getSelfHeightConstraintFor:self constant:30]];
    [self.superview addConstraint:[FSUtils getCenterXConstraintFor:self.superview with:self constant:0]];

FSUtils 类中用于添加约束的方法:

+ (NSLayoutConstraint *)getSelfHeightConstraintFor:(UIView *)view constant:(CGFloat)constant
{
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view
                                                                  attribute:NSLayoutAttributeHeight
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:nil
                                                                  attribute:NSLayoutAttributeNotAnAttribute
                                                                 multiplier:1.0
                                                                   constant:constant];
    return constraint;
}

+ (NSLayoutConstraint *)getCenterXConstraintFor:(UIView *)superView with:(UIView *)subView constant:(CGFloat)constant
{
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:subView
                                                                  attribute:NSLayoutAttributeCenterX
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:superView
                                                                  attribute:NSLayoutAttributeCenterX
                                                                 multiplier:1.0
                                                                   constant:constant];

    return constraint;
}

+ (NSLayoutConstraint *)getWidthConstraintFor:(UIView *)superView with:(UIView *)subView constant:(CGFloat)constant
{
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:subView
                                                                  attribute:NSLayoutAttributeWidth
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:superView
                                                                  attribute:NSLayoutAttributeWidth
                                                                 multiplier:1.0
                                                                   constant:constant];
    return constraint;
}

你注意到这些约束有什么问题吗?

4

4 回答 4

1

您尝试施加的约束shelfView(我假设是您的 UIScrollView)是不明智的。您正在创建具有零宽度和零 x 原点的架子子视图,FSShelf *shelf = [[FSShelf alloc] initWithFrame:CGRectMake(0, index * [FSConstants getShelfVerticalDistance], 0, 0)];然后立即尝试将架子视图约束为具有相同的零宽度减去一些常数(因此架子视图需要负宽度),然后与子视图相同的中心 x,但架子视图仍然是零宽度并且具有零 x 原点!您分配给货架子视图的唯一约束是它们的高度。事实上,我认为这里缺少一些东西。使用您发布的代码,您的货架子视图的宽度始终为零。你真的在屏幕上看到任何货架子视图吗?

无论如何,这是我的建议:尝试shelfView根据其每个货架子视图添加约束是一个失败的提议。在这种情况下,约束似乎是不可满足的,并且通常您会发现各种约束变得不可满足,除非您非常小心地确保所有子视图始终就它们的父视图应该如何布局达成一致。

而不是所有这些,只需忘记约束代码。你想要做的很简单。ShelfView 应该有一个等于屏幕大小的框架(或应用程序框架,无论如何可能是其父视图的边界),并且架子视图应该垂直排列,它们之间有一些垂直边距和一些水平边距分开他们从屏幕的边缘。像现在一样添加视图,而不是添加任何约束调用[self.view setNeedsLayout];,然后viewDidLayoutSubviews在视图控制器中实现该方法。你会想要这样的东西:

- (void)viewDidLayoutSubviews {
    const CGRect rootViewBounds = self.view.bounds;
    shelfView.frame = rootViewBounds;

    const CGFloat kHorizontalMargin = [FSConstants getShelveMargin];
    const CGFloat kVerticalDistancePerShelf = [FSConstants getShelfVerticalDistance];
    const CGFloat kShelfHeight = 30.0;
    const NSUInteger shelvesCount = [shelves count];
    for (NSUInteger j = 0; j < shelvesCount; j++) {
        UIView *shelf = [shelves objectAtIndex:j];
        shelf.frame = CGRectMake(kHorizontalMargin,
                                 j * kVerticalDistancePerShelf,
                                 CGRectGetWidth(rootViewBounds) - 2.0 * kHorizontalMargin,
                                 kShelfHeight);
    }
    shelfView.contentSize = CGSizeMake(CGRectGetWidth(rootViewBounds), (shelvesCount - 1) * kVerticalDistancePerShelf + kShelfHeight);
}
于 2013-03-24T15:04:10.530 回答
1

滚动与设备分辨率没有任何关系。当您的内容的大小大于您的 scrollView 框架的大小时,就会发生滚动。

通常,要使大小为 100*100 的内容可以滚动,您应该有一个帧大小小于 100*100 的滚动视图。如果 frame.width < contentsize.width,它将允许水平滚动。同样的,如果 frame.height < contentsize.height,它将允许垂直滚动。

您可能选择了自动布局,或者您可能不小心使用了自动调整大小标志,这可能导致您的 scrollview.frame 的大小大于 contentsize。当您提供方向时,框架可能会完美固定并且您可以滚动。

如果您想发现确切的问题,请发布代码。

于 2013-03-23T05:20:37.467 回答
1

在您的单次点击中,尝试像这样创建

UIScrollView * scrollview = [[UIScrollView alloc]init];
CGRect viewFrame = self.view.frame;
[scrollview setFrame:viewFrame];
[scrollview setShowsHorizontalScrollIndicator:YES];
[scrollview setShowsVerticalScrollIndicator:YES];

UIView * view = [[UIView alloc]init];
CGRect viewDoubleFrame = CGRectMake(viewFrame.origin.x,viewFrame.origin.y,viewFrame.size.width * 2,viewFrame.size.height *2);
[view setFrame:viewDoubleFrame];
[view setBackgroundColor:[UIColor darkGrayColor]];

// add your additional components here

[scrollview setContentSize:CGSizeMake(view.frame.size.width,view.frame.size.height)];
[scrollview addSubview:view];

[self.view addSubview:scrollview];
于 2013-03-22T12:39:29.450 回答
0

请注意,如果您使用自动布局,仅更改内容大小是不够的。滚动视图以不同的方式布局。我在 stack Here上发现这个问题非常有帮助。因此,请检查您是否正在使用自动布局并适应或禁用它。
希望这会有所帮助,Andrea

[编辑]
如果您的目标设备 >=iOS6,为什么不使用集合视图。它们是非常酷的东西,具有令人敬畏的布局功能,感谢 Peter,您可以替换 iOS>=4.3。据我了解,它们可以满足您的要求。 github

于 2013-03-22T14:51:01.500 回答