作者 周泳恩

init

  1 +import React, {Component} from 'react';
  2 +import {VirtualizedList, FlatList,Platform} from 'react-native';
  3 +class MJFlatList extends FlatList {
  4 + render() {
  5 + return (
  6 + <VirtualizedList
  7 + {...this.props}
  8 + renderItem={this._renderItem}
  9 + getItem={this._getItem}
  10 + getItemCount={this._getItemCount}
  11 + keyExtractor={this._keyExtractor}
  12 + ref={this._captureRef}
  13 + onViewableItemsChanged={
  14 + this.props.onViewableItemsChanged && this._onViewableItemsChanged
  15 + }
  16 + />
  17 + );
  18 + }
  19 +}
  20 +
  21 +module.exports = Platform.OS === 'ios' ? MJFlatList : FlatList;
  1 +import React,{Component} from 'react';
  2 +import {
  3 + findNodeHandle,
  4 + NativeModules,
  5 + Platform,
  6 + ListView,
  7 +} from 'react-native';
  8 +import MJScrollView from './MJScrollView'
  9 +const RCTMJScrollViewManager = NativeModules.MJScrollViewManager;
  10 +var DEFAULT_PAGE_SIZE = 1;
  11 +var DEFAULT_INITIAL_ROWS = 10;
  12 +var DEFAULT_SCROLL_RENDER_AHEAD = 1000;
  13 +var DEFAULT_END_REACHED_THRESHOLD = 1000;
  14 +
  15 +class MJListView extends ListView {
  16 + static defaultProps = {
  17 + initialListSize: DEFAULT_INITIAL_ROWS,
  18 + pageSize: DEFAULT_PAGE_SIZE,
  19 + renderScrollComponent: props => <MJScrollView {...props} />,
  20 + scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD,
  21 + onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD,
  22 + stickySectionHeadersEnabled: Platform.OS === 'ios',
  23 + stickyHeaderIndices: [],
  24 + }
  25 +
  26 + _measureAndUpdateScrollProps = () => {
  27 + var scrollComponent = this.getScrollResponder();
  28 + if (!scrollComponent || !scrollComponent.getInnerViewNode) {
  29 + return;
  30 + }
  31 + RCTMJScrollViewManager &&
  32 + RCTMJScrollViewManager.calculateChildFrames &&
  33 + RCTMJScrollViewManager.calculateChildFrames(
  34 + findNodeHandle(scrollComponent),
  35 + this._updateVisibleRows,
  36 + )
  37 + }
  38 +}
  39 +
  40 +module.exports = Platform.OS === 'ios' ? MJListView : ListView;
  1 +import React, {Component} from 'react';
  2 +import {
  3 + StyleSheet,
  4 + View,
  5 + Text,
  6 + requireNativeComponent,
  7 + ViewPropTypes as RNViewPropTypes,
  8 + findNodeHandle,
  9 + UIManager,
  10 + Platform,
  11 +} from 'react-native';
  12 +import PropTypes from 'prop-types'
  13 +import MJScrollView from './MJScrollView'
  14 +import MJListView from './MJListView'
  15 +import MJFlatlist from './MJFlatList'
  16 +const ViewPropTypes = RNViewPropTypes || View.propTypes;
  17 +const UnimplementedView = require('react-native/Libraries/Components/UnimplementedViews/UnimplementedView')
  18 +//Android平台未实现RCTMJRefreshView
  19 +const RCTMJRefreshView = Platform.OS === 'ios' ? requireNativeComponent('RCTMJRefreshView', MJRefresh) : UnimplementedView;
  20 +
  21 +class MJRefresh extends Component {
  22 + _onMJRefresh=()=>{
  23 + let {onRefresh} = this.props;
  24 + onRefresh && onRefresh();
  25 + }
  26 + _onMJPulling=(e)=>{
  27 + let {onPulling} = this.props;
  28 + onPulling && onPulling(e);
  29 + }
  30 + _onMJReleaseToRefresh=()=>{
  31 + let {onReleaseToRefresh} = this.props;
  32 + onReleaseToRefresh && onReleaseToRefresh();
  33 + }
  34 + _onMJRefreshIdle=()=>{
  35 + let {onRefreshIdle} = this.props;
  36 + onRefreshIdle && onRefreshIdle();
  37 + }
  38 + finishRefresh=()=>{
  39 + this.dispatchCommand('finishRefresh');
  40 + }
  41 + beginRefresh=()=>{
  42 + this.dispatchCommand('beginRefresh')
  43 + }
  44 + dispatchCommand (commandName, params) {
  45 + UIManager.dispatchViewManagerCommand(this.findNode(), UIManager.RCTMJRefreshView.Commands[commandName], params)
  46 + }
  47 + findNode=()=>{
  48 + return findNodeHandle(this.refs.refreshView);
  49 + }
  50 + render() {
  51 + let {style} = this.props;
  52 + return (
  53 + <RCTMJRefreshView
  54 + ref='refreshView'
  55 + {...this.props}
  56 + onMJRefresh={this._onMJRefresh}
  57 + onMJRefreshIdle={this._onMJRefreshIdle}
  58 + onMJReleaseToRefresh={this._onMJReleaseToRefresh}
  59 + onMJPulling={this._onMJPulling}
  60 + style={[
  61 + {
  62 + backgroundColor:'transparent'
  63 + },
  64 + style,
  65 + {
  66 + position:'absolute',
  67 + left:0,
  68 + right:0,
  69 + }
  70 + ]}
  71 + />)
  72 + }
  73 +}
  74 +MJRefresh.propTypes={
  75 + onRefresh:PropTypes.func,
  76 + onRefreshIdle:PropTypes.func,
  77 + onReleaseToRefresh:PropTypes.func,
  78 + onPulling:PropTypes.func,
  79 + ...ViewPropTypes
  80 +}
  81 +export const ScrollView = MJScrollView;
  82 +export const ListView = MJListView;
  83 +export const FlatList = MJFlatlist;
  84 +export default MJRefresh;
  1 +import React,{Component} from 'react';
  2 +import {
  3 + requireNativeComponent,
  4 + ScrollView,
  5 + View,
  6 + Platform,
  7 + StyleSheet,
  8 +} from 'react-native';
  9 +const warning = require('fbjs/lib/warning');
  10 +const flattenStyle = require('react-native/Libraries/StyleSheet/flattenStyle');
  11 +const invariant = require('fbjs/lib/invariant');
  12 +const ScrollViewStickyHeader = require('react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader');
  13 +const processDecelerationRate = require('react-native/Libraries/Components/ScrollView/processDecelerationRate');
  14 +const RCTMJScrollView = requireNativeComponent('RCTMJScrollView', MJScrollView, {
  15 + nativeOnly: {
  16 + onMomentumScrollBegin: true,
  17 + onMomentumScrollEnd : true,
  18 + onScrollBeginDrag: true,
  19 + onScrollEndDrag: true,
  20 + }
  21 +})
  22 +
  23 +const RCTMJScrollContentView = requireNativeComponent('RCTMJScrollContentView', View)
  24 +
  25 +class MJScrollView extends ScrollView {
  26 + render() {
  27 + let ScrollViewClass = RCTMJScrollView;
  28 + let ScrollContentContainerViewClass = RCTMJScrollContentView;
  29 + warning(
  30 + !this.props.snapToInterval || !this.props.pagingEnabled,
  31 + 'snapToInterval is currently ignored when pagingEnabled is true.'
  32 + );
  33 + invariant(
  34 + ScrollViewClass !== undefined,
  35 + 'ScrollViewClass must not be undefined'
  36 + );
  37 + invariant(
  38 + ScrollContentContainerViewClass !== undefined,
  39 + 'ScrollContentContainerViewClass must not be undefined'
  40 + );
  41 + const contentContainerStyle = [
  42 + this.props.horizontal && styles.contentContainerHorizontal,
  43 + this.props.contentContainerStyle,
  44 + ];
  45 + let style, childLayoutProps;
  46 + if (__DEV__ && this.props.style) {
  47 + style = flattenStyle(this.props.style);
  48 + childLayoutProps = ['alignItems', 'justifyContent']
  49 + .filter((prop) => style && style[prop] !== undefined);
  50 + invariant(
  51 + childLayoutProps.length === 0,
  52 + 'ScrollView child layout (' + JSON.stringify(childLayoutProps) +
  53 + ') must be applied through the contentContainerStyle prop.'
  54 + );
  55 + }
  56 +
  57 + let contentSizeChangeProps = {};
  58 + if (this.props.onContentSizeChange) {
  59 + contentSizeChangeProps = {
  60 + onLayout: this._handleContentOnLayout,
  61 + };
  62 + }
  63 +
  64 + const {stickyHeaderIndices} = this.props;
  65 + const hasStickyHeaders = stickyHeaderIndices && stickyHeaderIndices.length > 0;
  66 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This comment
  67 + * suppresses an error when upgrading Flow's support for React. To see the
  68 + * error delete this comment and run Flow. */
  69 + const childArray = hasStickyHeaders && React.Children.toArray(this.props.children);
  70 + const children = hasStickyHeaders ?
  71 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  72 + * comment suppresses an error when upgrading Flow's support for React.
  73 + * To see the error delete this comment and run Flow. */
  74 + childArray.map((child, index) => {
  75 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  76 + * comment suppresses an error when upgrading Flow's support for React.
  77 + * To see the error delete this comment and run Flow. */
  78 + const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1;
  79 + if (indexOfIndex > -1) {
  80 + const key = child.key;
  81 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  82 + * comment suppresses an error when upgrading Flow's support for
  83 + * React. To see the error delete this comment and run Flow. */
  84 + const nextIndex = stickyHeaderIndices[indexOfIndex + 1];
  85 + return (
  86 + <ScrollViewStickyHeader
  87 + key={key}
  88 + ref={(ref) => this._setStickyHeaderRef(key, ref)}
  89 + nextHeaderLayoutY={
  90 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss)
  91 + * This comment suppresses an error when upgrading Flow's
  92 + * support for React. To see the error delete this comment and
  93 + * run Flow. */
  94 + this._headerLayoutYs.get(this._getKeyForIndex(nextIndex, childArray))
  95 + }
  96 + onLayout={(event) => this._onStickyHeaderLayout(index, event, key)}
  97 + scrollAnimatedValue={this._scrollAnimatedValue}>
  98 + {child}
  99 + </ScrollViewStickyHeader>
  100 + );
  101 + } else {
  102 + return child;
  103 + }
  104 + }) :
  105 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  106 + * comment suppresses an error when upgrading Flow's support for React.
  107 + * To see the error delete this comment and run Flow. */
  108 + this.props.children;
  109 + const contentContainer =
  110 + <ScrollContentContainerViewClass
  111 + {...contentSizeChangeProps}
  112 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  113 + * comment suppresses an error when upgrading Flow's support for React.
  114 + * To see the error delete this comment and run Flow. */
  115 + ref={this._setInnerViewRef}
  116 + style={contentContainerStyle}
  117 + removeClippedSubviews={
  118 + // Subview clipping causes issues with sticky headers on Android and
  119 + // would be hard to fix properly in a performant way.
  120 + Platform.OS === 'android' && hasStickyHeaders ?
  121 + false :
  122 + this.props.removeClippedSubviews
  123 + }
  124 + collapsable={false}>
  125 + {children}
  126 + </ScrollContentContainerViewClass>;
  127 +
  128 + const alwaysBounceHorizontal =
  129 + this.props.alwaysBounceHorizontal !== undefined ?
  130 + this.props.alwaysBounceHorizontal :
  131 + this.props.horizontal;
  132 +
  133 + const alwaysBounceVertical =
  134 + this.props.alwaysBounceVertical !== undefined ?
  135 + this.props.alwaysBounceVertical :
  136 + !this.props.horizontal;
  137 +
  138 + const DEPRECATED_sendUpdatedChildFrames =
  139 + !!this.props.DEPRECATED_sendUpdatedChildFrames;
  140 +
  141 + const baseStyle = this.props.horizontal ? styles.baseHorizontal : styles.baseVertical;
  142 + const props = {
  143 + ...this.props,
  144 + alwaysBounceHorizontal,
  145 + alwaysBounceVertical,
  146 + style: [baseStyle, this.props.style],
  147 + // Override the onContentSizeChange from props, since this event can
  148 + // bubble up from TextInputs
  149 + onContentSizeChange: null,
  150 + onMomentumScrollBegin: this.scrollResponderHandleMomentumScrollBegin,
  151 + onMomentumScrollEnd: this.scrollResponderHandleMomentumScrollEnd,
  152 + onResponderGrant: this.scrollResponderHandleResponderGrant,
  153 + onResponderReject: this.scrollResponderHandleResponderReject,
  154 + onResponderRelease: this.scrollResponderHandleResponderRelease,
  155 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  156 + * comment suppresses an error when upgrading Flow's support for React.
  157 + * To see the error delete this comment and run Flow. */
  158 + onResponderTerminate: this.scrollResponderHandleTerminate,
  159 + onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest,
  160 + onScroll: this._handleScroll,
  161 + onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
  162 + onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
  163 + onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder,
  164 + onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder,
  165 + onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture,
  166 + onTouchEnd: this.scrollResponderHandleTouchEnd,
  167 + onTouchMove: this.scrollResponderHandleTouchMove,
  168 + onTouchStart: this.scrollResponderHandleTouchStart,
  169 + scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle,
  170 + sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ?
  171 + true : false,
  172 + DEPRECATED_sendUpdatedChildFrames,
  173 + };
  174 +
  175 + const { decelerationRate } = this.props;
  176 + if (decelerationRate) {
  177 + props.decelerationRate = processDecelerationRate(decelerationRate);
  178 + }
  179 +
  180 + const refreshControl = this.props.refreshControl;
  181 +
  182 + if (refreshControl) {
  183 + // On iOS the RefreshControl is a child of the ScrollView.
  184 + // tvOS lacks native support for RefreshControl, so don't include it in that case
  185 + return (
  186 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  187 + * comment suppresses an error when upgrading Flow's support for
  188 + * React. To see the error delete this comment and run Flow. */
  189 + <ScrollViewClass {...props} ref={this._setScrollViewRef}>
  190 + {Platform.isTVOS ? null : refreshControl}
  191 + {contentContainer}
  192 + </ScrollViewClass>
  193 + );
  194 + }
  195 + return (
  196 + /* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
  197 + * comment suppresses an error when upgrading Flow's support for React.
  198 + * To see the error delete this comment and run Flow. */
  199 + <ScrollViewClass {...props} ref={this._setScrollViewRef}>
  200 + {contentContainer}
  201 + </ScrollViewClass>
  202 + );
  203 + }
  204 +}
  205 +
  206 +const styles = StyleSheet.create({
  207 + baseVertical: {
  208 + flexGrow: 1,
  209 + flexShrink: 1,
  210 + flexDirection: 'column',
  211 + overflow: 'scroll',
  212 + },
  213 + baseHorizontal: {
  214 + flexGrow: 1,
  215 + flexShrink: 1,
  216 + flexDirection: 'row',
  217 + overflow: 'scroll',
  218 + },
  219 + contentContainerHorizontal: {
  220 + flexDirection: 'row',
  221 + },
  222 +});
  223 +
  224 +module.exports = Platform.OS === 'ios' ? MJScrollView : ScrollView
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 "name": "react-native-vode-mj-refresh", 3 "name": "react-native-vode-mj-refresh",
4 "version": "1.0.0", 4 "version": "1.0.0",
5 "description": "", 5 "description": "",
6 - "main": "index.js", 6 + "main": "MJRefresh.js",
7 "scripts": { 7 "scripts": {
8 "test": "echo \"Error: no test specified\" && exit 1" 8 "test": "echo \"Error: no test specified\" && exit 1"
9 }, 9 },