web-dev-qa-db-ja.com

iOS 7 UIRefreshControl tintColorがbeginRefreshingで機能しない

UIRefreshControl(iOS 7でビルド)でtintColorを設定しようとしています。ストーリーボードで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.P.S:サンプルプロジェクトを作成しましたが、同じバグがあるのか​​、コードに問題があるのか​​教えてもらえますか?リンクは次のとおりです。 http://d.pr/f/pGrV

どうもありがとう !

73
Noé Malzieu

ちょっと、ちょうどこの問題につまずいた。

興味深いことに、まず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

52
William George

迅速な解決策! 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()
23
Fox5150

@ 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に関連付けられたメソッドです。

8
jpsim

これらの答えはどれも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
Richard Sim

迅速:

私はSwift and> 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
arm0nic

TintColorの問題の解決策:これをviewDidLoadに追加します

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

BeginRefreshを手動で呼び出すと、白いインジケーターが表示されます。

3
Artjom Zabelin

以前の回答のいくつかを組み合わせました。これは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
    })        
}
3
Wendy Chu

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()
    }
}
3
Sefa Ayçiçek

このハックは非常に効果的です

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用に開発しましたが、同じ問題に遭遇しました。

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

私の更新方法は次のようになります。

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をプログラムで呼び出します。属性タイトルを設定する前は、スピナーは黒だったでしょう。これで適切な赤色になりました。

この「ハック/修正」には2番目のバグもあることに注意してください。初めて更新すると、AttributedTitleが表示されないことがわかります。 2番目(、3番目、4番目、...)の時間を更新すると、タイトルが正しく表示されます。ただし、タイトルが必要ない場合は、空の文字列で初期化するだけです。これは大きな問題ではありません。

これが他の人にも役立つことを願っています。

1
Thomas De Wilde

この問題を修正するドロップイン IRefreshControl + beginRefreshing category を作成しました。

簡単に言うと、tintColorの問題を修正し、手動でtableViewがcontentOffsetを調整して、更新コントロールが表示されるようにします。してみてください :)

0
Hlung

設定するとき

tableView.refreshControl = refreshControl 

何回か、refreshControlが毎回異なるインスタンスである場合、リフレッシュコントロールの色が常に黒で、色合いの色を異なる値に設定しても問題が解決しませんでした。

tableView.refreshControl = refreshControlを1回だけ設定し、非表示にする必要がある場合は、このスレッドで詳細をアルファ値に設定します。

IRefreshControlを「非表示」にする方法

0
Paul T.

これは、tintColorプロパティを設定した直後にリフレッシュコントロールでbeginRefreshing()を呼び出した場合(またはviewDidLoad()から呼び出した場合に発生するバグです(詳細 こちら )。ただし、deferステートメント内にbeginRefreshing()呼び出しをラップすることにより、簡単な回避策があります(Swift 4):

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

ViewWillAppearでUIRefreshControlのtintColorを設定してみてください。

0
MacMark

私は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が白い色合いをとるために欠けていた部分でした。

この質問に貢献してくれたすべての人に感謝します。

0
Matthew

スピンを開始する前に、tableView/scrollViewのコンテンツオフセットを手動で設定します。

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

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