refresh

下拉刷新控件目前比较火的有好几种,本人用过MJRefresh 和 SVPullToRefresh,相对而言,前者比后者可定制化、拓展新都更高一点。因此本文着重讲一下MJRefresh的简单用法。

广泛性分为6种使用场景,分别对应:默认、动画图片、隐藏时间、隐藏时间和状态、自定义文字说明、以及自定义刷新控件。

 

下面就各种场景分别讲一下:

1、默认场景

 

 包含刷新菊花、下拉说明、时间

使用代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma mark UITableView + 下拉刷新 默认
- ( void )example01
{
     __weak __typeof( self ) weakSelf =  self ;
     
     // 设置回调(一旦进入刷新状态就会调用这个refreshingBlock)
     self .tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
         [weakSelf loadNewData];
     }];
     
     // 马上进入刷新状态
     [ self .tableView.mj_header beginRefreshing];
}

  

2、使用动画图片

 

 

PS:这里的动画并不是用gif实现的,而是利用序列帧(即若干图片组成一个不同状态下的图片数组,然后根据位置显示不同图片)去展现。

1
2
3
4
5
6
7
8
9
#pragma mark UITableView + 下拉刷新 动画图片
- ( void )example02
{
     // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
     self .tableView.mj_header = [MJChiBaoZiHeader headerWithRefreshingTarget: self  refreshingAction: @selector (loadNewData)];
     
     // 马上进入刷新状态
     [ self .tableView.mj_header beginRefreshing];
}

这里用大众点评吃包子图片为例,新建一个自定义类 MJChiBaoZiHeader,继承:MJRefreshGifHeader

#import "MJRefreshGifHeader.h" 

@interface MJChiBaoZiHeader : MJRefreshGifHeader 

@end

然后重写prepare方法,代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- ( void )prepare
{
     [ super  prepare];
     
     // 设置普通状态的动画图片
     NSMutableArray  *idleImages = [ NSMutableArray  array];
     for  ( NSUInteger  i = 1; i<=60; i++) {
         UIImage *image = [UIImage imageNamed:[ NSString  stringWithFormat:@ "dropdown_anim__000%zd" , i]];
         [idleImages addObject:image];
     }
      [ self  setImages:idleImages forState:MJRefreshStateIdle];
     
     // 设置即将刷新状态的动画图片(一松开就会刷新的状态)
     NSMutableArray  *refreshingImages = [ NSMutableArray  array];
     for  ( NSUInteger  i = 1; i<=3; i++) {
         UIImage *image = [UIImage imageNamed:[ NSString  stringWithFormat:@ "dropdown_loading_0%zd" , i]];
         [refreshingImages addObject:image];
     }
     [ self  setImages:refreshingImages forState:MJRefreshStatePulling];
     
     // 设置正在刷新状态的动画图片
     [ self  setImages:refreshingImages forState:MJRefreshStateRefreshing];
}

关键点就是这里的两个图片数组,60是因为下拉控件默认拉动距离就是60距离,这里比较严谨,利用60张不同图片去对应每个距离点,当然实际中,我们可以缩减,不需要精确到每个距离点对应一张图片,这里个人自己决定。

这里需要先了解下,下拉的五种状态。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/** 刷新控件的状态 */
typedef  NS_ENUM ( NSInteger , MJRefreshState) {
     /** 普通闲置状态 */
     MJRefreshStateIdle = 1,
     /** 松开就可以进行刷新的状态 */
     MJRefreshStatePulling,
     /** 正在刷新中的状态 */
     MJRefreshStateRefreshing,
     /** 即将刷新的状态 */
     MJRefreshStateWillRefresh,
     /** 所有数据加载完毕,没有更多的数据了 */
     MJRefreshStateNoMoreData
};

  

1
idleImages图片数组对应闲置下拉状态,表示下拉到临界值前的展示图片。
1
refreshingImages图片数组对应正在刷新时的动画展示图片,一般这里需要3~5张图片去模拟动画。<br><br>重写完<span  class = "s1" >prepare方法,就可以实现动画了。<br><br></span>

3、下拉刷新 隐藏时间

 

 

这里与默认的区别就是不显示上次刷新时间,使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma mark UITableView + 下拉刷新 隐藏时间
- ( void )example03
{
     // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
     MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget: self  refreshingAction: @selector (loadNewData)];
     
     // 设置自动切换透明度(在导航栏下面自动隐藏)
     header.automaticallyChangeAlpha =  YES ;
     
     // 隐藏时间
     header.lastUpdatedTimeLabel.hidden =  YES ;
     
     // 马上进入刷新状态
     [header beginRefreshing];
     
     // 设置header
     self .tableView.mj_header = header;
}

 

4、下拉刷新 隐藏状态和时间

这个场景一般适用于只需要动画展示,简洁清爽,也是用的蛮多的。

同样,处理很简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma mark UITableView + 下拉刷新 隐藏状态和时间
- ( void )example04
{
     // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
     MJChiBaoZiHeader *header = [MJChiBaoZiHeader headerWithRefreshingTarget: self  refreshingAction: @selector (loadNewData)];
     
     // 隐藏时间
     header.lastUpdatedTimeLabel.hidden =  YES ;
 
     // 隐藏状态
     header.stateLabel.hidden =  YES ;
     
     // 马上进入刷新状态
     [header beginRefreshing];
     
     // 设置header
     self .tableView.mj_header = header;
}

  

5、下拉刷新 自定义文字

想自己DIY个性文字描述,一样很简单。

不管是文字text、文字大小、还是颜色都一句话搞定。

 

 

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
#pragma mark UITableView + 下拉刷新 自定义文字
- ( void )example05
{
     // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
     MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget: self  refreshingAction: @selector (loadNewData)];
     
     // 设置文字
     [header setTitle:@ "快扯我,快点"  forState:MJRefreshStateIdle];
     [header setTitle:@ "数据要来啦"  forState:MJRefreshStatePulling];
     [header setTitle:@ "服务器正在狂奔 ..."  forState:MJRefreshStateRefreshing];
     
     // 设置字体
     header.stateLabel.font = [UIFont systemFontOfSize:15];
     header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:14];
 
     // 设置颜色
     header.stateLabel.textColor = [UIColor redColor];
     header.lastUpdatedTimeLabel.textColor = [UIColor grayColor];
     
     // 马上进入刷新状态
     [header beginRefreshing];
     
     // 设置刷新控件
     self .tableView.mj_header = header;
}

  

6、下拉刷新 自定义刷新控件

上面的都不够玩,怎么办,没关系,还有最后一种更定制化的方法:自己加控件样式。

 

 

这里不限于任何控件,我们可以在头部的这片区域,尽情添加Subviews,但记住一点,高度千万不要吵过header高度(默认60)。

除了控件,甚至可以自己绘制动画等等。

实现原理:同样先自定义自己的类,继承 MJRefreshHeader

重写 prepare 方法,再重写 placeSubviews 方法 设置位置。

代码:

a、定义控件属性

1
2
3
4
5
6
@interface  MJDIYHeader()
@property  (weak,  nonatomic ) UILabel *label;
@property  (weak,  nonatomic ) UISwitch *s;
@property  (weak,  nonatomic ) UIImageView *logo;
@property  (weak,  nonatomic ) UIActivityIndicatorView *loading;
@end

b、重写prepare方法

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
#pragma mark 在这里做一些初始化配置(比如添加子控件)
- ( void )prepare
{
     [ super  prepare];   
     // 设置控件的高度
     self .mj_h = 50;
     
     // 添加label
     UILabel *label = [[UILabel alloc] init];
     label.textColor = [UIColor colorWithRed:1.0 green:0.5 blue:0.0 alpha:1.0];
     label.font = [UIFont boldSystemFontOfSize:16];
     label.textAlignment =  NSTextAlignmentCenter ;
     [ self  addSubview:label];
     self .label = label;
     
     // 打酱油的开关
     UISwitch *s = [[UISwitch alloc] init];
     [ self  addSubview:s];
     self .s = s;
     
     // logo
     UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@ "Logo" ]];
     logo.contentMode = UIViewContentModeScaleAspectFit;
     [ self  addSubview:logo];
     self .logo = logo;
     
     // loading
     UIActivityIndicatorView *loading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
     [ self  addSubview:loading];
     self .loading = loading;
}

c、重写 placeSubviews 

1
2
3
4
5
6
7
8
9
10
11
12
#pragma mark 在这里设置子控件的位置和尺寸
- ( void )placeSubviews
{
     [ super  placeSubviews];
 
     self .label.frame =  self .bounds;
     
     self .logo.bounds = CGRectMake(0, 0,  self .bounds.size.width, 100);
     self .logo.center = CGPointMake( self .mj_w * 0.5, -  self .logo.mj_h + 20);
     
     self .loading.center = CGPointMake( self .mj_w - 30,  self .mj_h * 0.5);
}

d、根据下拉位移,自定义不同位移的控件展示,比如显示不同文字,颜色等

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
#pragma mark 监听控件的刷新状态
- ( void )setState:(MJRefreshState)state
{
     MJRefreshCheckState;
 
     switch  (state) {
         case  MJRefreshStateIdle:
             [ self .loading stopAnimating];
             [ self .s setOn: NO  animated: YES ];
             self .label.text = @ "赶紧下拉吖(开关是打酱油滴)" ;
             break ;
         case  MJRefreshStatePulling:
             [ self .loading stopAnimating];
             [ self .s setOn: YES  animated: YES ];
             self .label.text = @ "赶紧放开我吧(开关是打酱油滴)" ;
             break ;
         case  MJRefreshStateRefreshing:
             [ self .s setOn: YES  animated: YES ];
             self .label.text = @ "加载数据中(开关是打酱油滴)" ;
             [ self .loading startAnimating];
             break ;
         default :
             break ;
     }
}

 

上拉刷新加载其实和下拉是同理,只不过区别就是:

self.tableView.mj_header  变成 self.tableView.mj_footer,后面的类也由 

MJRefreshNormalHeader 变成  MJRefreshAutoNormalFooter。

实现原理是相同的。

 

参考链接、下载源码:https://github.com/CoderMJLee/MJRefresh

### Go语言中的Token刷新机制 在Go语言中,处理Token刷新的操作主要围绕着OAuth 2.0协议来设计。当涉及到使用`refresh token`去获取新的`access token`时,客户端会向认证服务器发送带有特定参数的HTTP POST请求[^2]。 对于具体的实现细节,在构建用于创建带自定义声明的新令牌实例方面,有一个函数名为`NewWithClaims`,此函数接受签名方法以及声明作为输入参数并返回一个待签发的令牌对象[^1]。然而,这并不是直接用来执行刷新逻辑的部分;而是负责初始化具有适当声明结构的新令牌实例的基础组件之一。 为了完成整个刷新流程,开发者通常会在应用层面上封装一层服务或者工具类来进行如下工作: - 构建包含必要字段(如`grant_type=refresh_token`)在内的表单数据体; - 发送POST请求至授权服务器所暴露出来的token端点; - 解析响应内容以提取新颁发下来的`access token`及其关联信息(比如有效期、scope等),同时也有可能获得更新后的`refresh token`; - 将上述解析得到的信息存储起来供后续业务调用所需。 ```go // 示例代码展示如何发起一次基于refresh token换取新access token的过程 func RefreshAccessToken(refreshToken string) (string, error) { client := &http.Client{} reqBody := url.Values{ "grant_type": {"refresh_token"}, "refresh_token": {refreshToken}, } resp, err := client.PostForm("https://example.com/oauth/token", reqBody) if err != nil { return "", fmt.Errorf("failed to post form: %v", err) } defer resp.Body.Close() var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return "", fmt.Errorf("failed to decode response body: %v", err) } accessToken, ok := result["access_token"].(string) if !ok || accessToken == "" { return "", errors.New("invalid access token received") } return accessToken, nil } ``` 通过这种方式,应用程序能够在不重新经历完整的身份验证过程的情况下延长用户的登录状态或保持API访问权限的有效性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值