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 目录下。
实现步骤如下:
- #import “RCTScrollableProtocol.h” 在自己的下拉刷新控件中导入该头文件,然后实现RCTCustomRefreshContolProtocol协议,并添加属性:
@property (nonatomic, copy) RCTDirectEventBlock onRefresh;
- 根据自己的下拉刷新控件实现setRefreshing方法,因为MJRefresh在内部实现了绝大部分,所以下拉刷新的时候不需要我做处理,我只需要在refreshing状态变为false的时候停止刷新即可,所以我的实现如下:
- (void)setRefreshing:(BOOL)refreshing
if(self.isRefreshing && refreshing == NO)
[self endRefreshing];
return ;
- 打开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方法,否则报错。
- 打开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
- 在集成过程中发现布局异常,添加进去之后并没有重新布局,所以在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-第三方之react-native-pull 下拉刷新上拉加载