diff --git a/packages/taro-components-rn/TCRNExample/App.flatlist.js b/packages/taro-components-rn/TCRNExample/App.flatlist.js new file mode 100644 index 000000000000..681c89eaa639 --- /dev/null +++ b/packages/taro-components-rn/TCRNExample/App.flatlist.js @@ -0,0 +1,157 @@ +import React, { Component } from 'react' +import { StyleSheet } from 'react-native' +import { + Provider, + Block, + ScrollView, + View, + Text, + Button, + Image +} from '../dist' +// import EXAudio from './example/EXAudio' +import EXButton from './example/EXButton' +import EXCheckbox from './example/EXCheckbox' +import EXForm from './example/EXForm' +import EXIcon from './example/EXIcon' +import EXImage from './example/EXImage' +import EXInput from './example/EXInput' +// import EXMap from './example/EXMap' +import EXPicker from './example/EXPicker' +import EXProgress from './example/EXProgress' +import EXRadio from './example/EXRadio' +import EXRichText from './example/EXRichText' +import EXSlider from './example/EXSlider' +import EXSwiper from './example/EXSwiper' +import EXSwitch from './example/EXSwitch' +// import EXVideo from './example/EXVideo' +import EXWebView from './example/EXWebView' + +export default class App extends Component { + state = { + // 更改 scrollTop 可滚动 + scrollTop: 0 + } + + onViewTouchstart = () => { + console.log('view toucstart') + } + + onViewTouchmove = () => { + console.log('view touchmove') + } + + onViewTouchend = () => { + console.log('view touchend') + } + + componentDidMount () { + // setTimeout(() => { + // this.setState({ scrollTop: 2200 }) + // }, 0) + } + + renderItem = ({ item }) => { + switch (item.name) { + case 'welcome': + return Welcome to React Native! + case 'Block': + return ( + + + Block + + + + ) + case 'Button': + return ( + + + Button + + + + ) + case 'Checkbox': + return ( + + + Checkbox + + + + ) + case 'Form': + return ( + + + Form + + + + ) + } + } + + render () { + return ( + + { + console.log('to upper') + }} + onScrollToLower={() => { + console.log('to lower') + }} + onScroll={(e) => { + console.log('onScroll', e) + }} + bounces={false} + data={[ + { name: 'welcome' }, + { name: 'Block' }, + { name: 'Button' }, + { name: 'Checkbox' }, + { name: 'Form' }, + ]} + renderItem={this.renderItem} + /> + + ) + } +} + +const styles = StyleSheet.create({ + section: { + alignItems: 'center', + width: '100%', + paddingBottom: 10, + marginBottom: 10, + borderBottomWidth: 1, + borderBottomColor: 'gold' + }, + sectionTit: { + marginBottom: 10, + paddingVertical: 4, + paddingHorizontal: 8, + backgroundColor: 'tomato', + borderRadius: 4, + borderLeftWidth: 3, + borderLeftColor: '#666', + borderRightWidth: 3, + borderRightColor: '#666' + }, + sectionTitTxt: { + fontSize: 18, + color: 'white' + } +}) diff --git a/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx b/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx index fc38857cf139..465ea9c60f01 100644 --- a/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx +++ b/packages/taro-components-rn/src/components/ScrollView/PropsType.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { StyleProp, ViewStyle } from 'react-native' +import { StyleProp, ViewStyle, ListRenderItem } from 'react-native' export type ScrollMetrics = { contentLength: number; @@ -37,7 +37,7 @@ export interface ScrollViewState { snapScrollLeft: number; } -export interface ScrollViewProps { +export interface ScrollViewProps { children?: React.ReactNode; style?: StyleProp; scrollX?: boolean; @@ -52,4 +52,6 @@ export interface ScrollViewProps { onScroll?: (evt: EventOnScroll) => void; // RN 属性 contentContainerStyle?: StyleProp; + data?: ReadonlyArray | null; + renderItem?: ListRenderItem; } diff --git a/packages/taro-components-rn/src/components/ScrollView/index.tsx b/packages/taro-components-rn/src/components/ScrollView/index.tsx index 4a5e0fb3e38c..9ee100aa7615 100644 --- a/packages/taro-components-rn/src/components/ScrollView/index.tsx +++ b/packages/taro-components-rn/src/components/ScrollView/index.tsx @@ -22,6 +22,7 @@ import * as React from 'react' import { ScrollView, + FlatList, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, @@ -38,7 +39,7 @@ import { ScrollViewProps, ScrollViewState, ScrollMetrics } from './PropsType' // // Other // ] -class _ScrollView extends React.Component { +class _ScrollView extends React.Component, ScrollViewState> { static defaultProps = { upperThreshold: 50, lowerThreshold: 50, @@ -47,7 +48,7 @@ class _ScrollView extends React.Component { enableBackToTop: false, } - static getDerivedStateFromProps (props: ScrollViewProps, state: ScrollViewState) { + static getDerivedStateFromProps (props: ScrollViewProps, state: ScrollViewState) { return state.snapScrollTop !== props.scrollTop || state.snapScrollLeft !== props.scrollLeft ? { snapScrollTop: props.scrollTop, snapScrollLeft: props.scrollLeft @@ -70,7 +71,7 @@ class _ScrollView extends React.Component { velocity: 0, visibleLength: 0, } - $scrollView = React.createRef() + $scrollView = React.createRef() _hasDataChangedSinceEndReached: boolean _sentEndForContentLength: number = 0 _scrollEventThrottle: number = 50 @@ -180,8 +181,15 @@ class _ScrollView extends React.Component { } scrollToOffset = (x: number = 0, y: number = 0): void => { + const { scrollX, data, renderItem } = this.props const node = this.$scrollView.current - node && node.scrollTo({ x, y, animated: !!this.props.scrollWithAnimation }) + if (node) { + if (data && renderItem) { + (node as FlatList).scrollToOffset({ offset: scrollX ? x : y, animated: !!this.props.scrollWithAnimation }) + } else { + (node as ScrollView).scrollTo({ x, y, animated: !!this.props.scrollWithAnimation }) + } + } } componentDidMount () { @@ -192,11 +200,11 @@ class _ScrollView extends React.Component { } } - getSnapshotBeforeUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState) { + getSnapshotBeforeUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState) { return prevState.snapScrollTop !== this.state.snapScrollTop || prevState.snapScrollLeft !== this.state.snapScrollLeft } - componentDidUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState, snapshot: boolean) { + componentDidUpdate (prevProps: ScrollViewProps, prevState: ScrollViewState, snapshot: boolean) { if (snapshot) { this.scrollToOffset(this.state.snapScrollLeft, this.state.snapScrollTop) } @@ -213,6 +221,8 @@ class _ScrollView extends React.Component { scrollX, enableBackToTop, contentContainerStyle, + data, + renderItem, } = this.props const flattenStyle: ViewStyle & { [key: string]: any } = StyleSheet.flatten(style) @@ -226,45 +236,59 @@ class _ScrollView extends React.Component { flattenStyle.justifyContent && (_contentContainerStyle.justifyContent = flattenStyle.justifyContent) } - return ( + const scrollElementProps = { + horizontal: scrollX, + onContentSizeChange: this._onContentSizeChange, + onLayout: this._onLayout, + onScroll: this._onScroll, + onScrollEndDrag: this._onScrollEndDrag, + onMomentumScrollEnd: this._onMomentumScrollEnd, + scrollEventThrottle: this._scrollEventThrottle, + scrollsToTop: !!enableBackToTop, + style: wrapperStyle, + contentContainerStyle: [_contentContainerStyle, contentContainerStyle], + ...omit(this.props, [ + // props + 'style', + 'scrollX', + 'upperThreshold', + 'lowerThreshold', + 'scrollTop', + 'scrollLeft', + 'scrollWithAnimation', + 'enableBackToTop', + 'onScrollToUpper', + 'onScrollToLower', + 'onScroll', + 'contentContainerStyle', + // SProps + 'horizontal', + 'onContentSizeChange', + 'onLayout', + 'onScroll', + 'onScrollEndDrag', + 'onMomentumScrollEnd', + 'scrollEventThrottle', + 'scrollsToTop', + 'style', + 'contentContainerStyle', + 'data', + 'renderItem', + 'keyExtractor', + ]), + ref: this.$scrollView + } + + return data && renderItem ? ( + index + ''} + /> + ) : ( {children}