RN下拉刷新:修改RN代码,集成iOS原生下拉刷新

Posted 人生如梦91

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RN下拉刷新:修改RN代码,集成iOS原生下拉刷新相关的知识,希望对你有一定的参考价值。

在之前我已经用javascript实现了下拉刷新,详见RN下拉刷新(一):使用JavaScript实现,但是还遗留了一个问题无法解决,该篇就来解决该问题

使用Javascript实现的下拉刷新,在列表先上滑再下滑的情况下下拉刷新无法使用,必须松开手指后再次滑动才可以正常下拉刷新,我本来想着这样算了,好不容易实现了一个下拉刷新。但是大佬非觉得不行,所以最终还是通过修改RN的源代码集成原生的下拉刷新。原生的下拉刷新是继承自MJRefreshHeader,修改起来也很简单,改动也不大。

RN的源代码位于 /项目目录/RN/node_modules/react-native/React/Views 目录下。

实现步骤如下:

  1. #import “RCTScrollableProtocol.h” 在自己的下拉刷新控件中导入该头文件,然后实现RCTCustomRefreshContolProtocol协议,并添加属性:
@property (nonatomic, copy) RCTDirectEventBlock onRefresh;
  1. 根据自己的下拉刷新控件实现setRefreshing方法,因为MJRefresh在内部实现了绝大部分,所以下拉刷新的时候不需要我做处理,我只需要在refreshing状态变为false的时候停止刷新即可,所以我的实现如下:
- (void)setRefreshing:(BOOL)refreshing

    if(self.isRefreshing && refreshing == NO) 
        [self endRefreshing];
    
    
    return ;

  1. 打开RCTRefreshControlManager.m文件,修改view方法,将下拉刷新控件替换成自己的控件,如下所示:
@implementation RCTRefreshControlManager

RCT_EXPORT_MODULE()

- (UIView *)view

  return [[RCTRefreshGifHeader alloc] init];


RCT_EXPORT_VIEW_PROPERTY(onRefresh, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(refreshing, BOOL)
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor)
RCT_EXPORT_VIEW_PROPERTY(refreshStyle, NSInteger)

@end

其中RCTRefreshGifHeader是我自己的下拉刷新控件,refreshStyle是我自己导出的样式属性,因为我们的下拉刷新有两种样式,黑色和白色,该属性用于在RN指定下拉刷新的样式。导出属性后需要在下拉刷新控件中添加setRefreshStyle方法,否则报错。

  1. 打开RCTScrollView.m文件,在insertReactSubview方法中,将类型替换成自己的下拉刷新控件,如下所示:
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex

  [super insertReactSubview:view atIndex:atIndex];
#if !TARGET_OS_TV
  if ([view conformsToProtocol:@protocol(RCTCustomRefreshContolProtocol)]) 
    [_scrollView setCustomRefreshControl:(UIView<RCTCustomRefreshContolProtocol> *)view];
    if (![view isKindOfClass:[RCTRefreshGifHeader class]]
        && [view conformsToProtocol:@protocol(UIScrollViewDelegate)]) 
      [self addScrollListener:(UIView<UIScrollViewDelegate> *)view];
    
   else
#endif
  1. 在集成过程中发现布局异常,添加进去之后并没有重新布局,所以在RCTScrollView.m文件中的layoutsubview中我添加了一句setNeedsLayout,如下所示:
- (void)layoutSubviews

  [super layoutSubviews];
  RCTAssert(self.subviews.count == 1, @"we should only have exactly one subview");
  RCTAssert([self.subviews lastObject] == _scrollView, @"our only subview should be a scrollview");

#if !TARGET_OS_TV
  // Adjust the refresh control frame if the scrollview layout changes.
  UIView<RCTCustomRefreshContolProtocol> *refreshControl = _scrollView.customRefreshControl;
  if (refreshControl && refreshControl.isRefreshing) 
    refreshControl.frame = (CGRect)_scrollView.contentOffset, _scrollView.frame.size.width, refreshControl.frame.size.height;
  else 
      [refreshControl setNeedsLayout];
  
#endif

  [self updateClippedSubviews];


其他的部分则需要根据自己的下拉刷新做不同的修改,在此也不过多讲述,最终效果如下:

果然原生效果比RN体验强太多了。

以上是关于RN下拉刷新:修改RN代码,集成iOS原生下拉刷新的主要内容,如果未能解决你的问题,请参考以下文章

RN下拉刷新:使用JavaScript实现

RN下拉刷新:使用JavaScript实现

RN-第三方之react-native-pull 下拉刷新上拉加载

RN组件备忘录

原生的微信小程序有下拉刷新功能,怎么取消下拉刷新?不希望它刷新

快速集成上拉下拉刷新