Program Club

UIScrollView에서 UIRefreshControl을 사용할 수 있습니까?

proclub 2020. 10. 31. 10:17
반응형

UIScrollView에서 UIRefreshControl을 사용할 수 있습니까?


UIScrollView내 앱에는 이미 약 5 개의 .xib파일이 있으며 모두 여러 파일을 로드 합니다. 이제 UIRefreshControl. UITableViewControllers (UIRefreshControl 클래스 참조에 따라)와 함께 사용하도록 빌드되었습니다. 5 가지가 모두 어떻게 UIScrollView작동 하는지 다시하고 싶지 않습니다 . 나는 이미 UIRefreshControl내에서 사용하려고 시도 UIScrollView했으며 몇 가지를 제외하고는 예상대로 작동합니다.

  1. 새로 고침 이미지가 로더로 전환 된 직후에 UIScrollView약 10 픽셀 아래로 점프하는데, 이는 UIScrollview매우 천천히 아래 로 드래그하는 데 매우주의 할 때만 발생하지 않습니다 .

  2. 아래로 스크롤하여 재 장전을 시작한 다음를 놓으면는 내가 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];
}

많은 시간을 절약하고 a를 사용할 수있는 방법 UIRefreshControlUIScrollView있습니까?

감사합니다!!!


iOS 10 부터 UIScrollView 에는 이미 refreshControl 속성이 있습니다. 이 refreshControl은 UIRefereshControl을 만들고이 속성에 할당 할 때 나타납니다.

없습니다 필요 더 이상 하위 뷰로 UIRefereshControl을 추가 할 수는.

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의 코드 및 견적


나는 다음 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도 잠기거나 고정되어 부드러운 애니메이션이나 스피너가 표시되지 않습니다.

편집 : 좋아, 나는 OP와 똑같은 일을하고있다. 그리고 나는 그것에 약간의 텍스트를 추가했다 (즉, "새로 고침") 그리고 그것은 그 텍스트를 업데이트하기 위해 메인 스레드로 돌아갈 필요가있다.

답변이 업데이트되었습니다.


위의 답변에 추가하면 일부 상황에서 contentSize를 설정할 수 없거나 (아마도 자동 레이아웃을 사용합니까?) contentSize의 높이가 UIScrollView의 높이보다 작거나 같습니다. 이 경우 UIScrollView가 바운스되지 않기 때문에 UIRefreshControl이 작동하지 않습니다.

이 문제를 해결하려면 alwaysBounceVertical 속성 TRUE로 설정하십시오 .


당신이 운이 정도로는 아이폰 OS 10 +를 지원하는 경우에 경우에, 당신은 지금 간단하게 설정할 수 refreshControl의를 UIScrollView. 이것은 이전에 기존과 동일한 방식으로 작동 refreshControlUITableView.


다음은 C # / Monotouch에서이를 수행하는 방법입니다. 어디에서나 C #에 대한 샘플을 찾을 수 없으므로 여기 있습니다. 감사합니다 Log139!

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

Jumping 문제의 경우 Tim Norman의 답변으로 해결됩니다.

swift2를 사용하는 경우 다음은 빠른 버전입니다.

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 setter를 재정의했습니다.

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

For the Jumping issue, override contentInset only solves it before iOS 9. I just tried a way to avoid jump issue:

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)

works on iOS 9 10 11 and so on,and I hope they(Apple) just fix the issue.


You can simply create an instance of the refresh control and add it at the top of the scroll view. then, in the delegate methods you adjust its behavior to your requirements.

참고URL : https://stackoverflow.com/questions/14905382/can-i-use-a-uirefreshcontrol-in-a-uiscrollview

반응형