UITableView与UIRefreshControl在半透明状态栏下

时间:2012-10-16 11:00:05

标签: iphone objective-c ios uitableview uirefreshcontrol

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

现在,我刚刚添加了一个即时刷新的iOS6 UIRefreshControl,但是由于-20 y位置,它会从状态栏后面拖动。我希望它“处于”状态位置而非落后状态。“

为什么它变得混乱是有道理的但是改变它的框架似乎没有任何区别,而tableview的内容插入等也没有什么区别。

文档建议一旦设置了refreshControl,UITableViewController将从此开始处理它的位置。

有什么想法吗?

7 个答案:

答案 0 :(得分: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变量更改为您需要的任何值,它将处理其余的值。

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

答案 1 :(得分: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];
}

答案 2 :(得分:1)

current upvoted answer与你拉下组件的事实不一致(正如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];
}

答案 3 :(得分:0)

UIRefreshControl始终位于UITableView内容的上方。如果您需要更改refreshControl的位置,请尝试更改tableView的顶部contentInsetUIRefreshControl在确定应该放置的位置时会考虑到这一点。

答案 4 :(得分: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点;

答案 5 :(得分:0)

我发现在其他答案中覆盖布局子视图不仅仅是更改框架,它们还会改变行为(控件开始随内容滑落)。要更改框架而不是行为,我这样做了:

- (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);

}

答案 6 :(得分: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()
    }
}