将 UIRefreshControl 置于滚动 UICollectionView 上方的正确方法是啥?

Posted

技术标签:

【中文标题】将 UIRefreshControl 置于滚动 UICollectionView 上方的正确方法是啥?【英文标题】:What's the proper way to center the UIRefreshControl above a scrolling UICollectionView?将 UIRefreshControl 置于滚动 UICollectionView 上方的正确方法是什么? 【发布时间】:2018-02-15 20:13:59 【问题描述】:

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

我确定遇到过这个问题:

    在 UICollectionView 上创建 UIRefreshControl。 水平滚动以注意 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 在水平滚动条上偏离中心。我是否需要始终计算新中心?

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

【问题讨论】:

【参考方案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];


【讨论】:

以上是关于将 UIRefreshControl 置于滚动 UICollectionView 上方的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

UIRefreshControl 在启用 preferLargeTitles 的情况下向下滚动时出现奇怪的跳转

当 UIRefreshControl 处于活动状态时,字母滚动条会向下移动?

类似于 UIRefreshControl 将隐藏的 UIView 添加到 UITableView

路由更改时如何在不滚动 Reactjs 的情况下将页面置于顶部

用于“上拉”刷新的 UIRefreshControl?

UIRefreshControl 和 tableFooterView = UIView()