iOS 7 UIRefreshControl tintColor无法用于beginRefreshing

时间:2013-09-26 10:58:37

标签: iphone objective-c xcode user-interface ios7

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

[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];

强行表明。 它显示了它,但现在又回到了默认颜色:

enter image description here

如果我尝试手动拉动以后刷新,则为红色。

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

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

P.P.S:我构建了一个示例项目,你能告诉我你是否有相同的bug或我的代码中是否有问题?这是链接:http://d.pr/f/pGrV

非常感谢!

19 个答案:

答案 0 :(得分:51)

嘿,他只是偶然发现了这个问题。

有趣的是,我通过首先设置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 ^

答案 1 :(得分:23)

SWIFT解决方案! 在viewDidLoad

中插入以下代码
self.refreshControl.tintColor = UIColor.orangeColor()
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height)
self.refreshControl.beginRefreshing()

Swift 3.1

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

答案 2 :(得分: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绑定的方法。

答案 3 :(得分: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。

答案 4 :(得分:3)

(SWIFT):

我正在使用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()

}

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

答案 6 :(得分:2)

tintColor问题的解决方案:在viewDidLoad

中添加它
[self.refreshControl setTintColor:[UIColor whiteColor]];
[self.refreshControl tintColorDidChange];

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

答案 7 :(得分:2)

为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()
    }
}

答案 8 :(得分:1)

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

我通过设置AttributedTitle

RefreshControl来解决着色问题
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");
}

我的更新方法如下所示:

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'还附带第二个bug。 第一次刷新时,您会注意到AttributedTitle未显示。 刷新第二个(,第三个,第四个......)时间将正确显示标题。但是如果你不想要一个标题,你只需用空字符串初始化它,这对你来说不是一个大问题。

我希望这对其他人有用。

答案 9 :(得分:1)

这个黑客非常有用

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
        }
    }
}

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

答案 11 :(得分:0)

我创建了一个插件UIRefreshControl+beginRefreshing category来解决此问题。

简而言之,它修复了tintColor问题并手动tableView调整contentOffset以确保刷新控件可见。请尝试:)

答案 12 :(得分:0)

尝试在viewWillAppear中设置UIRefreshControl的tintColor。

答案 13 :(得分:0)

我正在使用Xamarin C#(iOS 10),并发现所有这些答案的组合是为我修复它的原因。

在我make我有以下内容:

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(); }); }); 缺少白色色调的部分。

感谢所有为此问题做出贡献的人。

答案 14 :(得分:0)

这是一个错误,在设置其const HomeStack = DrawerNavigator( { Logo: { screen: HomeScreen, navigationOptions: { drawerLabel: () => ( <Image source={require("../assets/Track.png")} style={{ backgroundColor: "#333", width: LogoWidth, height: LogoHeight, marginLeft: 10 }} /> ), drawerIcon: "", title: "" } }, Home: { screen: HomeScreen, navigationOptions: { drawerLabel: home, drawerIcon: () => <Icon name="home" size={24} color="#333" /> } }, ActiveBid: { screen: ActiveBidScreen, navigationOptions: { drawerLabel: all_Bid_list, drawerIcon: () => <Icon name="list" size={24} color="#333" /> } }, TripControl: { screen: TripStartStopScreen, navigationOptions: { drawerLabel: tripControl, drawerIcon: () => <MyIcon name="truck-fast" size={24} color="#333" /> } }, UnattenedTrips: { screen: UnattenedTrips, navigationOptions: { drawerLabel: miss_trips, drawerIcon: () => <MyIcon name="truck-fast" size={24} color="#333" /> } }, Profile: { screen: Profile, navigationOptions: { drawerLabel: profile, drawerIcon: () => <Icon name="people" size={24} color="#333" /> } }, UploadImage: { screen: UploadImageScreen, navigationOptions: { drawerLabel: image_upload, drawerIcon: () => <Icon name="image" size={24} color="#333" /> } }, Contact: { screen: ContactScreen, navigationOptions: { drawerLabel: contact, drawerIcon: () => <Icon name="contact-phone" size={24} color="#333" /> } }, Logout: { screen: Logout, navigationOptions: { drawerLabel: Log_out, drawerIcon: () => <MyIcon name="logout" size={24} color="#333" /> } } }, { gesturesEnabled: false } ); const MainNavigation = StackNavigator( { Login: { screen: LoginScreen, navigationOptions: { gesturesEnabled: false } }, forgotpassword: { screen: ForgetPassword, navigationOptions: { gesturesEnabled: false } }, Register: { screen: RegisterScreen, navigationOptions: { gesturesEnabled: false } }, DriverInfo: { screen: DriverInfoScreen, navigationOptions: { gesturesEnabled: false } }, HomeView: { screen: HomeStack }, TripDetail: { screen: TripDetailScreen, navigationOptions: { gesturesEnabled: false } }, TripDetailOnNotification: { screen: TripDetailOnNotificationScreen, navigationOptions: { gesturesEnabled: false } }, OrderDetails: { screen: OrderDetailsScreen, navigationOptions: { gesturesEnabled: false } }, addTruck: { screen: addTruckScreen, navigationOptions: { gesturesEnabled: false } }, }, { transitionConfig: () => ({ screenInterpolator: () => null }), headerMode: "none", initialRouteName: "Login", navigationOptions: { gesturesEnabled: false } } ); 属性(或从beginRefreshing()调用它(详细信息here)之后立即在刷新控件上调用tintColor时发生。但是,通过将viewDidLoad()调用包装在beginRefreshing()语句中(Swift 4),是一种简单的解决方法:

defer

答案 15 :(得分:0)

设置后

tableView.refreshControl = refreshControl 

refreshControl每次都是不同实例的几次,当刷新控件颜色始终为黑色,而将着色颜色设置为其他值时,我遇到了问题。

所以我只设置了tableView.refreshControl = refreshControl一次,而当我需要隐藏它时,我设置了alpha值,该线程中的更多细节:

How do I "hide" a UIRefreshControl?

答案 16 :(得分:0)

在Swift 4上,使用UIView.animate对我不起作用。

这就是我最终使用的

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

答案 17 :(得分:0)

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

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

答案 18 :(得分:-2)

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

[[NSOperationQueue mainQueue] addOperationWithBlock:^ {
    [self.refreshControl setTintColor:[UIColor redColor]];
    [self.refreshControl beginRefreshing];
}];