6

我创建了一个 UITableView,我想在我的半透明黑色状态栏下方滚动。在我的 XIB 中,我只是将表格视图的 y 位置设置为 -20,一切看起来都很好。

现在,我刚刚添加了一个下拉刷新 iOS6 UIRefreshControl,但是由于 -20 y 位置,它可以从状态栏后面拖动。我希望它的“拉伸到”位置位于状态栏下方而不是后面。

为什么它会搞砸是有道理的,但改变它的框架似乎没有任何区别,并且 tableview 的内容插图等没有任何区别。

文档建议,一旦设置了 refreshControl, UITableViewController 就会从那时起处理它的位置。

有任何想法吗?

4

7 回答 7

9

您可以像这样子类化UIRefreshControl并实现layoutSubviews

@implementation RefreshControl {
    CGFloat topContentInset;
    BOOL topContentInsetSaved;
}

- (void)layoutSubviews {
    [super layoutSubviews];

    // getting containing scrollView
    UIScrollView *scrollView = (UIScrollView *)self.superview;

    // saving present top contentInset, because it can be changed by refresh control
    if (!topContentInsetSaved) {
        topContentInset = scrollView.contentInset.top;
        topContentInsetSaved = YES;
    }

    // saving own frame, that will be modified
    CGRect newFrame = self.frame;

    // if refresh control is fully or partially behind UINavigationBar
    if (scrollView.contentOffset.y + topContentInset > -newFrame.size.height) {
        // moving it with the rest of the content
        newFrame.origin.y = -newFrame.size.height;

    // if refresh control fully appeared
    } else {
        // keeping it at the same place
        newFrame.origin.y = scrollView.contentOffset.y + topContentInset;
    }

    // applying new frame to the refresh control
    self.frame = newFrame;
}

它考虑了tableView contentInset,但您可以将topContentInset变量更改为您需要的任何值,其余部分将由它处理。

我希望代码有足够的文档来理解它是如何工作的。

于 2013-06-19T19:44:52.863 回答
4

只需子类化 UIRefreshControl 并像这样覆盖 layoutSubviews:

- (void)layoutSubviews
{
    UIScrollView* parentScrollView = (UIScrollView*)[self superview];

    CGSize viewSize = parentScrollView.frame.size;

    if (parentScrollView.contentInset.top + parentScrollView.contentOffset.y == 0 && !self.refreshing) {
        self.hidden = YES;
    } else {
        self.hidden = NO;
    }

    CGFloat y = parentScrollView.contentOffset.y + parentScrollView.scrollIndicatorInsets.top + 20;

    self.frame = CGRectMake(0, y, viewSize.width, viewSize.height);

    [super layoutSubviews];
}
于 2012-10-31T17:42:49.480 回答
1

当前投票的答案与您将组件拉下的事实不符(正如 Anthony Dmitriyev 指出的那样),偏移量不正确。最后一部分是修复它。

无论哪种方式:UIRefreshControl使用以下方法子类化:

- (void)layoutSubviews
{
    UIScrollView* parentScrollView = (UIScrollView*)[self superview];
    CGFloat extraOffset = parentScrollView.contentInset.top;

    CGSize viewSize = parentScrollView.frame.size;

    if (parentScrollView.contentInset.top + parentScrollView.contentOffset.y == 0 && !self.refreshing) {
        self.hidden = YES;
    } else {
        self.hidden = NO;
    }

    CGFloat y = parentScrollView.contentOffset.y + parentScrollView.scrollIndicatorInsets.top + extraOffset;

    if(y > -60 && !self.isRefreshing){
        y = -60;
    }else if(self.isRefreshing && y <30)
    {
        y = y-60;
    }
    else if(self.isRefreshing && y >=30)
    {
        y = (y-30) -y;
    }

    self.frame = CGRectMake(0, y, viewSize.width, viewSize.height);

    [super layoutSubviews];
}
于 2013-07-17T12:41:53.130 回答
0

UIRefreshControl always sits above the content in your UITableView. If you need to alter where the refreshControl is place, try altering the tableView's top contentInset. The UIRefreshControl takes that into account when determining where it should be positioned.

于 2012-10-17T03:01:34.330 回答
0

尝试这个:

CGFloat offset = 44;
for (UIView *subview in [self subviews]) {
    if ([subview isKindOfClass:NSClassFromString(@"_UIRefreshControlDefaultContentView")]) {
        NSLog(@"Setting offset!");
        [subview setFrame:CGRectMake(subview.frame.origin.x, subview.frame.origin.y + offset, subview.frame.size.width, subview.frame.size.height)];
    }
}

这会将 UIRefreshControll 向下移动 44 个点;

于 2013-05-28T03:23:18.953 回答
0

我发现覆盖其他答案中的 layoutsubviews 不仅仅改变了框架,它们还改变了行为(控件开始随着内容向下滑动)。要更改框架而不是我这样做的行为:

- (void)layoutSubviews {
    [super layoutSubviews];

    CGRect frame = self.frame;
    CGFloat desiredYOffset = 50.0f;
    self.frame = CGRectMake(frame.origin.x, frame.origin.y + desiredYOffset, frame.size.width, frame.size.height);

}

于 2014-05-07T22:24:20.120 回答
0

这非常顺利,但它是一个超级 hacky 的解决方案:

class CustomUIRefreshControl: UIRefreshControl {
    
    override func layoutSubviews() {
        let offset = UIApplication.shared.windows[0].safeAreaInsets.top
        frame = CGRect(
            x: frame.origin.x,
            y: frame.origin.y + offset/2.5,
            width: frame.size.width,
            height: frame.size.height
        )
        
        let attribute = [
            NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: offset/2)!,
            NSAttributedString.Key.foregroundColor: UIColor.clear
        ]
        attributedTitle = NSAttributedString(string: "Hack", attributes: attribute)

        super.layoutSubviews()
    }
}
于 2021-03-31T02:45:52.950 回答