ios 我可以在 UIScrollView 中使用 UIRefreshControl 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14905382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I use a UIRefreshControl in a UIScrollView?
提问by SirRupertIII
I have about 5 UIScrollView
's already in my app which all load multiple .xib
files. We now want to use a UIRefreshControl
. They are built to be used with UITableViewControllers (per UIRefreshControl class reference). I do not want to re-do how all 5 UIScrollView
work. I have already tried to use the UIRefreshControl
in my UIScrollView
's, and it works as expected except for a few things.
UIScrollView
我的应用程序中已经有大约 5 个,它们都加载了多个.xib
文件。我们现在想要使用UIRefreshControl
. 它们被构建为与 UITableViewControllers 一起使用(根据 UIRefreshControl 类参考)。我不想重新做所有 5 个UIScrollView
工作的方式。我已经尝试UIRefreshControl
在我的UIScrollView
's 中使用 ,它按预期工作,除了一些事情。
Just after the refresh image turns into the loader, the
UIScrollView
jumps down about 10 pixels, which only does not happen when I am very careful to drag theUIScrollview
down very slowly.When I scroll down and initiate the reload, then let go of the
UIScrollView
, theUIScrollView
stays where I let it go. After it is finished reloading, theUIScrollView
jumps up to the top with no animation.
刷新图像刚进入加载器后,
UIScrollView
向下跳跃了大约10个像素,只有当我非常小心地UIScrollview
非常缓慢地向下拖动时才会发生这种情况。当我向下滚动并启动重新加载,然后放开 时
UIScrollView
,UIScrollView
停留在我放开的地方。重新加载完成后,UIScrollView
没有动画跳到顶部。
Here is my code:
这是我的代码:
-(void)viewDidLoad
{
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[myScrollView addSubview:refreshControl];
}
-(void)handleRefresh:(UIRefreshControl *)refresh {
// Reload my data
[refresh endRefreshing];
}
Is there any way I can save a bunch of time and use a UIRefreshControl
in a UIScrollView
?
有什么办法可以节省大量时间并UIRefreshControl
在 a 中使用aUIScrollView
吗?
Thank You!!!
谢谢你!!!
采纳答案by MacMark
Since iOS 10UIScrollView already has a refreshControl property. This refreshControl will appear when you create a UIRefereshControl and assign it to this property.
由于iOS 10UIScrollView 已经有一个 refreshControl 属性。当您创建 UIRefereshControl 并将其分配给此属性时,将出现此 refreshControl。
There's no needto add UIRefereshControl as a subview anymore.
有没有必要添加UIRefereshControl作为一个子视图了。
func configureRefreshControl () {
// Add the refresh control to your UIScrollView object.
myScrollingView.refreshControl = UIRefreshControl()
myScrollingView.refreshControl?.addTarget(self, action:
#selector(handleRefreshControl),
for: .valueChanged)
}
@objc func handleRefreshControl() {
// Update your content…
// Dismiss the refresh control.
DispatchQueue.main.async {
self.myScrollingView.refreshControl?.endRefreshing()
}
}
A UIRefreshControl object is a standard control that you attach to any UIScrollView object
UIRefreshControl 对象是您附加到任何 UIScrollView 对象的标准控件
Code and quote from https://developer.apple.com/documentation/uikit/uirefreshcontrol
代码和引用来自https://developer.apple.com/documentation/uikit/uirefreshcontrol
回答by Padin215
I got a UIRefreshControl
to work with a UIScrollView
:
我有一个UIRefreshControl
工作UIScrollView
:
- (void)viewDidLoad
{
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
scrollView.userInteractionEnabled = TRUE;
scrollView.scrollEnabled = TRUE;
scrollView.backgroundColor = [UIColor whiteColor];
scrollView.contentSize = CGSizeMake(500, 1000);
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(testRefresh:) forControlEvents:UIControlEventValueChanged];
[scrollView addSubview:refreshControl];
[self.view addSubview:scrollView];
}
- (void)testRefresh:(UIRefreshControl *)refreshControl
{
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing data..."];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:3];//for 3 seconds, prevent scrollview from bouncing back down (which would cover up the refresh view immediately and stop the user from even seeing the refresh text / animation)
dispatch_async(dispatch_get_main_queue(), ^{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMM d, h:mm a"];
NSString *lastUpdate = [NSString stringWithFormat:@"Last updated on %@", [formatter stringFromDate:[NSDate date]]];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdate];
[refreshControl endRefreshing];
NSLog(@"refresh end");
});
});
}
Need to do the data update on a separate thread or it will lock up the main thread (which the UI uses to update the UI). So while the main thread is busy updating the data, the UI is also locked up or frozen and you never see the smooth animations or spinner.
需要在单独的线程上进行数据更新,否则它会锁定主线程(UI 用于更新 UI)。因此,当主线程忙于更新数据时,UI 也被锁定或冻结,您永远看不到流畅的动画或微调。
EDIT: ok, I'm doing the same thing as OP and i've now added some text to it (ie, "Pull to Refresh") and it does need to get back onto the main thread to update that text.
编辑:好的,我正在做与 OP 相同的事情,我现在已经向它添加了一些文本(即“拉动刷新”),它确实需要返回主线程来更新该文本。
Updated answer.
更新了答案。
回答by Diego Frata
Adding to above answers, in some situations you can't set the contentSize (using auto layout perhaps?) or the contentSize's height is less than or equal the height of the UIScrollView. In these cases, the UIRefreshControl won't work because the UIScrollView won't bounce.
添加到上述答案中,在某些情况下,您无法设置 contentSize(也许使用自动布局?)或者 contentSize 的高度小于或等于 UIScrollView 的高度。在这些情况下, UIRefreshControl 将不起作用,因为 UIScrollView 不会反弹。
To fix this set the property alwaysBounceVerticalto TRUE.
要解决此问题,请将属性alwaysBounceVertical设置为TRUE。
回答by Ben Packard
If and when you are fortunate enough to be supporting iOS 10+, you can now simply set the refreshControl
of the UIScrollView
. This works the same way as the previously existing refreshControl
on UITableView
.
如果当你有幸能够支持iOS的10+,你现在可以简单地设置refreshControl
的UIScrollView
。这与之前存在refreshControl
于 上的工作方式相同UITableView
。
回答by John Gavilan
Here is how you do this in C# / Monotouch. I cant find any samples for C# anywhere, so here it is.. Thanks Log139!
以下是在 C#/Monotouch 中执行此操作的方法。我在任何地方都找不到 C# 的任何示例,所以在这里......谢谢Log139!
public override void ViewDidLoad ()
{
//Create a scrollview object
UIScrollView MainScrollView = new UIScrollView(new RectangleF (0, 0, 500, 600));
//set the content size bigger so that it will bounce
MainScrollView.ContentSize = new SizeF(500,650);
// initialise and set the refresh class variable
refresh = new UIRefreshControl();
refresh.AddTarget(RefreshEventHandler,UIControlEvent.ValueChanged);
MainScrollView.AddSubview (refresh);
}
private void RefreshEventHandler (object obj, EventArgs args)
{
System.Threading.ThreadPool.QueueUserWorkItem ((callback) => {
InvokeOnMainThread (delegate() {
System.Threading.Thread.Sleep (3000);
refresh.EndRefreshing ();
});
});
}
回答by Camilo Ortegón
How to do it in Swift 3:
如何在 Swift 3 中做到这一点:
override func viewDidLoad() {
super.viewDidLoad()
let scroll = UIScrollView()
scroll.isScrollEnabled = true
view.addSubview(scroll)
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged)
scroll.addSubview(refreshControl)
}
func pullToRefresh(_ refreshControl: UIRefreshControl) {
// Update your conntent here
refreshControl.endRefreshing()
}
回答by Surely
For the Jumping issue, Tim Norman's answersolves it.
对于跳跃问题,蒂姆诺曼的回答解决了它。
Here is the swift version if you are using swift2:
如果您使用的是 swift2,这里是 swift 版本:
import UIKit
class NoJumpRefreshScrollView: UIScrollView {
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
override var contentInset:UIEdgeInsets {
willSet {
if self.tracking {
let diff = newValue.top - self.contentInset.top;
var translation = self.panGestureRecognizer.translationInView(self)
translation.y -= diff * 3.0 / 2.0
self.panGestureRecognizer.setTranslation(translation, inView: self)
}
}
}
}
回答by Dante
For the Jumping issue, override contentInset only solves it before iOS 9. I just tried a way to avoid jump issue:
对于跳转问题,override contentInset 只能在 iOS 9 之前解决。我只是尝试了一种避免跳转问题的方法:
let scrollView = UIScrollView()
let refresh = UIRefreshControl()
// scrollView.refreshControl = UIRefreshControl() this will cause the jump issue
refresh.addTarget(self, action: #selector(handleRefreshControl), for: .valueChanged)
scrollView.alwaysBounceVertical = true
//just add refreshControl and send it to back will avoid jump issue
scrollView.addSubview(refresh)
scrollView.sendSubviewToBack(refresh)
works on iOS 9 10 11 and so on,and I hope they(Apple) just fix the issue.
适用于 iOS 9 10 11 等等,我希望他们(Apple)能解决这个问题。
回答by Anton Zherdev
I made UIRefreshControl
work properly inside UIScrollView
. I inherited UIScrollView
, blocked changing of contentInset and overrided contentOffset setter:
我在UIRefreshControl
里面正常工作UIScrollView
。我继承UIScrollView
,阻止更改 contentInset 并覆盖 contentOffset setter:
class ScrollViewForRefreshControl : UIScrollView {
override var contentOffset : CGPoint {
get {return super.contentOffset }
set {
if newValue.y < -_contentInset.top || _contentInset.top == 0 {
super.contentOffset = newValue
}
}
}
private var _contentInset = UIEdgeInsetsZero
override var contentInset : UIEdgeInsets {
get { return _contentInset}
set {
_contentInset = newValue
if newValue.top == 0 && contentOffset.y < 0 {
self.setContentOffset(CGPointZero, animated: true)
}
}
}
}
回答by Gianluca Tranchedone
You can simply create an instance of the refresh control and add it at the top of the scroll view. then, in the delegate methods you adjust its behavior to your requirements.
您可以简单地创建刷新控件的实例并将其添加到滚动视图的顶部。然后,在委托方法中,您可以根据自己的要求调整其行为。