iOS 7 UIRefreshControl tintColor不适用于beginRefreshing


75

我正在尝试在UIRefreshControl(在iOS 7上构建)上设置tintColor。我在情节提要中启用了tableViewController的刷新,然后在ViewControllerviewDidLoad方法中执行以下操作:

[self.refreshControl setTintColor:[UIColor redColor]];

所以现在,当我拉动刷新时,刷新控件的颜色确实是红色的:

redSpiny

我希望我的视图在显示时自动更新,所以我这样做了:

- (void)viewDidAppear:(BOOL)animated{
    [self.refreshControl beginRefreshing];
}

根据https://stackoverflow.com/a/16250679/1809736的介绍,它没有显示出旋转的轮子。

[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:NO];

强迫展示它。它显示了它,但现在又恢复为默认颜色:

在此处输入图片说明

如果我尝试手动拉后刷新,它是红色的。

我尝试在iOS6上构建它,并且它应该可以正常工作,所以这是一个iOS7错误吗?

PS:模拟器不是问题,我尝试在设备上构建它,同样的错误。

PPS:我建立了一个示例项目,能否告诉我您是否有相同的错误或代码中是否存在问题?这是链接:http : //d.pr/f/pGrV

非常感谢 !


6
在iOS7下,UIRefreshControl确实存在问题。我建议暂时使用开放源代码或使用bug。确保在bugreport.apple.com
Leo Natan

5
几乎就像他们在iOS7上没时间了。也有错误UISearchViewController。希望将来的更新将解决此问题。
詹姆斯

8
iOS 8仍然存在此错误...奇怪...
Macistador

2
也是iOS9。有人找到解决方案了吗?
oren 2016年

5
同样在iOS 11上:(
Pranoy C

Answers:


54

嘿,偶然发现了这个确切的问题。

有趣的是,我先设置contentOffset然后调用beginRefreshing来修复代码

if(self.tableView.contentOffset.y == 0){
    self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
    [self.refreshControl beginRefreshing];
}

您可能要动画化此过程:

[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){
    self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
} completion:^(BOOL finished) {
    [self.refreshControl beginRefreshing];
}];

希望对您有帮助。

w ^


这有时不起作用,因为偏移表的要点是因为它有一定的偏移空间,但是只有在调用beginRefreshing之后……如果在偏移它之前,它不会偏移太多!
newton_guima 2014年

2
如广告所示工作。真奇怪。谢谢您:)
Vlad Spreys 2014年

1
在设置contentOffset之后调用“ beginRefreshing”非常重要!(至少在ios8上为准)
Macistador 2014年

1
我被困了一段时间,但事实证明我正在使用[myTableView setContentOffset ... animation:YES]。这对我不起作用。直接设置偏移量,然后使用上面的UIView动画块。
里克·罗伯茨

呼叫顺序确实很重要。奇怪的问题,应在代码文档中添加注释“ // ??? ***”。
2015年

26

SWIFT解决方案!将以下代码插入viewDidLoad

self.refreshControl.tintColor = UIColor.orangeColor()
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height)
self.refreshControl.beginRefreshing()

斯威夫特3.1

self.refreshControl.tintColor = UIColor.orange
self.tableView.contentOffset = CGPoint(x:0, y:-self.refreshControl.frame.size.height)
self.refreshControl.beginRefreshing()

1
谢谢,这为我修复了一些问题viewDidLoad。每次首次使用时,refreshcontrol的高度和颜色都不正确。
罗布

8

@ william-george的答案为我设定了正确的方向,但是却给了我奇怪的自动布局动画问题。

所以这是为我工作的版本:

- (void)programaticallyRefresh {
    // Hack necessary to keep UIRefreshControl's tintColor
    [self.scrollView setContentOffset:CGPointMake(0, -1.0f) animated:NO];
    [self.scrollView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
    [self.refreshControl beginRefreshing];
    [self refresh];
}

-refresh是绑定到的方法UIRefreshControl


6

为UIResfreshControl添加扩展。

extension UIRefreshControl {
    func beginRefreshingManually() {
        self.tintColor = UIColor.white
        if let scrollView = superview as? UIScrollView {
            scrollView.setContentOffset(CGPoint(x: 0, y:scrollView.contentOffset.y - frame.height), animated: false)
        }
        beginRefreshing()
    }
}

与另一种解决方案相比,这是一种行之有效的方法,并且看起来实现得更好。:)感谢Sefa和绝妙的技巧。
布鲁诺·里斯·波特拉

4

这些答案都无法在iOS8上正常工作,最接近的是@jpsim的答案,但在淡入动画期间仍然留下难看的黑色刷新控件(它将在动画过程中在黑色和黑色之间淡入淡出) )。

对我有用的解决方案是在viewDidLoad中创建刷新控件后立即将其放入:

self.refreshControl = [[UIRefreshControl alloc] init];
self.refreshControl.tintColor = [UIColor whiteColor];
...
self.refreshControlHeight = self.refreshControl.frame.size.height;
[self.tableView setContentOffset:CGPointMake(0, -1) animated:NO];
[self.tableView setContentOffset:CGPointMake(0, 0) animated:NO];

然后以编程方式显示UIRefreshControl:

[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControlHeight) animated:YES];
[self.refreshControl beginRefreshing];

我必须存储刷新控件的高度,因为它是为第一次调用设置的,而后续调用的高度将为0。


1
谢谢,您能启发我这个事实仅适用于-1吗?我不喜欢神奇的数字……
里克·范德·林德2015年

这不是一个神奇的数字,他只是将内容偏移量更改为可以忽略不计的金额,然后再将其更改回去。
伊兰·戈尔丁

3

tintColor问题的解决方案:在viewDidLoad中添加它

[self.refreshControl setTintColor:[UIColor whiteColor]];
[self.refreshControl tintColorDidChange];

现在,当您手动调用beginRefresh时,会有一个白色指示器。


3

迅速:

我正在使用Swift和> iOS8。所描述的大多数变通办法都不适合我。这就是我的工作方式:

在viewDidLoad中:

customRefreshControl.tintColor = UIColor.clearColor()

viewDidLoad中不必包含以下内容。我把它放在一个额外的函数中,每次我更新tableView时都会调用它:

private func startRefreshControlAnimation() {

    self.tableView.setContentOffset(CGPointMake(0, -self.customRefreshControl.frame.size.height), animated: true)

    CATransaction.begin()
    self.customRefreshControl.beginRefreshing()
    CATransaction.commit()

}

3

我结合了以前的一些答案。这对我适用于iOS 9和Swift 2:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let contentOffset = self.tableView.contentOffset.y
    UIView.animateWithDuration(0, delay: 0, options: .BeginFromCurrentState, animations: {
        print(self.tableView.contentOffset.y)
            self.tableView.setContentOffset(CGPointMake(0, -self.refreshControl.frame.size.height), animated: false)
        }, completion: { finished in
            self.refreshControl.beginRefreshing()
            self.tableView.setContentOffset(CGPointMake(0, contentOffset/2-self.refreshControl.frame.size.height), animated: true)
            self.refresh() // Code that refresh table data
    })        
}

2

我使用Xamarin(C#)为iOS开发,并遇到了相同的问题。

我固定的着色问题,通过设置AttributedTitleRefreshControl

private CGPoint originalOffset;
...
public override void ViewDidLoad ()
{
     base.ViewDidLoad ();
     ...
     originalOffset = TableView.ContentOffset; // Store the original offset of the table view
     RefreshControl = new UIRefreshControl (){ TintColor = UIColor.Red };
     RefreshControl.ValueChanged += ((s,e) => { Update (this, EventArgs.Empty); });
     // Hack so the TintColor of the RefreshControl will be properly set
     RefreshControl.AttributedTitle = new NSAttributedString ("Fetching data");
}

我的Update方法如下所示:

private async void Update(object sender, EventArgs args)
{
     try {
          TableView.UserInteractionEnabled = false;
          // I find -100 to be a big enough offset
          TableView.SetContentOffset (new CGPoint (0, -100), true);
          RefreshControl.BeginRefreshing ();
          ... // Fetch data & update table source 
          TableView.ReloadData ();
      } catch(Exception) {
          // Respond to exception
      } finally {
          // Put the offset back to the original
          TableView.SetContentOffset (originalOffset, true);
          RefreshControl.EndRefreshing ();
          TableView.UserInteractionEnabled = true;
      }
}

一次ViewDidAppear,我打电话Update编程方式。在设置属性标题之前,我的微调框将是黑色的。现在它具有适当的红色。

值得注意的是,这个“ hack / fix”还带有第二个错误。第一次刷新时,您会注意到AttributedTitle没有显示。刷新第二(第三,第四,...)时间将正确显示标题。但是,如果您不想要标题,则只需使用一个空字符串将其初始化即可,这对您来说不是一个大问题。

我希望这对其他人有用。


1

这个hack很有效

var refreshWasProgramBeginning: Bool = false

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if !refreshWasProgramBeginning {
        UIView.animate(withDuration: 0.25, animations: {
            self.tableView.contentOffset = CGPoint.init(x: 0, y: -self.refreshControl.frame.height)
        }) { (_) in
            self.refreshControl.beginRefreshing()
            self.refreshWasProgramBeginning = true
        }
    }
}

1

我正在使用Xamarin C#(iOS 10),发现所有这些答案的组合对我而言是固定的。

在我的ViewDidLoad我有以下几点:

    RefreshControl = new UIRefreshControl();
    RefreshControl.TintColor = UIColor.White;
    RefreshControl.ValueChanged += OnRefresh;
    RefreshControl.BackgroundColor = UIColor.Clear;

之后,我ViewDidAppear通过以下方式以编程方式调用刷新动画:

    BeginInvokeOnMainThread(() =>
    {
        UIView.Animate(0, 0.2, UIViewAnimationOptions.BeginFromCurrentState, () =>
        {
            TableView.SetContentOffset(new CGPoint(0, TableView.ContentOffset.Y - RefreshControl.Frame.Size.Height), true);
            RefreshControl.AttributedTitle = new NSAttributedString("");
        },
        () =>
        {
            RefreshControl.BeginRefreshing();
        });
    });

请注意,属性标题和动画块的设置是我缺少RefreshControl白色色调时缺少的部分。

感谢所有促成这个问题的人。


1

这是在调用时发生的错误beginRefreshing()的设置它之后刷新控制tintColor属性(或调用它viewDidLoad()(详情点击这里),有一个简单的解决办法但通过包装。beginRefreshing()调用内defer声明(SWIFT 4):

override func viewDidLoad() {
    super.viewDidLoad()
    refreshControl.tintColor = .red
    defer {
        refreshControl.beginRefreshing()
    }
}


0

我找到了一些解决方法,希望它对您有用

 [_TBL setContentOffset:CGPointMake(0,_TBL.contentOffset.y-_refreshControl.frame.size.height) animated:YES];
[_refreshControl performSelector:@selector(beginRefreshing) withObject:nil afterDelay:0.25];
[self getLatestUpdates];


0

当我设定

tableView.refreshControl = refreshControl 

有几次,每次refreshControl都是不同的实例时,我遇到了以下问题:刷新控件的颜色始终为黑色,而将颜色设置为其他值却无济于事。

所以我设置 tableView.refreshControl = refreshControl只了一次,当我需要隐藏它时,我设置了alpha值,此线程中有更多详细信息:

如何“隐藏” UIRefreshControl?


0

UIView.animate在Swift 4上,使用不适用于我。

这就是我最终使用的

extension UIRefreshControl {
    func beginRefreshingManually(with scrollView: UIScrollView, isFirstTime: Bool) {
        if self.isRefreshing { return }

        // Workaround: If we call setContentOffset on the first time that the screen loads
        // we get a black refreshControl with the wrong size.
        // We could just set the scrollView.contentOffset everytime, but it does not animate the scrolling.
        // So for every other time, we call the setContentOffset animated.
        if isFirstTime {
            scrollView.contentOffset = CGPoint(x: 0, y: -self.frame.size.height)
        } else {
            scrollView.setContentOffset(CGPoint(x: 0, y: -self.frame.size.height), animated: true)
        }
        self.beginRefreshing()
    }
}

0

开始旋转之前,为tableView / scrollView手动设置内容偏移量:

tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentOffset.y - (refreshControl.frame.size.height)), animated: true)
refreshControl.beginRefreshing()
......

-2

强制setTintColor在主线程中运行。(主线程更新ui)。

[[NSOperationQueue mainQueue] addOperationWithBlock:^ {
    [self.refreshControl setTintColor:[UIColor redColor]];
    [self.refreshControl beginRefreshing];
}];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.