アプリにはすでに5つのUIScrollView
があり、すべてが複数の.xib
ファイル。ここで、UIRefreshControl
を使用します。 UITableViewControllers(UIRefreshControlクラスリファレンスごと)で使用するように構築されています。 5つのUIScrollView
がすべて機能する方法をやり直したくありません。 UIRefreshControl
でUIScrollView
を使用しようとしましたが、いくつかの点を除いて期待どおりに機能します。
更新イメージがローダーに変わった直後に、UIScrollView
が約10ピクセル下にジャンプします。これは、UIScrollview
を非常にゆっくりと下にドラッグする場合にのみ発生します。
下にスクロールしてリロードを開始したら、UIScrollView
を放すと、UIScrollView
はそのままになります。リロードが完了すると、UIScrollView
はアニメーションなしで最上部にジャンプします。
ここに私のコードがあります:
-(void)viewDidLoad
{
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[myScrollView addSubview:refreshControl];
}
-(void)handleRefresh:(UIRefreshControl *)refresh {
// Reload my data
[refresh endRefreshing];
}
時間を節約し、UIRefreshControl
をUIScrollView
で使用する方法はありますか?
ありがとうございました!!!
UIRefreshControl
を扱うUIScrollView
を取得しました:
- (void)viewDidLoad
{
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
scrollView.userInteractionEnabled = TRUE;
scrollView.scrollEnabled = TRUE;
scrollView.backgroundColor = [UIColor whiteColor];
scrollView.contentSize = CGSizeMake(500, 1000);
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(testRefresh:) forControlEvents:UIControlEventValueChanged];
[scrollView addSubview:refreshControl];
[self.view addSubview:scrollView];
}
- (void)testRefresh:(UIRefreshControl *)refreshControl
{
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"Refreshing data..."];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:3];//for 3 seconds, prevent scrollview from bouncing back down (which would cover up the refresh view immediately and stop the user from even seeing the refresh text / animation)
dispatch_async(dispatch_get_main_queue(), ^{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMM d, h:mm a"];
NSString *lastUpdate = [NSString stringWithFormat:@"Last updated on %@", [formatter stringFromDate:[NSDate date]]];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdate];
[refreshControl endRefreshing];
NSLog(@"refresh end");
});
});
}
別のスレッドでデータ更新を行う必要があります。そうしないと、メインスレッド(UIがUIの更新に使用する)がロックされます。そのため、メインスレッドがデータの更新で忙しい間、UIもロックアップまたはフリーズされ、スムーズなアニメーションやスピナーは表示されません。
編集:OK、私はOPと同じことをやっていて、それにいくつかのテキストを追加しました(つまり、「Pull to Refresh」)、そのテキストを更新するにはメインスレッドに戻る必要があります。
更新された回答。
上記の答えに加えて、状況によってはcontentSizeを設定できない場合(おそらく自動レイアウトを使用しますか?)またはcontentSizeの高さがUIScrollViewの高さ以下である場合があります。これらの場合、UIScrollViewがバウンスしないため、UIRefreshControlは機能しません。
これを修正するには、プロパティalwaysBounceVerticalを[〜#〜] true [〜#〜]に設定します。
IOS 10以降をサポートできるほど幸運な場合は、refreshControl
のUIScrollView
を簡単に設定できます。これは、以前に存在したrefreshControl
on UITableView
と同じように機能します。
C#/ Monotouchでこれを行う方法を次に示します。 C#のサンプルはどこにも見つからないので、ここにあります。
public override void ViewDidLoad ()
{
//Create a scrollview object
UIScrollView MainScrollView = new UIScrollView(new RectangleF (0, 0, 500, 600));
//set the content size bigger so that it will bounce
MainScrollView.ContentSize = new SizeF(500,650);
// initialise and set the refresh class variable
refresh = new UIRefreshControl();
refresh.AddTarget(RefreshEventHandler,UIControlEvent.ValueChanged);
MainScrollView.AddSubview (refresh);
}
private void RefreshEventHandler (object obj, EventArgs args)
{
System.Threading.ThreadPool.QueueUserWorkItem ((callback) => {
InvokeOnMainThread (delegate() {
System.Threading.Thread.Sleep (3000);
refresh.EndRefreshing ();
});
});
}
ジャンプの問題については、 ティムノーマンの答え で解決します。
Swift2を使用している場合、Swiftバージョンです:
import UIKit
class NoJumpRefreshScrollView: UIScrollView {
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
override var contentInset:UIEdgeInsets {
willSet {
if self.tracking {
let diff = newValue.top - self.contentInset.top;
var translation = self.panGestureRecognizer.translationInView(self)
translation.y -= diff * 3.0 / 2.0
self.panGestureRecognizer.setTranslation(translation, inView: self)
}
}
}
}
Swift 3:
override func viewDidLoad() {
super.viewDidLoad()
let scroll = UIScrollView()
scroll.isScrollEnabled = true
view.addSubview(scroll)
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: .valueChanged)
scroll.addSubview(refreshControl)
}
func pullToRefresh(_ refreshControl: UIRefreshControl) {
// Update your conntent here
refreshControl.endRefreshing()
}
UIRefreshControl
内でUIScrollView
が適切に動作するようにしました。 UIScrollView
を継承し、contentInsetの変更をブロックし、contentOffsetセッターをオーバーライドしました。
class ScrollViewForRefreshControl : UIScrollView {
override var contentOffset : CGPoint {
get {return super.contentOffset }
set {
if newValue.y < -_contentInset.top || _contentInset.top == 0 {
super.contentOffset = newValue
}
}
}
private var _contentInset = UIEdgeInsetsZero
override var contentInset : UIEdgeInsets {
get { return _contentInset}
set {
_contentInset = newValue
if newValue.top == 0 && contentOffset.y < 0 {
self.setContentOffset(CGPointZero, animated: true)
}
}
}
}
iOS 1 UIScrollViewはすでにrefreshControlプロパティを持っていますなので。このrefreshControlは、UIRefereshControlを作成し、このプロパティに割り当てたときに表示されます。
UIRefereshControlをサブビューとして追加するno needがあります。
func configureRefreshControl () {
// Add the refresh control to your UIScrollView object.
myScrollingView.refreshControl = UIRefreshControl()
myScrollingView.refreshControl?.addTarget(self, action:
#selector(handleRefreshControl),
for: .valueChanged)
}
@objc func handleRefreshControl() {
// Update your content…
// Dismiss the refresh control.
DispatchQueue.main.async {
self.myScrollingView.refreshControl?.endRefreshing()
}
}
UIRefreshControlオブジェクトは、任意のUIScrollViewオブジェクトにアタッチする標準コントロールです
https://developer.Apple.com/documentation/uikit/uirefreshcontrol のコードと引用
ジャンプの問題の場合、オーバーライドcontentInsetはiOS 9の前にのみ解決します。ジャンプの問題を回避する方法を試しました。
let scrollView = UIScrollView()
let refresh = UIRefreshControl()
// scrollView.refreshControl = UIRefreshControl() this will cause the jump issue
refresh.addTarget(self, action: #selector(handleRefreshControl), for: .valueChanged)
scrollView.alwaysBounceVertical = true
//just add refreshControl and send it to back will avoid jump issue
scrollView.addSubview(refresh)
scrollView.sendSubviewToBack(refresh)
iOS 9 10 11などで動作し、Apple(Apple)が問題を解決することを願っています。