作者 周泳恩

init

import React, {Component} from 'react';
import {VirtualizedList, FlatList,Platform} from 'react-native';
class MJFlatList extends FlatList {
render() {
return (
<VirtualizedList
{...this.props}
renderItem={this._renderItem}
getItem={this._getItem}
getItemCount={this._getItemCount}
keyExtractor={this._keyExtractor}
ref={this._captureRef}
onViewableItemsChanged={
this.props.onViewableItemsChanged && this._onViewableItemsChanged
}
/>
);
}
}
module.exports = Platform.OS === 'ios' ? MJFlatList : FlatList;
\ No newline at end of file
... ...
import React,{Component} from 'react';
import {
findNodeHandle,
NativeModules,
Platform,
ListView,
} from 'react-native';
import MJScrollView from './MJScrollView'
const RCTMJScrollViewManager = NativeModules.MJScrollViewManager;
var DEFAULT_PAGE_SIZE = 1;
var DEFAULT_INITIAL_ROWS = 10;
var DEFAULT_SCROLL_RENDER_AHEAD = 1000;
var DEFAULT_END_REACHED_THRESHOLD = 1000;
class MJListView extends ListView {
static defaultProps = {
initialListSize: DEFAULT_INITIAL_ROWS,
pageSize: DEFAULT_PAGE_SIZE,
renderScrollComponent: props => <MJScrollView {...props} />,
scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD,
onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD,
stickySectionHeadersEnabled: Platform.OS === 'ios',
stickyHeaderIndices: [],
}
_measureAndUpdateScrollProps = () => {
var scrollComponent = this.getScrollResponder();
if (!scrollComponent || !scrollComponent.getInnerViewNode) {
return;
}
RCTMJScrollViewManager &&
RCTMJScrollViewManager.calculateChildFrames &&
RCTMJScrollViewManager.calculateChildFrames(
findNodeHandle(scrollComponent),
this._updateVisibleRows,
)
}
}
module.exports = Platform.OS === 'ios' ? MJListView : ListView;
... ...
import React, {Component} from 'react';
import {
StyleSheet,
View,
Text,
requireNativeComponent,
ViewPropTypes as RNViewPropTypes,
findNodeHandle,
UIManager,
Platform,
} from 'react-native';
import PropTypes from 'prop-types'
import MJScrollView from './MJScrollView'
import MJListView from './MJListView'
import MJFlatlist from './MJFlatList'
const ViewPropTypes = RNViewPropTypes || View.propTypes;
const UnimplementedView = require('react-native/Libraries/Components/UnimplementedViews/UnimplementedView')
//Android平台未实现RCTMJRefreshView
const RCTMJRefreshView = Platform.OS === 'ios' ? requireNativeComponent('RCTMJRefreshView', MJRefresh) : UnimplementedView;
class MJRefresh extends Component {
_onMJRefresh=()=>{
let {onRefresh} = this.props;
onRefresh && onRefresh();
}
_onMJPulling=(e)=>{
let {onPulling} = this.props;
onPulling && onPulling(e);
}
_onMJReleaseToRefresh=()=>{
let {onReleaseToRefresh} = this.props;
onReleaseToRefresh && onReleaseToRefresh();
}
_onMJRefreshIdle=()=>{
let {onRefreshIdle} = this.props;
onRefreshIdle && onRefreshIdle();
}
finishRefresh=()=>{
this.dispatchCommand('finishRefresh');
}
beginRefresh=()=>{
this.dispatchCommand('beginRefresh')
}
dispatchCommand (commandName, params) {
UIManager.dispatchViewManagerCommand(this.findNode(), UIManager.RCTMJRefreshView.Commands[commandName], params)
}
findNode=()=>{
return findNodeHandle(this.refs.refreshView);
}
render() {
let {style} = this.props;
return (
<RCTMJRefreshView
ref='refreshView'
{...this.props}
onMJRefresh={this._onMJRefresh}
onMJRefreshIdle={this._onMJRefreshIdle}
onMJReleaseToRefresh={this._onMJReleaseToRefresh}
onMJPulling={this._onMJPulling}
style={[
{
backgroundColor:'transparent'
},
style,
{
position:'absolute',
left:0,
right:0,
}
]}
/>)
}
}
MJRefresh.propTypes={
onRefresh:PropTypes.func,
onRefreshIdle:PropTypes.func,
onReleaseToRefresh:PropTypes.func,
onPulling:PropTypes.func,
...ViewPropTypes
}
export const ScrollView = MJScrollView;
export const ListView = MJListView;
export const FlatList = MJFlatlist;
export default MJRefresh;
... ...
import React,{Component} from 'react';
import {
requireNativeComponent,
ScrollView,
View,
Platform,
StyleSheet,
} from 'react-native';
const warning = require('fbjs/lib/warning');
const flattenStyle = require('react-native/Libraries/StyleSheet/flattenStyle');
const invariant = require('fbjs/lib/invariant');
const ScrollViewStickyHeader = require('react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader');
const processDecelerationRate = require('react-native/Libraries/Components/ScrollView/processDecelerationRate');
const RCTMJScrollView = requireNativeComponent('RCTMJScrollView', MJScrollView, {
nativeOnly: {
onMomentumScrollBegin: true,
onMomentumScrollEnd : true,
onScrollBeginDrag: true,
onScrollEndDrag: true,
}
})
const RCTMJScrollContentView = requireNativeComponent('RCTMJScrollContentView', View)
class MJScrollView extends ScrollView {
render() {
let ScrollViewClass = RCTMJScrollView;
let ScrollContentContainerViewClass = RCTMJScrollContentView;
warning(
!this.props.snapToInterval || !this.props.pagingEnabled,
'snapToInterval is currently ignored when pagingEnabled is true.'
);
invariant(
ScrollViewClass !== undefined,
'ScrollViewClass must not be undefined'
);
invariant(
ScrollContentContainerViewClass !== undefined,
'ScrollContentContainerViewClass must not be undefined'
);
const contentContainerStyle = [
this.props.horizontal && styles.contentContainerHorizontal,
this.props.contentContainerStyle,
];
let style, childLayoutProps;
if (__DEV__ && this.props.style) {
style = flattenStyle(this.props.style);
childLayoutProps = ['alignItems', 'justifyContent']
.filter((prop) => style && style[prop] !== undefined);
invariant(
childLayoutProps.length === 0,
'ScrollView child layout (' + JSON.stringify(childLayoutProps) +
') must be applied through the contentContainerStyle prop.'
);
}
let contentSizeChangeProps = {};
if (this.props.onContentSizeChange) {
contentSizeChangeProps = {
onLayout: this._handleContentOnLayout,
};
}
const {stickyHeaderIndices} = this.props;
const hasStickyHeaders = stickyHeaderIndices && stickyHeaderIndices.length > 0;
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This comment
* suppresses an error when upgrading Flow's support for React. To see the
* error delete this comment and run Flow. */
const childArray = hasStickyHeaders && React.Children.toArray(this.props.children);
const children = hasStickyHeaders ?
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
childArray.map((child, index) => {
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
const indexOfIndex = child ? stickyHeaderIndices.indexOf(index) : -1;
if (indexOfIndex > -1) {
const key = child.key;
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for
* React. To see the error delete this comment and run Flow. */
const nextIndex = stickyHeaderIndices[indexOfIndex + 1];
return (
<ScrollViewStickyHeader
key={key}
ref={(ref) => this._setStickyHeaderRef(key, ref)}
nextHeaderLayoutY={
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss)
* This comment suppresses an error when upgrading Flow's
* support for React. To see the error delete this comment and
* run Flow. */
this._headerLayoutYs.get(this._getKeyForIndex(nextIndex, childArray))
}
onLayout={(event) => this._onStickyHeaderLayout(index, event, key)}
scrollAnimatedValue={this._scrollAnimatedValue}>
{child}
</ScrollViewStickyHeader>
);
} else {
return child;
}
}) :
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
this.props.children;
const contentContainer =
<ScrollContentContainerViewClass
{...contentSizeChangeProps}
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
ref={this._setInnerViewRef}
style={contentContainerStyle}
removeClippedSubviews={
// Subview clipping causes issues with sticky headers on Android and
// would be hard to fix properly in a performant way.
Platform.OS === 'android' && hasStickyHeaders ?
false :
this.props.removeClippedSubviews
}
collapsable={false}>
{children}
</ScrollContentContainerViewClass>;
const alwaysBounceHorizontal =
this.props.alwaysBounceHorizontal !== undefined ?
this.props.alwaysBounceHorizontal :
this.props.horizontal;
const alwaysBounceVertical =
this.props.alwaysBounceVertical !== undefined ?
this.props.alwaysBounceVertical :
!this.props.horizontal;
const DEPRECATED_sendUpdatedChildFrames =
!!this.props.DEPRECATED_sendUpdatedChildFrames;
const baseStyle = this.props.horizontal ? styles.baseHorizontal : styles.baseVertical;
const props = {
...this.props,
alwaysBounceHorizontal,
alwaysBounceVertical,
style: [baseStyle, this.props.style],
// Override the onContentSizeChange from props, since this event can
// bubble up from TextInputs
onContentSizeChange: null,
onMomentumScrollBegin: this.scrollResponderHandleMomentumScrollBegin,
onMomentumScrollEnd: this.scrollResponderHandleMomentumScrollEnd,
onResponderGrant: this.scrollResponderHandleResponderGrant,
onResponderReject: this.scrollResponderHandleResponderReject,
onResponderRelease: this.scrollResponderHandleResponderRelease,
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
onResponderTerminate: this.scrollResponderHandleTerminate,
onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest,
onScroll: this._handleScroll,
onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder,
onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder,
onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture,
onTouchEnd: this.scrollResponderHandleTouchEnd,
onTouchMove: this.scrollResponderHandleTouchMove,
onTouchStart: this.scrollResponderHandleTouchStart,
scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle,
sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ?
true : false,
DEPRECATED_sendUpdatedChildFrames,
};
const { decelerationRate } = this.props;
if (decelerationRate) {
props.decelerationRate = processDecelerationRate(decelerationRate);
}
const refreshControl = this.props.refreshControl;
if (refreshControl) {
// On iOS the RefreshControl is a child of the ScrollView.
// tvOS lacks native support for RefreshControl, so don't include it in that case
return (
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for
* React. To see the error delete this comment and run Flow. */
<ScrollViewClass {...props} ref={this._setScrollViewRef}>
{Platform.isTVOS ? null : refreshControl}
{contentContainer}
</ScrollViewClass>
);
}
return (
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error when upgrading Flow's support for React.
* To see the error delete this comment and run Flow. */
<ScrollViewClass {...props} ref={this._setScrollViewRef}>
{contentContainer}
</ScrollViewClass>
);
}
}
const styles = StyleSheet.create({
baseVertical: {
flexGrow: 1,
flexShrink: 1,
flexDirection: 'column',
overflow: 'scroll',
},
baseHorizontal: {
flexGrow: 1,
flexShrink: 1,
flexDirection: 'row',
overflow: 'scroll',
},
contentContainerHorizontal: {
flexDirection: 'row',
},
});
module.exports = Platform.OS === 'ios' ? MJScrollView : ScrollView
... ...
... ... @@ -3,7 +3,7 @@
"name": "react-native-vode-mj-refresh",
"version": "1.0.0",
"description": "",
"main": "index.js",
"main": "MJRefresh.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
... ...