diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index b72d38da3..2c43b4255 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -14,6 +14,12 @@ toc: false --- +### 5.2.3 +`2024-09-09` +- 🔥 **Carousel** + - fix: Carousel autoplay and manual conflict. [#1259](https://github.com/ant-design/ant-design-mobile-rn/issues/1259) +- fix: **Button** `children` support `string[]` type. [~commit](https://github.com/ant-design/ant-design-mobile-rn/commit/ce08b346cd1f53c39ea9cd861626247880720af4) + ### 5.2.2 `2024-08-12` - 🔥 **NoticeBar** diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 315478fb8..e279a993d 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -14,6 +14,12 @@ toc: false --- +### 5.2.3 +`2024-09-09` +- 🔥 **Carousel** + - fix: Carousel自动切换和手动切换冲突。[#1259](https://github.com/ant-design/ant-design-mobile-rn/issues/1259) +- fix: **Button** `children` 支持 `string[]` 类型。[~commit](https://github.com/ant-design/ant-design-mobile-rn/commit/ce08b346cd1f53c39ea9cd861626247880720af4) + ### 5.2.2 `2024-08-12` - 🔥 **NoticeBar** diff --git a/README.md b/README.md index 4a71d5dc6..9832cf699 100644 --- a/README.md +++ b/README.md @@ -32,18 +32,18 @@ A configurable Mobile UI specification and React-based implementation. > HTML5 Preview: [ant-design-mobile-rn/index.html](https://1uokun.github.io/ant-design-mobile-rn/index.html) -|SDK 49+| +|SDK 51| |--| -| [expo/ant-design-mobile-rn](https://expo.dev/preview/update?message=5.2.2&updateRuntimeVersion=5.2.2&createdAt=2024-08-12T13%3A33%3A56.096Z&slug=exp&projectId=7729a68b-f881-4294-89f5-5ae751bfb2b2&group=bbf0a647-4ff2-46bd-9aad-dfd81bc6ba08) | +| [expo/ant-design-mobile-rn](https://expo.dev/preview/update?message=5.2.3&updateRuntimeVersion=5.2.3&createdAt=2024-09-09T09%3A01%3A36.394Z&slug=exp&projectId=7729a68b-f881-4294-89f5-5ae751bfb2b2&group=2e623b22-08d9-4ab2-92f2-017c7a92d5aa) | Open the camera app on your device and scan the code above,
need install expo app: https://expo.io/tools -
Expo SDK history version +
Expo SDK(44, 47, 49, 50) history version -|Expo SDK 44|SDK 47 iOS|SDK 47 Android| -|--|--|--| -| [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | +|Expo SDK 44|SDK 47 iOS|SDK 47 Android|SDK 49,50| +|--|--|--|--| +| [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/preview/update?message=5.2.2&updateRuntimeVersion=5.2.2&createdAt=2024-08-12T13%3A33%3A56.096Z&slug=exp&projectId=7729a68b-f881-4294-89f5-5ae751bfb2b2&group=bbf0a647-4ff2-46bd-9aad-dfd81bc6ba08) |
diff --git a/README.zh-CN.md b/README.zh-CN.md index 1733c1d7e..3349c0340 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -30,17 +30,17 @@ Ant Design 移动端设计规范。`@ant-design/react-native` 是 Ant Design 的 > HTML5 预览: [ant-design-mobile-rn/index.html](https://1uokun.github.io/ant-design-mobile-rn/index.html) -|SDK 49+| +|SDK 51| |--| -| [expo/ant-design-mobile-rn](https://expo.dev/preview/update?message=5.2.2&updateRuntimeVersion=5.2.2&createdAt=2024-08-12T13%3A33%3A56.096Z&slug=exp&projectId=7729a68b-f881-4294-89f5-5ae751bfb2b2&group=bbf0a647-4ff2-46bd-9aad-dfd81bc6ba08) | +| [expo/ant-design-mobile-rn](https://expo.dev/preview/update?message=5.2.3&updateRuntimeVersion=5.2.3&createdAt=2024-09-09T09%3A01%3A36.394Z&slug=exp&projectId=7729a68b-f881-4294-89f5-5ae751bfb2b2&group=2e623b22-08d9-4ab2-92f2-017c7a92d5aa) | 提示:使用本地原相机扫瞄上面的二维码, 需要下载 Expo App: https://expo.io/tools -
Expo SDK历史版本 +
Expo SDK(44, 47, 49, 50) 历史版本 -|Expo SDK 44|SDK 47 iOS|SDK 47 Android| -|--|--|--| -| [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | +|Expo SDK 44|SDK 47 iOS|SDK 47 Android|SDK 49,50| +|--|--|--|--| +| [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/@1uokun/ant-design-mobile-rn) | [expo/ant-design-mobile-rn](https://expo.dev/preview/update?message=5.2.2&updateRuntimeVersion=5.2.2&createdAt=2024-08-12T13%3A33%3A56.096Z&slug=exp&projectId=7729a68b-f881-4294-89f5-5ae751bfb2b2&group=bbf0a647-4ff2-46bd-9aad-dfd81bc6ba08) |
## 安装 & 使用 diff --git a/components/button/__tests__/__snapshots__/demo.test.js.snap b/components/button/__tests__/__snapshots__/demo.test.js.snap index 91c6b2533..ce368e53f 100644 --- a/components/button/__tests__/__snapshots__/demo.test.js.snap +++ b/components/button/__tests__/__snapshots__/demo.test.js.snap @@ -984,22 +984,37 @@ exports[`renders ./components/button/demo/basic.tsx correctly 1`] = ` } } > - -  - + +  + + diff --git a/components/button/index.tsx b/components/button/index.tsx index eda65044a..3dbb572b7 100644 --- a/components/button/index.tsx +++ b/components/button/index.tsx @@ -5,13 +5,13 @@ import { GestureResponderEvent, StyleProp, StyleSheet, - Text, TouchableHighlight, TouchableHighlightProps, View, ViewStyle, } from 'react-native' import { WithTheme, WithThemeStyles } from '../style' +import AntmView from '../view' import { ButtonPropsType } from './PropsType' import buttonStyles, { ButtonStyles } from './style/index' @@ -140,11 +140,7 @@ export default class Button extends React.Component { size="small" /> ) : null} - {typeof this.props.children === 'string' ? ( - {this.props.children} - ) : ( - <>{this.props.children} - )} + {this.props.children} ) diff --git a/components/carousel/PropsType.tsx b/components/carousel/PropsType.tsx new file mode 100644 index 000000000..aea2cf4e4 --- /dev/null +++ b/components/carousel/PropsType.tsx @@ -0,0 +1,37 @@ +import { ReactNode } from 'react' +import { ScrollViewProps, StyleProp, ViewStyle } from 'react-native' +import { CarouselStyle } from './style/index' + +export interface CarouselProps extends ScrollViewProps { + accessibilityLabel?: string + autoplay?: boolean + autoplayInterval?: number + afterChange?: (index: number) => void + children?: ReactNode + dots?: boolean + dotActiveStyle?: StyleProp + dotStyle?: StyleProp + infinite?: boolean + pageStyle?: StyleProp + pagination?: (props: PaginationProps) => ReactNode + selectedIndex?: number + style?: StyleProp + styles?: Partial + vertical?: boolean +} + +export interface PaginationProps { + current: number + count: number + dotStyle?: StyleProp + dotActiveStyle?: StyleProp + styles: Partial + vertical?: boolean +} + +export interface CarouselForwardedRef { + scrollToStart: () => void + scrollToEnd: () => void + scrollNextPage: () => void + goTo: (index: number, animated?: boolean) => void +} diff --git a/components/carousel/__tests__/__snapshots__/demo.test.js.snap b/components/carousel/__tests__/__snapshots__/demo.test.js.snap index a74ed90af..115537b93 100644 --- a/components/carousel/__tests__/__snapshots__/demo.test.js.snap +++ b/components/carousel/__tests__/__snapshots__/demo.test.js.snap @@ -1,303 +1,447 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders ./components/carousel/demo/basic.tsx correctly 1`] = ` - - - - horizontal - + - + + horizontal + + - - + } + directionalLockEnabled={true} + disableIntervalMomentum={false} + dotActiveStyle={Object {}} + dotStyle={Object {}} + dots={true} + horizontal={true} + infinite={true} + nestedScrollEnabled={true} + onScroll={[Function]} + onScrollBeginDrag={[Function]} + onScrollEndDrag={[Function]} + onTouchEnd={[Function]} + onTouchStart={[Function]} + pageStyle={Object {}} + pagination={[Function]} + pagingEnabled={true} + scrollEventThrottle={16} + selectedIndex={2} + showsHorizontalScrollIndicator={false} + showsVerticalScrollIndicator={false} + style={ + Object { + "backgroundColor": "#fff", + "height": 150, + "width": "100%", + } + } + vertical={false} + > + - - Carousel 5 - + + + Carousel 5 + + - - + + + Carousel 1 + + + + - - Carousel 1 - + + + Carousel 2 + + - - + + + Carousel 3 + + + + - - Carousel 2 - + + + Carousel 4 + + - - + + + Carousel 5 + + + + - - Carousel 3 - + + + Carousel 1 + + + + - - Carousel 4 - - - - + /> - - Carousel 5 - - - - + /> - - Carousel 1 - - + /> + + - + @@ -308,637 +452,487 @@ exports[`renders ./components/carousel/demo/basic.tsx correctly 1`] = ` } } > - - - - - + > + Go to 0 + + + vertical + - - Go to 0 - - - - - - - vertical - - - - - + - - Carousel 5 - + + + Carousel 5 + + - - + + + Carousel 1 + + + + - - Carousel 1 - + + + Carousel 2 + + - - + + + Carousel 3 + + + + - - Carousel 2 - + + + Carousel 4 + + - - + + + Carousel 5 + + + + - - Carousel 3 - + + + Carousel 1 + + + + - - Carousel 4 - - - - + /> - - Carousel 5 - - - - + /> - - Carousel 1 - - + /> + + - + - - - - - + > + Toggle autoplay true + - - - - Toggle autoplay true - - - - + `; diff --git a/components/carousel/demo/basic.tsx b/components/carousel/demo/basic.tsx index 83b7ee2c5..e26347c13 100644 --- a/components/carousel/demo/basic.tsx +++ b/components/carousel/demo/basic.tsx @@ -1,5 +1,12 @@ import React from 'react' -import { StyleSheet, Text, TextStyle, View, ViewStyle } from 'react-native' +import { + ScrollView, + StyleSheet, + Text, + TextStyle, + View, + ViewStyle, +} from 'react-native' import { Button, Carousel } from '../../' export default class BasicCarouselExample extends React.Component { @@ -22,7 +29,7 @@ export default class BasicCarouselExample extends React.Component { } render() { return ( - + horizontal { {`Toggle autoplay ${this.state.autoplay ? 'true' : 'false'}`} - + ) } } @@ -121,13 +128,11 @@ const styles = StyleSheet.create<{ flexGrow: 1, alignItems: 'center', justifyContent: 'center', - height: 150, }, containerVertical: { flexGrow: 1, alignItems: 'center', justifyContent: 'center', - height: 150, }, text: { color: '#fff', diff --git a/components/carousel/index.en-US.md b/components/carousel/index.en-US.md index b0f874fed..949a9e41f 100644 --- a/components/carousel/index.en-US.md +++ b/components/carousel/index.en-US.md @@ -8,23 +8,29 @@ title: Carousel Properties | Descrition | Type | Default -----------|------------|------|-------- -| selectedIndex | current selected index | number | 0 | -| dots | whether to display the indication dots | Boolean | true | -| vertical | controls the pagination display direction. | Boolean | false | +| afterChange | callback to be called after a slide is changed | (current: number) => void | | | autoplay | autoplay mode active | Boolean | false | | autoplayInterval | interval for autoplay iteration | Number | 3000 | -| infinite | whether is infinite loop | Boolean | false | -| afterChange | callback to be called after a slide is changed | (current: number): void | | +| dots | whether to display the indication dots | Boolean | true | | dotStyle | style of dots | ViewStyle | | | dotActiveStyle | style of active dot | ViewStyle | | +| infinite | whether is infinite loop | Boolean | false | | pageStyle | style of the carousel page | ViewStyle | | -| pagination | A generator function which could be used to customized pagination. | (props) => React.ReactNode | | +| pagination | A generator function which could be used to customized pagination. | (props) => ReactNode | | +| selectedIndex | current selected index | number | 0 | +| style | ScrollView style
(`tips: Recommended setting, the overall carousel size is determined by the container scrollview and not the inner page`) | ViewStyle | | +| vertical | controls the pagination display direction. | Boolean | false | + +The rest of the props of Carousel are exactly the same as the react-native [ScrollView](https://reactnative.dev/docs/scrollview.html); -## Carousel methods +eg: `scrollEnabled`、`onScroll` (if it not works, it is a mandatory prop of Carousel) -属性 | 说明 | 类型 | 默认值 -----|-----|------|------ -| goTo | jump to specified index | (index: number, animated?: boolean): void | - | +## Carousel ref methods + +Properties | Descrition | Type +----|-----|------ +| goTo | jump to specified index | `(index: number, animated?: boolean): void` | +| scrollNextPage | scroll to next page | `() => void` | ## FAQ @@ -37,4 +43,9 @@ Support in `5.1.3`. Set the `nestedScrollEnabled` property of `ScrollView` to `t ... -``` \ No newline at end of file +``` + +### Why choose Carousel instead of `react-native-pager-view` ? + +First, Carousel supports the `infinite` property, which means 🌟a true infinite loop🌟.
+Second, Carousel is completely based on `ScrollView`, which is not only lighter but also more compatible. \ No newline at end of file diff --git a/components/carousel/index.tsx b/components/carousel/index.tsx index 53387c87b..b52f0ca60 100644 --- a/components/carousel/index.tsx +++ b/components/carousel/index.tsx @@ -1,68 +1,33 @@ import React from 'react' import { - LayoutRectangle, + GestureResponderEvent, + LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, Platform, ScrollView, - ScrollViewProps, - StyleProp, View, - ViewStyle, } from 'react-native' import devWarning from '../_util/devWarning' -import { WithTheme, WithThemeStyles } from '../style' -import CarouselStyles, { CarouselStyle } from './style/index' - -export interface CarouselPropsType - extends WithThemeStyles, - ScrollViewProps { - accessibilityLabel?: string - pageStyle?: ViewStyle - children?: React.ReactNode - - selectedIndex?: number - dots?: boolean - vertical?: boolean - autoplay?: boolean - autoplayInterval?: number - infinite?: boolean -} - -export interface CarouselProps extends CarouselPropsType { - style?: StyleProp - dotStyle?: StyleProp - dotActiveStyle?: StyleProp - pagination?: (props: PaginationProps) => React.ReactNode - afterChange?: (index: number) => void -} +import { WithTheme } from '../style' +import { CarouselProps, PaginationProps } from './PropsType' +import CarouselStyles from './style/index' +// fix: Compatible History +export { CarouselProps, PaginationProps } from './PropsType' interface NativeScrollPoint { x: number y: number } -interface TargetedEvent { - target: number -} export interface CarouselState { width: number height: number selectedIndex: number afterSelectedIndex: number - isScrolling: boolean offset: NativeScrollPoint } -export interface PaginationProps { - vertical?: boolean - current: number - count: number - styles: ReturnType - dotStyle?: StyleProp - dotActiveStyle?: StyleProp -} - const defaultPagination = (props: PaginationProps) => { const { styles, current, vertical, count, dotStyle, dotActiveStyle } = props const positionStyle = vertical ? 'paginationY' : 'paginationX' @@ -89,7 +54,7 @@ const defaultPagination = (props: PaginationProps) => { ) } class Carousel extends React.PureComponent { - static defaultProps: CarouselProps = { + static defaultProps = { accessibilityLabel: 'Carousel', pageStyle: {}, @@ -116,7 +81,6 @@ class Carousel extends React.PureComponent { this.state = { width: 0, height: 0, - isScrolling: false, selectedIndex: index, afterSelectedIndex: -1, offset: { x: 0, y: 0 }, @@ -132,13 +96,11 @@ class Carousel extends React.PureComponent { const { width, height } = this.state if (autoplay !== this.props.autoplay) { if (autoplay) { - this.autoplay() + this.autoplay(autoplay) } else { - this.autoplayTimer && clearTimeout(this.autoplayTimer) + this.clearTimeout() } } - // selectedIndex only take effect once - // ... if ( children && @@ -153,7 +115,6 @@ class Carousel extends React.PureComponent { : { x: width * (infinite ? 1 : 0), y: 0 } this.setState( { - isScrolling: false, afterSelectedIndex: -1, selectedIndex: 0, offset: offset, @@ -165,84 +126,108 @@ class Carousel extends React.PureComponent { ) } - private autoplayTimer: ReturnType - private scrollEndTimter: ReturnType + private autoplayTimer: ReturnType | undefined + private isScrolling: boolean | undefined componentWillUnmount() { - this.autoplayTimer && clearTimeout(this.autoplayTimer) - this.scrollEndTimter && clearTimeout(this.scrollEndTimter) - } - - onScrollBegin = (e: NativeSyntheticEvent) => { - this.setState( - { - isScrolling: true, - }, - () => { - if (this.props.onScrollBeginDrag) { - this.props.onScrollBeginDrag(e) - } - }, - ) + this.clearTimeout() } - onScrollEnd = (e: NativeSyntheticEvent) => { - e.persist?.() - // android/web hack - if (!e.nativeEvent.contentOffset) { - //@ts-ignore - const { position } = e.nativeEvent - e.nativeEvent.contentOffset = { - x: this.props.vertical ? 0 : position * this.state.width, - y: this.props.vertical ? position * this.state.height : 0, - } + /** + * Plathform: iOS & android + * 手势介入时: onScrollBeginDrag -> onScrollEndDrag + * **/ + private onScrollBeginDrag = (e: NativeSyntheticEvent) => { + this.isScrolling = true + + if (this.props.onScrollBeginDrag) { + this.props.onScrollBeginDrag(e) } - this.autoplay() - clearTimeout(this.scrollEndTimter) - this.scrollEndTimter = setTimeout(() => { - this.updateIndex(e.nativeEvent.contentOffset) - - if (this.props.onMomentumScrollEnd) { - this.props.onMomentumScrollEnd(e) - } - }, 50) //idle time } + private onScrollEndDrag = (e: NativeSyntheticEvent) => { + this.isScrolling = false + // fix: drag page in Perfect fit + this.onScrollAnimationEnd( + JSON.parse(JSON.stringify(e.nativeEvent.contentOffset)), + ) - onScrollEndDrag = (e: NativeSyntheticEvent) => { - e.persist?.() - const { offset, selectedIndex } = this.state - const previousOffset = offset - const newOffset = e.nativeEvent.contentOffset - if ( - (this.props.vertical - ? previousOffset.y === newOffset.y - : previousOffset.x === newOffset.x) && - (selectedIndex === 0 || selectedIndex === this.count - 1) - ) { - this.setState({ - isScrolling: false, - }) - } if (this.props.onScrollEndDrag) { this.props.onScrollEndDrag(e) } } - onTouchStartForWeb = () => { - this.setState({ isScrolling: true }) + /** + * Plathform: web + * 手势介入时: onTouchStart -> onScroll…onScroll(只要动了就会触发) -> onTouchEnd -> onScroll(动画结束时触发) + * autoplay: [onScroll...onScroll] -> onScroll(动画结束时触发) + * **/ + private onTouchStartForWeb = (e: GestureResponderEvent) => { + this.isScrolling = true + if (this.props.onTouchStart) { + this.props.onTouchStart(e) + } + } + private onTouchEndForWeb = (e: GestureResponderEvent) => { + this.isScrolling = false + if (this.props.onTouchEnd) { + this.props.onTouchEnd(e) + } } - onTouchEndForWeb = () => { - this.autoplay() + private onScroll = (e: NativeSyntheticEvent) => { + // Simulate infinite pages + if (this.props.infinite) { + const contentOffset = JSON.parse( + JSON.stringify(e.nativeEvent.contentOffset), + ) + const { width, height } = this.state + + const offset = this.props.vertical ? 'y' : 'x' + const maxOffset = + (this.props.vertical ? height : width) * (this.count + 1) + + if (contentOffset[offset] <= 0) { + contentOffset[offset] = 0 + this.updateIndex(contentOffset) + } else if (contentOffset[offset] >= maxOffset) { + contentOffset[offset] = maxOffset + this.updateIndex(contentOffset) + } + } + + this.onScrollAnimationEnd( + JSON.parse(JSON.stringify(e.nativeEvent.contentOffset)), + ) + + if (this.props.onScroll) { + this.props.onScroll(e) + } + } + /** + * 所有scroll事件结束时触发 + * **/ + private onScrollAnimationEnd = (currentOffset: NativeScrollPoint) => { + const { x, y } = currentOffset + const { width, height } = this.state + // 🌟 fix: `onMomentumScrollEnd` & `onScrollAnimationEnd` not support for web & android 🌟 + const isScrollAnimationEnd = + !this.isScrolling && + (this.props.vertical ? y / height : x / width) % 1 === 0 + + if (isScrollAnimationEnd) { + this.updateIndex(currentOffset) + this.autoplay() + } } - onScrollForWeb = (e: any) => { - this.onScrollEnd(JSON.parse(JSON.stringify(e))) + private clearTimeout = () => { + if (this.autoplayTimer) { + clearTimeout(this.autoplayTimer) + this.autoplayTimer = undefined + } } - onLayout = ( - e: NativeSyntheticEvent, - ) => { + private onLayout = (e: LayoutChangeEvent) => { const { selectedIndex, infinite, vertical } = this.props const scrollIndex = (this.count > 1 && Math.min(selectedIndex as number, this.count - 1)) || 0 @@ -263,8 +248,8 @@ class Carousel extends React.PureComponent { offset, }, () => { - // web - this.scrollview?.current?.scrollTo({ ...offset, animated: false }) + // web & android + this.scrollview?.current?.scrollTo({ ...offset, animated: true }) this.autoplay() }, ) @@ -351,8 +336,8 @@ class Carousel extends React.PureComponent { } scrollNextPage = () => { - const { selectedIndex, isScrolling, width, height } = this.state - if (isScrolling || this.count < 2) { + const { selectedIndex, width, height } = this.state + if (this.isScrolling || this.count < 2) { return } const diff = selectedIndex + 1 + (this.props.infinite ? 1 : 0) @@ -361,22 +346,6 @@ class Carousel extends React.PureComponent { ? { x: 0, y: diff * height } : { x: diff * width, y: 0 }, ) - - this.setState( - { - isScrolling: true, - }, - () => { - if (Platform.OS !== 'ios') { - this.onScrollEnd({ - nativeEvent: { - // @ts-ignore - position: diff, - }, - }) - } - }, - ) } /** @@ -441,48 +410,37 @@ class Carousel extends React.PureComponent { ) } - private autoplay = () => { - this.setState({ isScrolling: false }, () => { - const { children, autoplay, autoplayInterval, infinite } = this.props - const { selectedIndex } = this.state - if (!Array.isArray(children) || !autoplay) { - return - } - clearTimeout(this.autoplayTimer) - this.autoplayTimer = setTimeout(() => { - if (!infinite && selectedIndex + 1 === this.count - 1) { - return - } - this.scrollNextPage() - }, autoplayInterval) - }) + private autoplay = (autoplay = this.props.autoplay) => { + const { children, autoplayInterval } = this.props + if (!Array.isArray(children) || !autoplay) { + return + } + this.clearTimeout() + this.autoplayTimer = setTimeout(() => { + this.scrollNextPage() + }, autoplayInterval) } private renderScroll = (pages: React.ReactNode) => { return ( + onScroll={this.onScroll} + onTouchStart={this.onTouchStartForWeb} + onTouchEnd={this.onTouchEndForWeb}> {pages} ) diff --git a/components/carousel/index.zh-CN.md b/components/carousel/index.zh-CN.md index 1b446b8a7..0f1f6a177 100644 --- a/components/carousel/index.zh-CN.md +++ b/components/carousel/index.zh-CN.md @@ -11,27 +11,33 @@ subtitle: 走马灯 属性 | 说明 | 类型 | 默认值 ----|-----|------|------ -| selectedIndex | 手动设置当前显示的索引 | number | 0 | -| dots | 是否显示面板指示点 | Boolean | true | -| vertical | 垂直显示 | Boolean | false | +| afterChange | 切换面板后的回调函数 | (current: number) => void | 无 | | autoplay | 是否自动切换 | Boolean | false | | autoplayInterval | 自动切换的时间间隔 | Number | 3000 | -| infinite | 是否循环播放 | Boolean | false | -| afterChange | 切换面板后的回调函数 | (current: number): void | 无 | +| dots | 是否显示面板指示点 | Boolean | true | | dotStyle | 指示点样式 | ViewStyle | 无 | | dotActiveStyle | 当前激活的指示点样式 | ViewStyle | 无 | -| pageStyle | 轮播页样式 | ViewStyle | 无 | -| pagination | 自定义 pagination | (props) => React.ReactNode | | +| infinite | 是否循环播放 | Boolean | false | +| pageStyle | 轮播页内样式 | ViewStyle | 无 | +| pagination | 自定义 pagination | (props) => ReactNode | | +| selectedIndex | 手动设置当前显示的索引 | number | 0 | +| style | 轮播容器样式
(建议设置,整体轮播大小由容器决定非页内决定) | ViewStyle | 无 | +| vertical | 垂直显示 | Boolean | false | + + +Carousel 的其他属性和 react-native 内置组件[ScrollView](https://reactnative.dev/docs/scrollview.html) 一致;
+比如:`scrollEnabled`、`onScroll` (若设置后不生效则为Carousel强制属性) ## Carousel methods -属性 | 说明 | 类型 | 默认值 -----|-----|------|------ -| goTo | 跳转到指定位置 | (index: number, animated?: boolean): void | - | +属性 | 说明 | 类型 +----|-----|------ +| goTo | 跳转到指定位置 | `(index: number, animated?: boolean) => void` | +| scrollNextPage | 滚动到下一页 | `() => void` | ## FAQ -### 在Android平台,ScrollView中嵌套使用Carousel,会发生Carousel Item不能滑动的情况,怎么办? +### 1. 在Android平台,ScrollView中嵌套使用Carousel,会发生Carousel Item不能滑动的情况,怎么办? `5.1.3`新增支持。 设置`ScrollView`的`nestedScrollEnabled`属性为`true`即可。 @@ -40,4 +46,9 @@ subtitle: 走马灯 ... -``` \ No newline at end of file +``` + +### 2. Carousel和 `react-native-pager-view` 有什么区别(或优势)? + +首先,Carousel支持`infinite`属性,即🌟真正的无限循环🌟。
+其次,Carousel是完全基于`ScrollView`实现,不仅更轻量,且更具有兼容性。 \ No newline at end of file diff --git a/components/grid/__tests__/__snapshots__/demo.test.js.snap b/components/grid/__tests__/__snapshots__/demo.test.js.snap index 87613c192..b657dcecb 100644 --- a/components/grid/__tests__/__snapshots__/demo.test.js.snap +++ b/components/grid/__tests__/__snapshots__/demo.test.js.snap @@ -926,19 +926,22 @@ exports[`renders ./components/grid/demo/basic.tsx correctly 1`] = ` } } directionalLockEnabled={true} + disableIntervalMomentum={false} dotActiveStyle={Object {}} dotStyle={Object {}} dots={true} horizontal={true} infinite={false} nestedScrollEnabled={true} - onMomentumScrollEnd={[Function]} + onScroll={[Function]} onScrollBeginDrag={[Function]} onScrollEndDrag={[Function]} + onTouchEnd={[Function]} + onTouchStart={[Function]} pageStyle={Object {}} pagination={[Function]} pagingEnabled={true} - removeClippedSubviews={false} + scrollEventThrottle={16} selectedIndex={0} showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false} diff --git a/example/app.json b/example/app.json index 3b5866e01..0cf6791f0 100644 --- a/example/app.json +++ b/example/app.json @@ -4,7 +4,7 @@ "expo": { "name": "@ant-design/react-native", "slug": "ant-design-mobile-rn", - "version": "5.2.2", + "version": "5.2.3", "description": "基于蚂蚁金服移动设计规范的 React Native 组件库", "icon": "../rn-kitchen-sink/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png", "splash": { diff --git a/example/package.json b/example/package.json index 7c54ee1f3..44a6405fd 100644 --- a/example/package.json +++ b/example/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/react-native-example", - "version": "5.2.2", + "version": "5.2.3", "description": "Demo app for ant-design mobile RN UI Library", "private": true, "homepage": ".", @@ -18,17 +18,17 @@ }, "dependencies": { "@ant-design/icons-react-native": "^2.3.2", - "@expo/metro-runtime": "~3.1.3", - "expo": "^50.0.3", + "@expo/metro-runtime": "~3.2.3", + "expo": "51", "expo-haptics": "^13.0.1", - "expo-splash-screen": "~0.26.3", - "expo-status-bar": "~1.11.1", - "expo-updates": "~0.24.11", + "expo-splash-screen": "~0.27.5", + "expo-status-bar": "~1.12.1", + "expo-updates": "~0.25.24", "react": "18.2.0", "react-dom": "18.2.0", "react-native": "0.73.2", - "react-native-gesture-handler": "~2.14.0", - "react-native-reanimated": "~3.6.2", + "react-native-gesture-handler": "~2.16.1", + "react-native-reanimated": "~3.10.1", "react-native-web": "~0.19.6" }, "devDependencies": { diff --git a/package.json b/package.json index 76d0f30a5..c61b39178 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ant-design/react-native", - "version": "5.2.2", + "version": "5.2.3", "description": "基于蚂蚁金服移动设计规范的 React Native 组件库", "keywords": [ "ant",