我创建了一个UITableView,我想在我的半透明黑色状态栏下面滚动。在我的XIB中,我只是将表格视图的y位置设置为-20,它看起来都很好。
现在,我刚刚添加了一个即时刷新的iOS6 UIRefreshControl,但是由于-20 y位置,它会从状态栏后面拖动。我希望它“处于”状态位置而非落后状态。“
为什么它变得混乱是有道理的但是改变它的框架似乎没有任何区别,而tableview的内容插入等也没有什么区别。
文档建议一旦设置了refreshControl,UITableViewController将从此开始处理它的位置。
有什么想法吗?
答案 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的顶部contentInset
。 UIRefreshControl
在确定应该放置的位置时会考虑到这一点。
答案 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()
}
}