【问题标题】:What's the proper way to center the UIRefreshControl above a scrolling UICollectionView?将 UIRefreshControl 置于滚动 UICollectionView 上方的正确方法是什么?
【发布时间】:2025-12-19 22:30:12
【问题描述】:

场景:包含图像视图的刷新控件。

我确定遇到过这个问题:

  1. 在 UICollectionView 上创建 UIRefreshControl。
  2. 水平滚动以注意 UIRefreshControl 是倾斜的。

这是设置代码:

- (void)setupRefreshControl {
    self.refreshControl = [UIRefreshControl new];
    self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refresh Data"];
    self.refreshControl.tintColor = UIColor.redColor;
    self.refreshControl.backgroundColor = UIColor.whiteColor;
    UIImage *hook = [UIImage imageNamed:@"Hook"];
    UIImageView *hookImageView = [[UIImageView alloc] initWithImage:hook];
    UIImage *fish = [UIImage imageNamed:@"Fish"];
    UIImageView *fishImageView = [[UIImageView alloc] initWithImage:fish];

    UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[hookImageView ,fishImageView]];
    stackView.axis = UILayoutConstraintAxisVertical;
    stackView.spacing = 10.0;
    [self.refreshControl addSubview:stackView];

    [stackView setTranslatesAutoresizingMaskIntoConstraints:NO];
    UILayoutGuide *container = [_refreshControl layoutMarginsGuide];
    [stackView.topAnchor constraintEqualToAnchor:container.topAnchor].active = YES;
    CGFloat width = self.refreshControl.bounds.size.width;
    [stackView.leftAnchor constraintEqualToAnchor:container.leftAnchor constant:width/2].active = YES;
    [self.refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
    self.collectionView.refreshControl = self.refreshControl;
}

如您所见,UIRefreshControl 在水平滚动条上偏离中心。我是否需要始终计算新中心?

必须有一个标准的方法来做到这一点。

【问题讨论】:

    标签: ios objective-c uicollectionview uirefreshcontrol


    【解决方案1】:

    最简单的方法应该是使用自动布局使堆栈视图居中,我不会将堆栈视图嵌入到刷新控件中。以下约束(您应该适应您的需要的 20.0 除外)应将堆栈视图放在正确的位置:

    stackView.backgroundColor = [UIColor clearColor];
    [stackView.centeredXAnchor constraintEqualToAnchor:container.centeredXAnchor constant:0.0].active = YES; 
    [stackView.bottomAnchor constraintEqualToAnchor:container.topAnchor constant:20.0].active = YES;
    

    您还应该向堆栈视图添加一个活动视图(或动画鱼图标)和一个标签,并且您必须自己处理弹跳。

    【讨论】:

    • 我无法让您的建议对我有用。但是,我确实设法通过上面发布的解决方案将 UIRefreshControl 居中。我错过了几个锚。 ....尽管我喜欢它的行为有点奇怪。
    • 我的建议是取消控制。
    • 这是一个需要使用控件的编码挑战。但我同意删除控件会让生活更轻松。
    • @FrederickC.Lee:太糟糕了,我没有中奖。 ;-)
    【解决方案2】:

    简单的监督:
    我只需要一个额外的锚来使 UIRefreshControl 居中:

    - (void)setupRefreshControl {
        // Refresh Control:
        self.refreshControl = [UIRefreshControl new];
        self.collectionView.refreshControl = self.refreshControl;
    
        [_refreshControl setTranslatesAutoresizingMaskIntoConstraints:NO];
        UILayoutGuide *refreshControlContainer = [_collectionView layoutMarginsGuide];
        [_refreshControl.topAnchor constraintEqualToAnchor:refreshControlContainer.topAnchor constant: 1.0].active = YES;
        [_refreshControl.leftAnchor constraintEqualToAnchor:refreshControlContainer.leftAnchor constant: 1.0].active = YES;
        [_refreshControl.heightAnchor constraintEqualToConstant:300.0].active = YES;
    
        self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refresh Data"];
        self.refreshControl.tintColor = UIColor.redColor;
        self.refreshControl.backgroundColor = UIColor.whiteColor;
    
         // StackView members:
        UIImage *hook = [UIImage imageNamed:@"Hook"];
        UIImageView *hookImageView = [[UIImageView alloc] initWithImage:hook];
        UIImage *fish = [UIImage imageNamed:@"Fish"];
        UIImageView *fishImageView = [[UIImageView alloc] initWithImage:fish];
    
        UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[hookImageView ,fishImageView]];
        stackView.axis = UILayoutConstraintAxisVertical;
        stackView.spacing = 10.0;
        [self.refreshControl addSubview:stackView];
    
        // StackView:
        [stackView setTranslatesAutoresizingMaskIntoConstraints:NO];
        UILayoutGuide *stackViewContainer = [_refreshControl layoutMarginsGuide];
        [stackView.topAnchor constraintEqualToAnchor:stackViewContainer.topAnchor].active = YES;
        CGFloat width = self.refreshControl.bounds.size.width;
        [stackView.leftAnchor constraintEqualToAnchor:stackViewContainer.leftAnchor constant:width/2].active = YES;
    
        [self.refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
    
    }
    

    【讨论】:

      最近更新 更多