web-dev-qa-db-fra.com

iOS 7 UIRefreshControl tintColor ne fonctionne pas pour commencer

J'essaie de définir un paramètre tintColor sur mon UIRefreshControl (sous iOS 7) . J'ai activé l'actualisation du tableauViewController dans le storyboard, puis dans ma méthode ViewController viewDidLoad, j'ai procédé comme suit:

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

Alors maintenant, lorsque je tire pour rafraîchir, la couleur du contrôle de rafraîchissement est bien rouge:

redSpiny

Je souhaite que mon affichage soit automatiquement mis à jour lorsqu'il apparaît. Je l'ai donc fait:

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

Il n'a pas montré le rouet, selon https://stackoverflow.com/a/16250679/1809736 , j'ai ajouté

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

forcer le montrer . Il le montre, mais maintenant il est revenu à la couleur par défaut: 

enter image description here

Si j'essaie manuellement de rafraîchir après, il est rouge.

J'ai essayé de le construire sur iOS6 et cela fonctionne comme il se doit, alors s'agit-il d'un bogue iOS7?

P.S .: ce n’est pas un problème avec le simulateur, j’ai essayé de le construire sur un appareil, même bogue.

P.P.S: J'ai construit un exemple de projet, pouvez-vous me dire si vous avez le même bogue ou s'il y a un problème dans mon code? Voici le lien: http://d.pr/f/pGrV

Merci beaucoup !

68
Noé Malzieu

Hey viens de tomber sur cette question exacte.

Fait intéressant, j'ai corrigé mon code en définissant d'abord le contentOffset, puis en appelant beginRefreshing

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

Vous voudrez peut-être animer ce processus:

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

J'espère que cela vous aide.

W

49
William George

Swift SOLUTION! Insérez le code suivant dans la 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()
20
Fox5150

La réponse de @ william-george m'a mis dans la bonne direction, mais me donnait d'étranges problèmes d'animation avec autolayout.

Alors voici la version qui a fonctionné pour moi:

- (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 est la méthode liée à la UIRefreshControl.

8
jpsim

Aucune de ces réponses ne fonctionne correctement pour moi sur iOS8, la réponse la plus proche étant celle de @ jpsim, mais elle laissait tout de même un contrôle d'actualisation noir inesthétique lors de son animation en fondu (cela fondrait en fondu en noir et au fil de l'animation ).

La solution qui a fonctionné pour moi a été de mettre cela immédiatement après la création du contrôle d'actualisation dans mon 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];

Ensuite, pour afficher UIRefreshControl par programme:

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

Je devais stocker la hauteur du contrôle d'actualisation, car s'il était défini pour la première invocation, les appels suivants avaient une hauteur de 0.

4
Richard Sim

Rapide:

J'utilise Swift et> iOS8. La plupart des solutions de contournement décrites n'ont pas fonctionné pour moi. Voilà comment je l'ai fait fonctionner:

Dans viewDidLoad:

customRefreshControl.tintColor = UIColor.clearColor()

Ce qui suit ne doit pas nécessairement être dans viewDidLoad. Je le mets dans une fonction supplémentaire qui est appelée à chaque fois que je mets à jour tableView:

private func startRefreshControlAnimation() {

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

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

}
3
arm0nic

J'ai combiné certaines des réponses précédentes. Cela fonctionne pour moi sur iOS 9 et 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
    })        
}
3
Wendy Chu

Solution au problème tintColor: ajoutez ceci dans viewDidLoad

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

Vous avez maintenant un indicateur blanc lorsque vous appelez beginRefresh manuellement.

2
Artjom Zabelin

ce hack fonctionne très bien 

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

Ajoutez une extension pour 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()
    }
}
1
Sefa Ayçiçek

Je développe pour iOS avec Xamarin (C #) et rencontre le même problème.

J'ai corrigé le problème de coloration en définissant la AttributedTitle de la 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");
}

Ma méthode de mise à jour ressemble à ceci:

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

Une fois que ViewDidAppear, j’appelle Update par programmation .. Avant de définir le titre attribué, mon disque aurait été noir . Il a maintenant la couleur rouge appropriée.

Il est intéressant de noter que ce 'hack/fix' est également livré avec un deuxième bogue . La première fois que vous actualisez, vous remarquerez que la AttributedTitle n'est pas affichée . Rafraîchir une seconde (, ...) le temps affichera le titre correctement. Mais si vous ne voulez pas de titre, il vous suffit de l'initialiser avec une chaîne vide, ce qui ne vous pose pas de gros problème.

J'espère que cela pourra être utile à d'autres.

1
Thomas De Wilde

J'ai créé une catégorie UIRefreshControl + beginRefreshing qui résout ce problème. 

En résumé, il corrige le problème tintColor et tableView ajuste manuellement contentOffset pour s’assurer que le contrôle de rafraîchissement est visible. S'il vous plaît essayez :)

0
Hlung

Quand je mis 

tableView.refreshControl = refreshControl 

plusieurs fois où refreshControl est une instance différente à chaque fois, j'ai eu le problème lorsque la couleur de contrôle d'actualisation était toujours noire et que le réglage de la couleur de la teinte sur une valeur différente n'a pas aidé. 

Pour que je ne définisse tableView.refreshControl = refreshControl qu'une seule fois et lorsque j'ai besoin de le cacher, je définis une valeur alpha, plus de détails dans ce fil de discussion:

Comment "cacher" un UIRefreshControl?

0
Paul T.

Il s'agit d'un bogue qui survient lorsque vous appelez beginRefreshing() sur le contrôle d'actualisation juste après la définition de sa propriété tintColor (ou l'appelez-le à partir de viewDidLoad() (details here ). Il existe toutefois une solution de contournement simple en encapsulant l'appel beginRefreshing() dans une instruction defer (Swift 4):

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

Essayez de définir la teinteCouleur de votre UIRefreshControl dans viewWillAppear.

0
MacMark

Je travaille avec Xamarin C # (iOS 10) et j'ai constaté qu'une combinaison de toutes ces réponses est ce qui a réglé le problème pour moi. 

Dans ma ViewDidLoad, j'ai les éléments suivants:

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

Et plus tard, j'appelle par programme l’animation de rafraîchissement dans ma ViewDidAppear avec ce qui suit:

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

Notez que les paramètres du titre et du bloc d’animation attribués sont les éléments qui me manquaient pour que ma RefreshControl puisse prendre ma couleur blanche.

Merci à tous ceux qui ont contribué à cette question.

0
Matthew

Définissez manuellement le contenu du décalage pour votre tableView/scrollView avant de commencer à tourner:

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

L'utilisation de UIView.animate n'a pas fonctionné pour moi sur Swift 4.

Voici ce que j'ai fini par utiliser

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
Marcio Granzotto

j'ai trouvé du travail autour, j'espère que cela fonctionne pour vous 

 [_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
khaled