Ios 我可以在UIScrollView中使用UIRefreshControl吗?
我的应用程序中已经有大约5个Ios 我可以在UIScrollView中使用UIRefreshControl吗?,ios,iphone,uiscrollview,xamarin.ios,uirefreshcontrol,Ios,Iphone,Uiscrollview,Xamarin.ios,Uirefreshcontrol,我的应用程序中已经有大约5个UIScrollView,它们都加载了多个.xib文件。我们现在想要使用UIRefreshControl。它们是为与UITableViewController一起使用而构建的(每个UIRefreshControl类引用)。我不想重复所有5个UIScrollView的工作方式。我已经尝试在我的UIScrollView中使用UIRefreshControl,除了一些事情外,它的工作原理与预期一样 刷新图像进入加载程序后,UIScrollView会跳下大约10个像素,这只有
UIScrollView
,它们都加载了多个.xib
文件。我们现在想要使用UIRefreshControl
。它们是为与UITableViewController一起使用而构建的(每个UIRefreshControl类引用)。我不想重复所有5个UIScrollView
的工作方式。我已经尝试在我的UIScrollView
中使用UIRefreshControl
,除了一些事情外,它的工作原理与预期一样
UIScrollView
会跳下大约10个像素,这只有在我非常小心地将UIScrollView
缓慢向下拖动时才会发生UIScrollView
时,UIScrollView
会停留在我放开的地方。重新加载完成后,UIScrollView
跳到顶部,没有动画-(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];
}
是否有任何方法可以节省大量时间并在UIScrollView
中使用UIRefreshControl
谢谢你 您只需创建刷新控件的实例并将其添加到滚动视图的顶部即可。然后,在委托方法中,您可以根据自己的需求调整其行为。我获得了一个
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");
});
});
}
需要在单独的线程上执行数据更新,否则它将锁定主线程(UI用于更新UI)。因此,当主线程忙于更新数据时,UI也会被锁定或冻结,您永远看不到平滑的动画或微调器
编辑:好的,我正在做与OP相同的事情,现在我已经添加了一些文本(例如,“拉到刷新”),它确实需要回到主线程来更新该文本
更新答案。以下是如何在C#/Monotouch中实现这一点。我在任何地方都找不到C#的样品,所以在这里。。谢谢你
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 ();
});
});
}
除了上述答案之外,在某些情况下,您无法设置contentSize(可能使用自动布局?),或者contentSize的高度小于或等于UIScrollView的高度。在这些情况下,UIRefreshControl将无法工作,因为UIScrollView不会反弹
要修复此问题,请将属性alwaysBounceVertical设置为TRUE我使
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)
}
}
}
}
class ScrollViewForRefreshControl:UIScrollView{
覆盖变量contentOffset:CGPoint{
获取{return super.contentOffset}
设置{
如果newValue.y<--u contentInset.top | | u contentInset.top==0{
super.contentOffset=newValue
}
}
}
私有var\u contentInset=UIEdgeInsetsZero
覆盖变量contentInset:uiedgeinset{
获取{return\u contentInset}
设置{
_contentInset=newValue
如果newValue.top==0&&contentOffset.y<0{
self.setContentOffset(CGPointZero,动画:true)
}
}
}
}
对于跳跃问题,解决它
如果您使用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)
}
}
}
}
如果您有幸支持iOS 10+,现在只需设置
UIScrollView
的refreshControl
。这与以前在UITableView
上存在的refreshControl
的工作方式相同。如何在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()
}
对于跳转问题,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)
适用于iOS 9 10 11等,我希望他们(苹果)能解决这个问题。因为iOS 10UIScrollView已经有了refreshControl属性。创建UIRefereshControl并将其分配给此属性时,将显示此refreshControl 不再需要将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()
}
}
UIRefreshControl对象是附加到任何UIScrollView对象的标准控件
从iOS 10开始的代码和引号UIScrollView具有可设置为UIRefreshControl的refreshControl属性。一如既往,您不需要管理控件的框架。只需配置控件,为valueChanged事件设置目标操作并分配给属性 无论您使用的是普通滚动视图、表视图还是集合视图,创建刷新控件的步骤都是相同的
if #available(iOS 10.0, *) {
let refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl.addTarget(self,
action: #selector(refreshOptions(sender:)),
for: .valueChanged)
scrollView.refreshControl = refreshControl
}
@objc private func refreshOptions(sender: UIRefreshControl) {
// Perform actions to refresh the content
// ...
// and then dismiss the control
sender.endRefreshing()
}
+感谢你发现自己甚至可以做到这一点。但是,我很难再现这两种症状。我注意到一个完全不同的问题,
attributedtille
在我第一次下拉刷新时出现在错误的位置,除非我在第一次创建刷新控件时明确设置了初始attributedtille
(例如,设置为类似“拉动刷新”)的值。所以,有几个问题:1。在初始创建过程中,您是否将attributeditle
初始化为任何内容?还有,2。你在使用自动布局吗?3.您是否在使用任何UIScrollViewDelegate
方法进行其他操作?如果您阅读了我的问题,我就是这么做的。你有不同的方法吗?你可能会想把你的endRefreshing
放在一个主队列块中,因为它是一个UI方法。我也这么认为,我的第一篇文章包括检索主线程,但这不会导致任何错误或崩溃。这个解决方案对我很有效。然而,在我看来,uirefreshcontrol微调器是最重要的。有没有办法在我的视野下出现?@Salx。。。相同的问题:/@jsetting32-我修复了这行代码的问题:[refreshControl.superview SendSubViewToPack:refreshControl];我也面临着同样的问题