iOS 7 UIRefreshControl tintColor funktioniert nicht für beginRefreshing

75

Ich versuche, auf meinem UIRefreshControl (basierend auf iOS 7) eine tintColor festzulegen. Ich habe die Aktualisierung für den tableViewController im Storyboard aktiviert und dann in meiner ViewController- viewDidLoadMethode Folgendes ausgeführt:

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

Wenn ich jetzt zum Aktualisieren ziehe, ist die Farbe des Aktualisierungssteuerelements tatsächlich rot:

redSpiny

Ich möchte, dass meine Ansicht automatisch aktualisiert wird, wenn sie angezeigt wird. Deshalb habe ich Folgendes getan:

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

Laut https://stackoverflow.com/a/16250679/1809736 wurde das Spinnrad nicht angezeigt , fügte ich hinzu

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

zu zwingen, es zu zeigen. Es zeigt es, aber jetzt ist es wieder in der Standardfarbe:

Geben Sie hier die Bildbeschreibung ein

Wenn ich versuche, manuell zu ziehen, um danach zu aktualisieren, ist es rot.

Ich habe versucht, es auf iOS6 zu erstellen, und es funktioniert wie es sollte. Ist das also ein iOS7-Fehler?

PS: Es ist kein Problem mit dem Simulator, ich habe versucht, es auf dem Gerät zu bauen, der gleiche Fehler.

PPS: Ich habe ein Beispielprojekt erstellt. Können Sie mir sagen, ob Sie denselben Fehler haben oder ob ein Problem in meinem Code vorliegt? Hier ist der Link: http://d.pr/f/pGrV

Danke vielmals !

Noé Malzieu
quelle
6
UIRefreshControl ist unter iOS7 sehr fehlerhaft. Ich schlage vor, Open Source zu verwenden oder vorerst mit den Bugs zu leben. Stellen
Leo Natan
5
Es ist fast so, als hätten sie mit iOS7 keine Zeit mehr. Es gibt auch Fehler mit dem UISearchViewController. Hoffentlich wird dies durch ein zukünftiges Update behoben.
James
8
IOS 8 hat immer noch diesen Fehler ... seltsam ...
Macistador
2
Auch iOS9. Hat jemand eine Lösung gefunden?
Oren
5
Gleiches gilt für iOS 11 :(
Pranoy C

Antworten:

54

Hey ist gerade auf genau dieses Problem gestoßen.

Interessanterweise habe ich meinen Code korrigiert, indem ich zuerst das contentOffset festgelegt und dann beginRefreshing aufgerufen habe

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

Möglicherweise möchten Sie diesen Prozess animieren:

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

Hoffe das hilft dir.

W.

William George
quelle
Dies funktioniert manchmal nicht, weil der Punkt beim Versetzen der Tabelle darin besteht, dass sie etwas Platz zum Versetzen hat, aber erst, nachdem Sie beginRefreshing aufgerufen haben ... wenn Sie sie versetzen, bevor sie nicht viel zu versetzen hat!
Newton_guima
2
Funktioniert wie angegeben. Es ist seltsam. Vielen Dank :)
Vlad Spreys
1
Es ist sehr wichtig, "beginRefreshing" nach dem Festlegen des contentOffset aufzurufen! (zumindest auf ios8)
Macistador
1
Ich habe eine Weile daran festgehalten, aber es stellte sich heraus, dass ich [myTableView setContentOffset ... animiert: JA] verwendet habe. Das hat bei mir nicht funktioniert. Stellen Sie den Versatz direkt ein und verwenden Sie stattdessen den UIView-Animationsblock wie oben.
Rick Roberts
Die Reihenfolge der Anrufe ist in der Tat wichtig. Seltsames Problem, das einen Kommentar "// ??? ***" in der Codedokumentation verdient.
SayeedHussain
26

SCHNELLE LÖSUNG! Fügen Sie den folgenden Code in Folgendes ein 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()
Fox5150
quelle
1
Vielen Dank, dies behebt einige Probleme für mich beim Laden von viewDidLoad. Die Auffrischungssteuerung hatte bei jedem ersten Gebrauch die falsche Höhe und Farbe.
Rob
8

Die Antwort von @ william-george brachte mich in die richtige Richtung, gab mir aber seltsame Probleme mit der automatischen Animation.

Hier ist die Version, die für mich funktioniert hat:

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

-refreshist die Methode an die gebunden UIRefreshControl.

jpsim
quelle
6

Fügen Sie eine Erweiterung für UIResfreshControl hinzu.

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 Ayçiçek
quelle
Im Vergleich zu anderen Lösungen hat diese Lösung funktioniert und sah besser aus. :) Danke Sefa und toller Trick.
Bruno Reis Portela
4

Keine dieser Antworten funktioniert für mich unter iOS8 korrekt. Die nächstgelegene ist die Antwort von @ jpsim, die jedoch während der Einblendanimation eine unansehnliche schwarze Aktualisierungssteuerung hinterlassen hat (sie würde zwischen Schwarz und im Verlauf der Animation überblenden ).

Die Lösung, die für mich funktioniert hat, bestand darin, dies sofort nach dem Erstellen des Aktualisierungssteuerelements in mein viewDidLoad einzufügen:

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

Um das UIRefreshControl programmgesteuert anzuzeigen:

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

Ich musste die Höhe des Aktualisierungssteuerelements speichern, da nachfolgende Aufrufe eine Höhe von 0 hatten, während es für den ersten Aufruf festgelegt wurde.

Richard Sim
quelle
1
Danke, könnten Sie mich darüber aufklären, dass dies nur mit -1 funktioniert? Ich mag keine magischen Zahlen ...
Rick van der Linde
Es ist keine magische Zahl, er ändert nur den Inhaltsversatz um einen vernachlässigbaren Betrag und ändert ihn dann zurück.
Eran Goldin
3

Lösung für das Problem mit tintColor: Fügen Sie dies in viewDidLoad hinzu

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

Jetzt haben Sie eine weiße Anzeige, wenn Sie beginRefresh manuell aufrufen.

Upvote
quelle
3

SCHNELL:

Ich benutze Swift und> iOS8. Die meisten der beschriebenen Problemumgehungen haben bei mir nicht funktioniert. So habe ich es zum Laufen gebracht:

In viewDidLoad:

customRefreshControl.tintColor = UIColor.clearColor()

Folgendes muss sich nicht in viewDidLoad befinden. Ich habe es in eine zusätzliche Funktion eingefügt, die jedes Mal aufgerufen wird, wenn ich die tableView aktualisiere:

private func startRefreshControlAnimation() {

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

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

}
Flocbit
quelle
3

Ich habe einige der vorherigen Antworten kombiniert. Dies funktioniert für mich unter iOS 9 und 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
    })        
}
Wendy Chu
quelle
2

Ich habe für iOS mit Xamarin (C #) entwickelt und bin auf dasselbe Problem gestoßen.

Ich reparierte die Färbung Ausgabe, durch die Einstellung AttributedTitleder 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");
}

Meine Update-Methode sieht folgendermaßen aus:

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

Einmal ViewDidAppearrufe ich anUpdate programmgesteuert an. Vor dem Festlegen des zugewiesenen Titels wäre mein Spinner schwarz gewesen. Jetzt hat es die richtige rote Farbe.

Es ist erwähnenswert, dass dieser 'Hack / Fix' auch einen zweiten Fehler mit sich bringt. Beim ersten Aktualisieren werden Sie feststellen, dass das AttributedTitlenicht angezeigt wird. Wenn Sie ein zweites (, drittes, viertes, ...) Mal aktualisieren, wird der Titel korrekt angezeigt. Wenn Sie jedoch keinen Titel möchten, initialisieren Sie ihn einfach mit einer leeren Zeichenfolge, und dies ist für Sie kein großes Problem.

Ich hoffe, dass dies für andere von Nutzen sein kann.

Thomas De Wilde
quelle
1

Dieser Hack funktioniert sehr gut

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
        }
    }
}
Andrey Gerashchenko
quelle
1

Ich arbeite mit Xamarin C # (iOS 10) und habe festgestellt, dass eine Kombination all dieser Antworten das Problem für mich behoben hat.

In meinem habe ViewDidLoadich folgendes:

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

Und später rufe ich programmgesteuert die Aktualisierungsanimation in meinem ViewDidAppearmit folgendem auf:

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

Beachten Sie, dass die Einstellung des zugewiesenen Titels und des Animationsblocks die Teile waren, die mir fehlten RefreshControl, um meine weiße Tönungsfarbe anzunehmen.

Vielen Dank an alle, die zu dieser Frage beigetragen haben.

Matthew
quelle
0

Versuchen Sie, die Farbtonfarbe Ihres UIRefreshControl in viewWillAppear festzulegen.

MacMark
quelle
0

Ich habe einige Work Around gefunden. Ich hoffe, es funktioniert für Sie

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

Ich habe eine Dropdown- Kategorie für UIRefreshControl + beginRefreshing erstellt , die dieses Problem behebt.

Kurz gesagt, das Problem mit tintColor wird behoben, und tableView passt contentOffset manuell an, um sicherzustellen, dass das Aktualisierungssteuerelement sichtbar ist. Bitte versuche :)

Hlung
quelle
0

Dies ist ein Fehler, der auftritt, wenn beginRefreshing()das Aktualisierungssteuerelement direkt nach dem Festlegen seiner tintColorEigenschaft (oder dem Aufrufen von viewDidLoad()(Details hier )) beginRefreshing()aufgerufen wird . Es gibt jedoch eine einfache Problemumgehung, indem der Aufruf in eine deferAnweisung eingeschlossen wird (Swift 4):

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

Wenn ich setze

tableView.refreshControl = refreshControl 

mehrmals, wenn refreshControl jedes Mal eine andere Instanz ist, hatte ich das Problem, dass die Farbe der Aktualisierungssteuerung immer schwarz war und das Einstellen der Farbtonfarbe auf einen anderen Wert nicht half.

Damit ich tableView.refreshControl = refreshControlnur einmal setze und wenn ich es ausblenden muss, setze ich den Alpha-Wert, weitere Details in diesem Thread:

Wie "verstecke" ich ein UIRefreshControl?

Paul T.
quelle
0

Die Verwendung UIView.animatehat bei Swift 4 bei mir nicht funktioniert.

Folgendes habe ich letztendlich verwendet

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()
    }
}
Marcio Granzotto
quelle
0

Stellen Sie den Inhaltsversatz für Ihre tableView / scrollView manuell ein, bevor Sie mit dem Drehen beginnen:

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

Erzwingen Sie, dass setTintColor im Hauptthread ausgeführt wird. (Haupt-Thread aktualisiert die Benutzeroberfläche).

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