xcode Custom UIRefreshControl를 이용한 새로고침2 (Pull to Refresh)

2019. 7. 16. 14:20 IOS/xcode | IOS

UIRefreshControl의 배경색을 바꿔주면서 하트 이미지를 회전 시켜 보았습니다.


   



UIRefreshControl 커스텀 사용법


1. SingleView Application 으로 프로젝트 생성

2. MainStoryboard에 TableView  생성




3. 소스코드 작성

ViewController.h에 UIRefreshControl 배경뷰, 로딩이미지, 로딩이미지의 배경 등을 선언합니다.


ViewController.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
    NSArray *array;
    UIRefreshControl *refreshControl;
}
 
@property (strong, nonatomic) IBOutlet UITableView *tableView;
 
// UIRefreshControl 배경
@property (strong, nonatomic) UIView *refreshColorView;
// 로딩이미지의 투명배경
@property (strong, nonatomic) UIView *refreshLoadingView;
// 로딩이미지
@property (strong, nonatomic) UIImageView *loadingImg;
// 리프레싱 하고 있는지 여부
@property (assign) BOOL isRefreshAnimating;
 
@end
 
 
 
cs


UIRefreshControl을  초기화합니다.

배경으로 사용 할 refreshColorView를 생성한 후 refreshControl에 addSubview 해줍니다.

회전시킬 로딩이미지뷰를 생성하여 로딩이미지배경뷰에 addSubView를 해준 후, 로딩이미지배경뷰를 refreshControl에 addSubview해줍니다.


refreshControl

L  배경 뷰(refreshColorView)

L 로딩이미지 배경 뷰

L 로딩이미지 뷰


그리고 리프레싱 중일 때의 동작할 함수를 addTarget을 이용하여 연결해주고, 이렇게 초기화 해 준 refreshControl을  tableView에 붙여줍니다.


ViewController.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * Custom RefreshControl 초기화
 */
- (void)initCustomRefreshControl {
    refreshControl = [[UIRefreshControl alloc] init];
    
    // UIRefreshControl 배경
    self.refreshColorView = [[UIView alloc] initWithFrame:refreshControl.bounds];
    self.refreshColorView.backgroundColor = [UIColor clearColor];
    self.refreshColorView.alpha = 0.30;
    
    // 로딩이미지의 투명배경
    self.refreshLoadingView = [[UIView alloc] initWithFrame:refreshControl.bounds];
    self.refreshLoadingView.backgroundColor = [UIColor clearColor];
    
    // 로딩 이미지
    self.loadingImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ic_favorite_18pt.png"]];
    
    [self.refreshLoadingView addSubview:self.loadingImg];
    self.refreshLoadingView.clipsToBounds = YES;
    
    // 기존 로딩이미지 icon 숨기기
    refreshControl.tintColor = [UIColor clearColor];
    
    [refreshControl addSubview:self.refreshColorView];
    [refreshControl addSubview:self.refreshLoadingView];
    
    self.isRefreshAnimating = NO;
    
    // 리프레시 이벤트 연결
    [refreshControl addTarget:self action:@selector(handleRefreshForCustom:) forControlEvents:UIControlEventValueChanged];
 
    [_tableView addSubview:refreshControl];
}
cs


새로고침 할  동작을 구현해주고, 그 후에 endRefreshing을 호출해줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
 * 리프레시 이벤트 for Custom
 */
- (void)handleRefreshForCustom:(UIRefreshControl *)sender {
    
    // -- DO SOMETHING AWESOME (... or just wait 3 seconds) --
    // This is where you'll make requests to an API, reload data, or process information
    double delayInSeconds = 3.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        
        // When done requesting/reloading/processing invoke endRefreshing, to close the control
        [refreshControl endRefreshing];
    });
    // -- FINISHED SOMETHING AWESOME, WOO! --
}
cs


테이블뷰 스크롤 이벤트를 이용해서 로딩이미지의 동작을 변경 할 수 있습니다.

저는 로딩이미지를 가운데 위치시키고 회전애니메이션을 주었습니다. 이 외에 더 다양한 효과를 이곳에서 적용할 수 있습니다.


테이블뷰를 위에서 아래로 당길 때 로딩이미지의 위치를 가운데로 위치시켜주고,

당긴 거리가 어느정도 이상되면 리프레싱 이벤트가 발생하는데 이 때 회전 애니메이션을 적용해줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
 * 테이블뷰 스크롤시 이벤트
 * 로딩이미지 위치 계산
 */
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (!isCustom) {
        return;
    }
    
    // RefreshControl 크기
    CGRect refreshBounds = refreshControl.bounds;
    
    // 테이블뷰 당겨진 거리 >= 0
    CGFloat pullDistance = MAX(0.0- refreshControl.frame.origin.y);
    
    // 테이블뷰이 Width의 중간
    CGFloat midX = _tableView.frame.size.width / 2.0;
    
    // 로딩이미지 RefreshControl의 중간에 위치하도록 계산
    CGFloat loadingImgHeight = self.loadingImg.bounds.size.height;
    CGFloat loadingImgHeightHalf = loadingImgHeight / 2.0;
    
    CGFloat loadingImgWidth = self.loadingImg.bounds.size.width;
    CGFloat loadingImgWidthHalf = loadingImgWidth / 2.0;
    
    CGFloat loadingImgY = pullDistance / 2.0 - loadingImgHeightHalf;
    CGFloat loadingImgX = midX - loadingImgWidthHalf;
    
    CGRect loadingImgFrame = self.loadingImg.frame;
    loadingImgFrame.origin.x = loadingImgX;
    loadingImgFrame.origin.y = loadingImgY;
    
    self.loadingImg.frame = loadingImgFrame;
    
    refreshBounds.size.height = pullDistance;
    
    self.refreshColorView.frame = refreshBounds;
    self.refreshLoadingView.frame = refreshBounds;
    
    if (refreshControl.isRefreshing && !self.isRefreshAnimating) {
        [self animateRefreshView];
    }
}
cs


새로고침을 할 동안 로딩이미지를 회전하는 애니메이션입니다. 그리고 동시에 refreshControl의 배경색을 바꿔주었습니다.

그리고 새로 고침이 끝난 후 애니메이션을 중지합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * 애니메이션
 * 로딩이미지 회전
 */
- (void)animateRefreshView {
    NSArray *colorArray = @[[UIColor redColor],[UIColor blueColor],[UIColor purpleColor],[UIColor cyanColor],[UIColor orangeColor],[UIColor magentaColor]];
    static int colorIndex = 0;
    
    self.isRefreshAnimating = YES;
    
    [UIView animateWithDuration:0.3
                          delay:0
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                         // 로딩이미지 회전 by M_PI_2 = PI/2 = 90 degrees
                         [self.loadingImg setTransform:CGAffineTransformRotate(self.loadingImg.transform, M_PI_2)];
                    
                         self.refreshColorView.backgroundColor = [colorArray objectAtIndex:colorIndex];
                         colorIndex = (colorIndex + 1) % colorArray.count;
                     }
                     completion:^(BOOL finished) {
                         if (refreshControl.isRefreshing) {
                             [self animateRefreshView];
                         } else {
                             [self resetAnimation];
                         }
                     }];
}
 
/**
 * 애니메이션 중지
 */
- (void)resetAnimation {
    // Reset our flags and background color
    self.isRefreshAnimating = NO;
    self.refreshColorView.backgroundColor = [UIColor clearColor];
}



출처: https://jepark-diary.tistory.com/16?category=874567 [JEP's Diary]