|
@@ -0,0 +1,7922 @@
|
|
|
|
|
+# Ant Design Mobile RN Component Documentation
|
|
|
|
|
+
|
|
|
|
|
+Aggregated content from all component docs.
|
|
|
|
|
+
|
|
|
|
|
+> 47 components
|
|
|
|
|
+
|
|
|
|
|
+## Accordion
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/accordion.md
|
|
|
|
|
+
|
|
|
|
|
+# Accordion
|
|
|
|
|
+
|
|
|
|
|
+> This package has been deprecated in `5.2.1`, recommend [components/Collapse](/components/collapse)
|
|
|
|
|
+
|
|
|
|
|
+You can collapse / expand the content area.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- Group and hide complex areas.
|
|
|
|
|
+- Typically, only a single content area is allowed to expand at a time; in special cases, multiple content areas can be expanded at the same time.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Accordion, List } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class AccordionExmple extends React.Component<any, any> {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ activeSections: [2, 0],
|
|
|
|
|
+ }
|
|
|
|
|
+ onChange = (activeSections: number[]) => {
|
|
|
|
|
+ this.setState({ activeSections })
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ marginTop: 80, marginBottom: 10 }}>
|
|
|
|
|
+ <Accordion
|
|
|
|
|
+ onChange={this.onChange}
|
|
|
|
|
+ activeSections={this.state.activeSections}>
|
|
|
|
|
+ <Accordion.Panel header="Title 1">
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <List.Item>Content 1</List.Item>
|
|
|
|
|
+ <List.Item>Content 2</List.Item>
|
|
|
|
|
+ <List.Item>Content 3</List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </Accordion.Panel>
|
|
|
|
|
+ <Accordion.Panel header="Title 2">
|
|
|
|
|
+ this is panel content2 or other
|
|
|
|
|
+ </Accordion.Panel>
|
|
|
|
|
+ <Accordion.Panel header="Title 3">
|
|
|
|
|
+ Text text text text text text text text text text text text text
|
|
|
|
|
+ text text
|
|
|
|
|
+ </Accordion.Panel>
|
|
|
|
|
+ </Accordion>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Accordion
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default |
|
|
|
|
|
+| ----------------- | ------------------------------------------------------------------------------------------------ | ------------------------- | ------- |
|
|
|
|
|
+| onChange(indexes) | A function that is called when the currently active section(s) are updated. | (indexes: number[])=>void | - |
|
|
|
|
|
+| activeSections | Control which indices in the `sections` array are currently open. If empty, closes all sections. | number[] | [] |
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Read more https://github.com/oblador/react-native-collapsible#properties-1
|
|
|
|
|
+
|
|
|
|
|
+### Accordion.Panel
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default |
|
|
|
|
|
+| ---------- | ----------------------- | ----------------------- | ------- |
|
|
|
|
|
+| key | corresponding activeKey | String | - |
|
|
|
|
|
+| header | header content of Panel | React.Element or String | - |
|
|
|
|
|
+
|
|
|
|
|
+Note: Currently does not support nested use for RN.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## ActionSheet
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/action-sheet.md
|
|
|
|
|
+
|
|
|
|
|
+# ActionSheet
|
|
|
|
|
+
|
|
|
|
|
+The modal box pops up from the bottom, providing more than two actions related to the current scene, and also support provide the title and description. Built-in fixed display style, does not support particularly flexible changes.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Provide a clear exit button.
|
|
|
|
|
+- Can highlight the destructive operation, e.g. "delete" use red text.
|
|
|
|
|
+- Do not place too much content to avoid vertical roll of the panel.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { ActionSheet, Button, Provider } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Platform, Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class Test extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ clicked: 'none',
|
|
|
|
|
+ text: '',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <View style={{ marginTop: 30 }}>
|
|
|
|
|
+ <View style={[{ padding: 8 }]}>
|
|
|
|
|
+ <Button onPress={this.showActionSheet}>showActionSheet</Button>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Text style={[{ padding: 8 }]}>
|
|
|
|
|
+ clicked button: {this.state.clicked}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <View style={[{ padding: 8 }]}>
|
|
|
|
|
+ <Button onPress={this.showShareActionSheet}>
|
|
|
|
|
+ showShareActionSheet
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Text style={[{ padding: 8 }]}>{this.state.text}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ showActionSheet = () => {
|
|
|
|
|
+ const BUTTONS = [
|
|
|
|
|
+ 'Operation1',
|
|
|
|
|
+ 'Operation2',
|
|
|
|
|
+ 'Operation3',
|
|
|
|
|
+ 'Delete',
|
|
|
|
|
+ 'Cancel',
|
|
|
|
|
+ ]
|
|
|
|
|
+ ActionSheet.showActionSheetWithOptions(
|
|
|
|
|
+ {
|
|
|
|
|
+ title: 'Title',
|
|
|
|
|
+ message: 'Description',
|
|
|
|
|
+ options: BUTTONS,
|
|
|
|
|
+ cancelButtonIndex: 4,
|
|
|
|
|
+ destructiveButtonIndex: 3,
|
|
|
|
|
+ },
|
|
|
|
|
+ (buttonIndex: any) => {
|
|
|
|
|
+ this.setState({ clicked: BUTTONS[buttonIndex] })
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ showShareActionSheet = () => {
|
|
|
|
|
+ const opts: any = {
|
|
|
|
|
+ message: 'Message to go with the shared url',
|
|
|
|
|
+ title: 'Share Actionsheet',
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (Platform.OS === 'ios') {
|
|
|
|
|
+ opts.url = 'https://www.alipay.com/'
|
|
|
|
|
+ opts.tintColor = '#ff0000'
|
|
|
|
|
+ opts.excludedActivityTypes = ['com.apple.UIKit.activity.PostToTwitter']
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ActionSheet.showShareActionSheetWithOptions(
|
|
|
|
|
+ opts,
|
|
|
|
|
+ (error: any) => alert(error),
|
|
|
|
|
+ (success: any, method: any) => {
|
|
|
|
|
+ let text
|
|
|
|
|
+ if (success) {
|
|
|
|
|
+ text = `Shared with ${method}`
|
|
|
|
|
+ } else {
|
|
|
|
|
+ text = 'Did not share'
|
|
|
|
|
+ }
|
|
|
|
|
+ this.setState({ text })
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const title = 'ActionSheet'
|
|
|
|
|
+export const description = 'ActionSheet example'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+### ActionSheet.showActionSheetWithOptions(options, callback)
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| options | ActionSheet's options | Object | - |
|
|
|
|
|
+| callback | Callback for selected item | (index:number):void | - |
|
|
|
|
|
+
|
|
|
|
|
+Display a action sheet. The `options` object must contain one or more of:
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| options | a list of button titles (required) | Array or String | - |
|
|
|
|
|
+| cancelButtonIndex | index of cancel button in `options` | Number | - |
|
|
|
|
|
+| destructiveButtonIndex | index of destructive button in `options` | Number | - |
|
|
|
|
|
+| title | a title to show above the action sheet | String | - |
|
|
|
|
|
+| message | a message to show below the title | String or React.element | - |
|
|
|
|
|
+
|
|
|
|
|
+### ActionSheet.showShareActionSheetWithOptions(options, failureCallback?, successCallback?)
|
|
|
|
|
+
|
|
|
|
|
+`React-Native Only, react-native@version >= 0.39`
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| options | ShareActionSheet's options | Object | - |
|
|
|
|
|
+| failureCallback | Callback for share failed(`iOS Only`, See [react-native/share](https://github.com/facebook/react-native/blob/master/Libraries/Share/Share.js#L80) ) | (error):void | - |
|
|
|
|
|
+| successCallback | Callback for share successed(`iOS Only`, See [react-native/share](https://github.com/facebook/react-native/blob/master/Libraries/Share/Share.js#L80) ) | (completed:Boolean, activityType?:String):void | - |
|
|
|
|
|
+
|
|
|
|
|
+Display a shareable action sheet. The `options` object must contain one or more of:
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| message | a message to share | String | - |
|
|
|
|
|
+| title | title of the message | String | - |
|
|
|
|
|
+| url | an URL to share `iOS Only` | String | - |
|
|
|
|
|
+| excludedActivityTypes | the activities to exclude from the ShareActionSheet `iOS Only` | Array | - |
|
|
|
|
|
+
|
|
|
|
|
+### ActionSheet.close()
|
|
|
|
|
+Close the action sheet.`Android Only`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## ActivityIndicator
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/activity-indicator.md
|
|
|
|
|
+
|
|
|
|
|
+# ActivityIndicator
|
|
|
|
|
+
|
|
|
|
|
+`ActivityIndicator` indicates that a task is currently in progress.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- Don't stop activity indicator if the task is not completed.
|
|
|
|
|
+- By providing meaningful texts under certain circumstances can help user understand which task is in progress. eg: uploading photos.
|
|
|
|
|
+- If you know the user's waiting time, you can use `Progress` instead.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { ActivityIndicator, Button, Flex, WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { StyleSheet, Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class ActivityIndicatorExample extends React.Component<
|
|
|
|
|
+ any,
|
|
|
|
|
+ any
|
|
|
|
|
+> {
|
|
|
|
|
+ closeTimer: any
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ animating: false,
|
|
|
|
|
+ }
|
|
|
|
|
+ this.loadingToast = this.loadingToast.bind(this)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ componentWillUnmount() {
|
|
|
|
|
+ clearTimeout(this.closeTimer)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ loadingToast() {
|
|
|
|
|
+ this.setState({ animating: !this.state.animating })
|
|
|
|
|
+ this.closeTimer = setTimeout(() => {
|
|
|
|
|
+ this.setState({ animating: !this.state.animating })
|
|
|
|
|
+ }, 2000)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={[styles.demo]}>
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <Text>Icon without text</Text>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <ActivityIndicator />
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace size="xl" style={{ backgroundColor: '#fff' }} />
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <Text>Icon with text</Text>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <ActivityIndicator text="Loading..." />
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace size="xl" style={{ backgroundColor: '#fff' }} />
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <Text>Dark Background</Text>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <View style={[styles.darkBg]}>
|
|
|
|
|
+ <ActivityIndicator color="#fff" />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace size="xl" style={{ backgroundColor: '#fff' }} />
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <Text>Large Size</Text>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item>
|
|
|
|
|
+ <ActivityIndicator size="large" />
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace size="xl" style={{ backgroundColor: '#fff' }} />
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Button onPress={this.loadingToast}>Click to show Toast</Button>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <ActivityIndicator
|
|
|
|
|
+ animating={this.state.animating}
|
|
|
|
|
+ toast
|
|
|
|
|
+ size="large"
|
|
|
|
|
+ text="Loading..."
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const styles = StyleSheet.create({
|
|
|
|
|
+ demo: {
|
|
|
|
|
+ marginTop: 20,
|
|
|
|
|
+ },
|
|
|
|
|
+ darkBg: {
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ width: 89,
|
|
|
|
|
+ height: 89,
|
|
|
|
|
+ backgroundColor: '#2B2F42',
|
|
|
|
|
+ },
|
|
|
|
|
+ gray: {
|
|
|
|
|
+ backgroundColor: '#CCC',
|
|
|
|
|
+ },
|
|
|
|
|
+ horizontal: {
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ justifyContent: 'space-around',
|
|
|
|
|
+ padding: 8,
|
|
|
|
|
+ },
|
|
|
|
|
+})
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<ActivityIndicator />
|
|
|
|
|
+<ActivityIndicator color="white" />
|
|
|
|
|
+<ActivityIndicator size="large" />
|
|
|
|
|
+<ActivityIndicator text="loading" />
|
|
|
|
|
+<ActivityIndicator toast />
|
|
|
|
|
+<ActivityIndicator toast text="loading" />
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### ActivityIndicator
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| animating | Whether to show the indicator (true, the default) or hide it (false). | boolean | true |
|
|
|
|
|
+| size | Size of the indicator (`small`/`large` or number [android only]) | string\|number | small |
|
|
|
|
|
+| toast | Whether to use toast style | boolean | false |
|
|
|
|
|
+| text | loading text behind the indicator | string | - |
|
|
|
|
|
+| color | The foreground color of the spinner (default is gray). | string | gray |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Badge
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/badge.md
|
|
|
|
|
+
|
|
|
|
|
+# Badge
|
|
|
|
|
+
|
|
|
|
|
+The red dot at corner for notification and getting user attention.
|
|
|
|
|
+
|
|
|
|
|
+### When to use
|
|
|
|
|
+
|
|
|
|
|
+- Use plain dot badge when user just need to know there is something new, eg: one-to-one new messages.
|
|
|
|
|
+- Use numberic badge when user need to know specific number of notifications, eg: new messages from a group.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Badge, WhiteSpace } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicTagExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ style={{ flex: 1 }}
|
|
|
|
|
+ automaticallyAdjustContentInsets={false}
|
|
|
|
|
+ showsHorizontalScrollIndicator={false}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}>
|
|
|
|
|
+ <View style={{ padding: 20 }}>
|
|
|
|
|
+ <Badge text={9}>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: 52,
|
|
|
|
|
+ height: 52,
|
|
|
|
|
+ backgroundColor: 'rgba(255, 140, 101, 0.15)',
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+
|
|
|
|
|
+ <Badge text={109} overflowCount={100}>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: 52,
|
|
|
|
|
+ height: 52,
|
|
|
|
|
+ backgroundColor: 'rgba(255, 140, 101, 0.15)',
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+
|
|
|
|
|
+ <Badge text={109}>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: 52,
|
|
|
|
|
+ height: 52,
|
|
|
|
|
+ backgroundColor: 'rgba(255, 140, 101, 0.15)',
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+
|
|
|
|
|
+ <Badge text="new">
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: 52,
|
|
|
|
|
+ height: 52,
|
|
|
|
|
+ backgroundColor: 'rgba(255, 140, 101, 0.15)',
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+
|
|
|
|
|
+ <Badge text={109} dot>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: 52,
|
|
|
|
|
+ height: 52,
|
|
|
|
|
+ backgroundColor: 'rgba(255, 140, 101, 0.15)',
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+
|
|
|
|
|
+ <Badge text={33} corner>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ width: 52,
|
|
|
|
|
+ height: 52,
|
|
|
|
|
+ backgroundColor: 'rgba(255, 140, 101, 0.15)',
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Badge>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+size | size of badge, optional: `large` `small` | string | `small`
|
|
|
|
|
+text | text or number inside badge | string\|number | -
|
|
|
|
|
+corner | whether is badge at corner position | boolean | `false`
|
|
|
|
|
+dot | show badge as a red dot | boolean | `false`
|
|
|
|
|
+overflowCount | max count to show | number | `99`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Button
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/button.md
|
|
|
|
|
+
|
|
|
|
|
+# Button
|
|
|
|
|
+
|
|
|
|
|
+To trigger an operation.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Icon, WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+
|
|
|
|
|
+export default () => (
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button>default</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button disabled>default disabled</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+
|
|
|
|
|
+ <Button type="primary">primary</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button type="primary" disabled>
|
|
|
|
|
+ primary disabled
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+
|
|
|
|
|
+ <Button type="warning">warning</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button type="warning" disabled>
|
|
|
|
|
+ warning disabled
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+
|
|
|
|
|
+ <Button loading>loading button</Button>
|
|
|
|
|
+
|
|
|
|
|
+ <Button activeStyle={false}>No click feedback</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button underlayColor={'blue'}>Custom Underlay</Button>
|
|
|
|
|
+ <Button activeStyle={{ backgroundColor: 'red' }}>
|
|
|
|
|
+ custom feedback style
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+
|
|
|
|
|
+ <Button
|
|
|
|
|
+ styles={{
|
|
|
|
|
+ rawText: { color: 'darkgray' },
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'red',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ custon background and text color
|
|
|
|
|
+ </Button>
|
|
|
|
|
+
|
|
|
|
|
+ <WingBlank
|
|
|
|
|
+ style={{
|
|
|
|
|
+ marginTop: 20,
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ justifyContent: 'space-between',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Button type="ghost">ghost</Button>
|
|
|
|
|
+ <Button type="ghost" disabled>
|
|
|
|
|
+ ghost disabled
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button type="ghost" size="small">
|
|
|
|
|
+ ghost
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+
|
|
|
|
|
+ <Button type="primary">
|
|
|
|
|
+ <Icon name="login" />
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| type | can be set to `primary`/`ghost`/`warning` or omitted | string | - |
|
|
|
|
|
+| size | can be set to `large`、`small` or omitted | string | `large`|
|
|
|
|
|
+| activeStyle | the feedback's custom style (set to false to disable click feedback) | {}/false | {} |
|
|
|
|
|
+| activeClassName | the feedback's custom class name | string | |
|
|
|
|
|
+| disabled | set disabled | boolean | false |
|
|
|
|
|
+| onPress | set the handler to handle `click` event | (e: Object): void | - |
|
|
|
|
|
+| style | custom style | Object | - |
|
|
|
|
|
+| styles | Semantic DOM style | [ButtonStyles](#buttonStyles-interface) | - |
|
|
|
|
|
+| onPressIn | same as RN Pressable onPressIn | (e: Object): void | - |
|
|
|
|
|
+| onPressOut | same as RN Pressable onPressOut | (e: Object): void | - |
|
|
|
|
|
+| onShowUnderlay | same as RN Pressable onPressIn but only triggered if `activeStyle` is not false | (e: Object): void | - |
|
|
|
|
|
+| onHideUnderlay | same as RN Pressable onPressOut but only triggered if `activeStyle` is not false | (e: Object): void | - |
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### ButtonStyles interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface ButtonStyles {
|
|
|
|
|
+ container: ViewStyle
|
|
|
|
|
+ defaultHighlight: ViewStyle
|
|
|
|
|
+ primaryHighlight: ViewStyle
|
|
|
|
|
+ ghostHighlight: ViewStyle
|
|
|
|
|
+ warningHighlight: ViewStyle
|
|
|
|
|
+ wrapperStyle: ViewStyle
|
|
|
|
|
+ underlayStyle: ViewStyle
|
|
|
|
|
+ largeRaw: ViewStyle
|
|
|
|
|
+ largeUnderlayContainerRaw: ViewStyle
|
|
|
|
|
+ smallRaw: ViewStyle
|
|
|
|
|
+ smallUnderlayContainerRaw: ViewStyle
|
|
|
|
|
+ defaultRaw: ViewStyle
|
|
|
|
|
+ defaultUnderlayContainerRaw: ViewStyle
|
|
|
|
|
+ primaryRaw: ViewStyle
|
|
|
|
|
+ primaryUnderlayContainerRaw: ViewStyle
|
|
|
|
|
+ ghostRaw: ViewStyle
|
|
|
|
|
+ ghostUnderlayContainerRaw: ViewStyle
|
|
|
|
|
+ warningRaw: ViewStyle
|
|
|
|
|
+ warningUnderlayContainerRaw: ViewStyle
|
|
|
|
|
+ defaultDisabledRaw: ViewStyle
|
|
|
|
|
+ primaryDisabledRaw: ViewStyle
|
|
|
|
|
+ ghostDisabledRaw: ViewStyle
|
|
|
|
|
+ warningDisabledRaw: ViewStyle
|
|
|
|
|
+ defaultHighlightText: TextStyle
|
|
|
|
|
+ primaryHighlightText: TextStyle
|
|
|
|
|
+ ghostHighlightText: TextStyle
|
|
|
|
|
+ warningHighlightText: TextStyle
|
|
|
|
|
+ rawText: TextStyle
|
|
|
|
|
+ largeRawText: TextStyle
|
|
|
|
|
+ smallRawText: TextStyle
|
|
|
|
|
+ defaultRawText: TextStyle
|
|
|
|
|
+ primaryRawText: TextStyle
|
|
|
|
|
+ ghostRawText: TextStyle
|
|
|
|
|
+ warningRawText: TextStyle
|
|
|
|
|
+ defaultDisabledRawText: TextStyle
|
|
|
|
|
+ primaryDisabledRawText: TextStyle
|
|
|
|
|
+ ghostDisabledRawText: TextStyle
|
|
|
|
|
+ warningDisabledRawText: TextStyle
|
|
|
|
|
+ indicator: ViewStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Card
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/card.md
|
|
|
|
|
+
|
|
|
|
|
+# Card
|
|
|
|
|
+
|
|
|
|
|
+Card can be used to organize information and operations, usually also as an entry for detailed information.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- The shape is rectangular.
|
|
|
|
|
+- The content can consist of multiple elements of varying type, eg: images, texts, buttons, etc.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Card, WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicCardExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ paddingTop: 30 }}>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Card>
|
|
|
|
|
+ <Card.Header
|
|
|
|
|
+ title="This is title"
|
|
|
|
|
+ thumbStyle={{ width: 30, height: 30 }}
|
|
|
|
|
+ thumb="https://gw.alipayobjects.com/zos/rmsportal/MRhHctKOineMbKAZslML.jpg"
|
|
|
|
|
+ extra="this is extra"
|
|
|
|
|
+ />
|
|
|
|
|
+ <Card.Body>
|
|
|
|
|
+ <View style={{ height: 42 }}>
|
|
|
|
|
+ <Text style={{ marginLeft: 16 }}>Card Content</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Card.Body>
|
|
|
|
|
+ <Card.Footer
|
|
|
|
|
+ content="footer content"
|
|
|
|
|
+ extra="footer extra content"
|
|
|
|
|
+ />
|
|
|
|
|
+ </Card>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <Card full>
|
|
|
|
|
+ <Card.Header
|
|
|
|
|
+ title="Full Column"
|
|
|
|
|
+ thumbStyle={{ width: 30, height: 30 }}
|
|
|
|
|
+ thumb="https://gw.alipayobjects.com/zos/rmsportal/MRhHctKOineMbKAZslML.jpg"
|
|
|
|
|
+ extra="this is extra"
|
|
|
|
|
+ />
|
|
|
|
|
+ <Card.Body>
|
|
|
|
|
+ <View style={{ height: 42 }}>
|
|
|
|
|
+ <Text style={{ marginLeft: 16 }}>Card Content</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Card.Body>
|
|
|
|
|
+ <Card.Footer content="footer content" extra="footer extra content" />
|
|
|
|
|
+ </Card>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Card
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| full | whether is full column | boolean | `false` |
|
|
|
|
|
+
|
|
|
|
|
+### Card.Header
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+|title| title for `Card.Header` | React.Element、String | |
|
|
|
|
|
+|thumb| thumb to render in the left of `Card.Header` | String、React.Element | |
|
|
|
|
|
+|thumbStyle| style of thumb | Object | {} |
|
|
|
|
|
+|extra| extra content to render in the right of `Card.Header` | React.Element、String | |
|
|
|
|
|
+
|
|
|
|
|
+### Card.Body
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| | | | |
|
|
|
|
|
+
|
|
|
|
|
+### Card.Footer
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+|content| content of `Card.Footer` | React.Element、String | |
|
|
|
|
|
+|extra| extra content of `Card.Footer` | React.Element、String | |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Carousel
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/carousel.md
|
|
|
|
|
+
|
|
|
|
|
+# Carousel
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Carousel } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import {
|
|
|
|
|
+ ScrollView,
|
|
|
|
|
+ StyleSheet,
|
|
|
|
|
+ Text,
|
|
|
|
|
+ TextStyle,
|
|
|
|
|
+ View,
|
|
|
|
|
+ ViewStyle,
|
|
|
|
|
+} from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicCarouselExample extends React.Component<any, any> {
|
|
|
|
|
+ carousel: null | Carousel
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ selectedIndex: 2,
|
|
|
|
|
+ autoplay: true,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ onHorizontalSelectedIndexChange = (index: number) => {
|
|
|
|
|
+ /* tslint:disable: no-console */
|
|
|
|
|
+ console.log('horizontal change to', index)
|
|
|
|
|
+ this.setState({ selectedIndex: index })
|
|
|
|
|
+ }
|
|
|
|
|
+ onVerticalSelectedIndexChange(index: number) {
|
|
|
|
|
+ /* tslint:disable: no-console */
|
|
|
|
|
+ console.log('vertical change to', index)
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView style={{ paddingTop: 30 }}>
|
|
|
|
|
+ <View style={{ paddingHorizontal: 15 }}>
|
|
|
|
|
+ <Text>horizontal</Text>
|
|
|
|
|
+ <Carousel
|
|
|
|
|
+ style={styles.wrapper}
|
|
|
|
|
+ selectedIndex={this.state.selectedIndex}
|
|
|
|
|
+ autoplay
|
|
|
|
|
+ infinite
|
|
|
|
|
+ afterChange={this.onHorizontalSelectedIndexChange}
|
|
|
|
|
+ ref={(ref) => (this.carousel = ref)}>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerHorizontal, { backgroundColor: 'red' }]}>
|
|
|
|
|
+ <Text>Carousel 1</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerHorizontal, { backgroundColor: 'blue' }]}>
|
|
|
|
|
+ <Text>Carousel 2</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ styles.containerHorizontal,
|
|
|
|
|
+ { backgroundColor: 'yellow' },
|
|
|
|
|
+ ]}>
|
|
|
|
|
+ <Text>Carousel 3</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerHorizontal, { backgroundColor: 'aqua' }]}>
|
|
|
|
|
+ <Text>Carousel 4</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ styles.containerHorizontal,
|
|
|
|
|
+ { backgroundColor: 'fuchsia' },
|
|
|
|
|
+ ]}>
|
|
|
|
|
+ <Text>Carousel 5</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Carousel>
|
|
|
|
|
+ <Button onPress={() => this.carousel && this.carousel.goTo(0)}>
|
|
|
|
|
+ Go to 0
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={{ paddingHorizontal: 15 }}>
|
|
|
|
|
+ <Text>vertical</Text>
|
|
|
|
|
+ <Carousel
|
|
|
|
|
+ style={styles.wrapper}
|
|
|
|
|
+ selectedIndex={1}
|
|
|
|
|
+ autoplay={this.state.autoplay}
|
|
|
|
|
+ infinite
|
|
|
|
|
+ afterChange={this.onVerticalSelectedIndexChange}
|
|
|
|
|
+ vertical>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerVertical, { backgroundColor: 'red' }]}>
|
|
|
|
|
+ <Text>Carousel 1</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerVertical, { backgroundColor: 'blue' }]}>
|
|
|
|
|
+ <Text>Carousel 2</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerVertical, { backgroundColor: 'yellow' }]}>
|
|
|
|
|
+ <Text>Carousel 3</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[styles.containerVertical, { backgroundColor: 'aqua' }]}>
|
|
|
|
|
+ <Text>Carousel 4</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ styles.containerVertical,
|
|
|
|
|
+ { backgroundColor: 'fuchsia' },
|
|
|
|
|
+ ]}>
|
|
|
|
|
+ <Text>Carousel 5</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Carousel>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => this.setState({ autoplay: !this.state.autoplay })}>
|
|
|
|
|
+ {`Toggle autoplay ${this.state.autoplay ? 'true' : 'false'}`}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const styles = StyleSheet.create<{
|
|
|
|
|
+ wrapper: ViewStyle
|
|
|
|
|
+ containerHorizontal: ViewStyle
|
|
|
|
|
+ containerVertical: ViewStyle
|
|
|
|
|
+ text: TextStyle
|
|
|
|
|
+}>({
|
|
|
|
|
+ wrapper: {
|
|
|
|
|
+ backgroundColor: '#fff',
|
|
|
|
|
+ width: '100%',
|
|
|
|
|
+ height: 150,
|
|
|
|
|
+ },
|
|
|
|
|
+ containerHorizontal: {
|
|
|
|
|
+ flexGrow: 1,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ },
|
|
|
|
|
+ containerVertical: {
|
|
|
|
|
+ flexGrow: 1,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ },
|
|
|
|
|
+ text: {
|
|
|
|
|
+ color: '#fff',
|
|
|
|
|
+ fontSize: 36,
|
|
|
|
|
+ },
|
|
|
|
|
+})
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|---------|----------
|
|
|
|
|
+| 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 | |
|
|
|
|
|
+| 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 | |
|
|
|
|
|
+| lazy | Function which takes an object with the current page and returns a boolean to indicate whether to lazily render the scenes. | Boolean \| `(index:number) => boolean` | false | `5.3.1` |
|
|
|
|
|
+| renderLazyPlaceholder | A callback that returns a custom React Element to render for pages not yet rendered. Requires the `lazy` prop to be enabled. | `(index:number) => ReactNode` | - | `5.3.1` |
|
|
|
|
|
+| pageStyle | style of the carousel page | ViewStyle | | |
|
|
|
|
|
+| pagination | A generator function which could be used to customized pagination. | (props) => ReactNode | | |
|
|
|
|
|
+| selectedIndex | current selected index | number | 0 | |
|
|
|
|
|
+| style | ScrollView style<br/>(`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 | |
|
|
|
|
|
+| onScrollAnimationEnd | Called when a scrolling animation ends. | ()=>void | | `5.3.0` |
|
|
|
|
|
+
|
|
|
|
|
+The rest of the props of Carousel are exactly the same as the react-native [ScrollView](https://reactnative.dev/docs/scrollview.html);
|
|
|
|
|
+
|
|
|
|
|
+eg: `scrollEnabled`、`onScroll` (if it not works, it is a mandatory prop of Carousel)
|
|
|
|
|
+
|
|
|
|
|
+## Carousel ref methods
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type
|
|
|
|
|
+----|-----|------
|
|
|
|
|
+| goTo | jump to specified index | `(index: number, animated?: boolean): void` |
|
|
|
|
|
+| scrollNextPage | scroll to next page | `() => void` |
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### 1. On the Android platform, when using `Carousel` nested in `ScrollView`, the Carousel Item cannot slide. What should I do?
|
|
|
|
|
+
|
|
|
|
|
+Support in `5.1.3`. Set the `nestedScrollEnabled` property of `ScrollView` to `true`.
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<ScrollView nestedScrollEnabled={true}>
|
|
|
|
|
+ ...
|
|
|
|
|
+ <Carousel vertical/>
|
|
|
|
|
+</ScrollView>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2. Use `lazy` and `renderLazyPlaceholder` props to render routes as needed
|
|
|
|
|
+
|
|
|
|
|
+Support in `5.3.1`.
|
|
|
|
|
+```jsx
|
|
|
|
|
+// `lazy={true}` only the current page is rendered
|
|
|
|
|
+<Carousel
|
|
|
|
|
+ lazy
|
|
|
|
|
+ renderLazyPlaceholder={()=> <Loading /> }
|
|
|
|
|
+/>
|
|
|
|
|
+
|
|
|
|
|
+// eg: Render the sibling pages, a total of 3 pages
|
|
|
|
|
+<Carousel
|
|
|
|
|
+ lazy={(i) => Math.abs(selectedIndex - i) < 2}
|
|
|
|
|
+>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3. Why choose Carousel instead of `react-native-pager-view` ?
|
|
|
|
|
+
|
|
|
|
|
+First, Carousel supports the `infinite` property, which means 🌟a true infinite loop🌟. <br/>
|
|
|
|
|
+Second, Carousel is completely based on `ScrollView`, which is not only lighter but also more compatible.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Checkbox
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/checkbox.md
|
|
|
|
|
+
|
|
|
|
|
+# Checkbox
|
|
|
|
|
+
|
|
|
|
|
+Checkbox
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Checkbox, Flex, List, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+const AgreeItem = Checkbox.AgreeItem
|
|
|
|
|
+const CheckboxItem = Checkbox.CheckboxItem
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicCheckboxExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any, context: any) {
|
|
|
|
|
+ super(props, context)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ checked: true,
|
|
|
|
|
+ disabled: false,
|
|
|
|
|
+
|
|
|
|
|
+ checkBox1: true,
|
|
|
|
|
+ agreeItem1: true,
|
|
|
|
|
+ checkboxItem1: true,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange = (e: { target: { checked: boolean } }) => {
|
|
|
|
|
+ console.log(`checked = ${e.target.checked}`)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ toggleChecked = () => {
|
|
|
|
|
+ this.setState({ checked: !this.state.checked })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ toggleDisable = () => {
|
|
|
|
|
+ this.setState({ disabled: !this.state.disabled })
|
|
|
|
|
+ }
|
|
|
|
|
+ onChange2 = (e: { target: { checked: boolean } }) => {
|
|
|
|
|
+ console.log('checked = ', e.target.checked)
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ checked: e.target.checked,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const label = `${this.state.checked ? 'Checked' : 'Unchecked'}-${
|
|
|
|
|
+ this.state.disabled ? 'Disabled' : 'Enabled'
|
|
|
|
|
+ }`
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List renderHeader="基本用法">
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ thumb={<Checkbox onChange={this.onChange}>Checkbox</Checkbox>}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="不可用">
|
|
|
|
|
+ <List.Item thumb={<Checkbox defaultChecked={false} disabled />} />
|
|
|
|
|
+ <List.Item thumb={<Checkbox defaultChecked disabled />} />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List
|
|
|
|
|
+ renderHeader="受控的Checkbox"
|
|
|
|
|
+ renderFooter={
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Flex.Item style={{ margin: 10 }}>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ onPress={this.toggleChecked}>
|
|
|
|
|
+ {!this.state.checked ? 'Check' : 'Uncheck'}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item style={{ margin: 10 }}>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ onPress={this.toggleDisable}>
|
|
|
|
|
+ {!this.state.disabled ? 'Disable' : 'Enable'}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ }>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ thumb={
|
|
|
|
|
+ <Checkbox
|
|
|
|
|
+ checked={this.state.checked}
|
|
|
|
|
+ disabled={this.state.disabled}
|
|
|
|
|
+ onChange={this.onChange2}>
|
|
|
|
|
+ {label}
|
|
|
|
|
+ </Checkbox>
|
|
|
|
|
+ }
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="AgreeItem">
|
|
|
|
|
+ <AgreeItem>
|
|
|
|
|
+ Agree agreement agreement agreement agreement agreement agreement
|
|
|
|
|
+ agreement
|
|
|
|
|
+ </AgreeItem>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="CheckboxItem">
|
|
|
|
|
+ <CheckboxItem
|
|
|
|
|
+ checked={this.state.checkboxItem1}
|
|
|
|
|
+ onChange={(event) => {
|
|
|
|
|
+ this.setState({ checkboxItem1: event.target.checked })
|
|
|
|
|
+ }}>
|
|
|
|
|
+ Option 1
|
|
|
|
|
+ </CheckboxItem>
|
|
|
|
|
+ <CheckboxItem>Option 2</CheckboxItem>
|
|
|
|
|
+ <CheckboxItem disabled>Option 3</CheckboxItem>
|
|
|
|
|
+ <CheckboxItem disabled checked right>
|
|
|
|
|
+ More...
|
|
|
|
|
+ </CheckboxItem>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List
|
|
|
|
|
+ renderHeader={
|
|
|
|
|
+ '全选\n在实现全选效果时,你可能会用到 indeterminate 属性。'
|
|
|
|
|
+ }>
|
|
|
|
|
+ <CheckboxGroupExample />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const plainOptions = ['Apple', 'Pear', 'Orange']
|
|
|
|
|
+const defaultCheckedList = ['Apple', 'Orange']
|
|
|
|
|
+
|
|
|
|
|
+const CheckboxGroupExample = () => {
|
|
|
|
|
+ const [checkedList, setCheckedList] = React.useState(
|
|
|
|
|
+ new Set(defaultCheckedList),
|
|
|
|
|
+ )
|
|
|
|
|
+ const [indeterminate, setIndeterminate] = React.useState(true)
|
|
|
|
|
+ const [checkAll, setCheckAll] = React.useState(false)
|
|
|
|
|
+
|
|
|
|
|
+ const onChange = (value: any, e: { target: { checked: boolean } }) => {
|
|
|
|
|
+ if (e.target.checked) {
|
|
|
|
|
+ checkedList.add(value)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ checkedList.delete(value)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setCheckedList(new Set(checkedList))
|
|
|
|
|
+ setIndeterminate(
|
|
|
|
|
+ !!checkedList.size && checkedList.size < plainOptions.length,
|
|
|
|
|
+ )
|
|
|
|
|
+ setCheckAll(checkedList.size === plainOptions.length)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const onCheckAllChange = (e: { target: { checked: boolean } }) => {
|
|
|
|
|
+ setCheckedList(e.target.checked ? new Set(plainOptions) : new Set())
|
|
|
|
|
+ setIndeterminate(false)
|
|
|
|
|
+ setCheckAll(e.target.checked)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <CheckboxItem
|
|
|
|
|
+ indeterminate={indeterminate}
|
|
|
|
|
+ onChange={onCheckAllChange}
|
|
|
|
|
+ checked={checkAll}>
|
|
|
|
|
+ Check all
|
|
|
|
|
+ </CheckboxItem>
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ {plainOptions.map((a) => (
|
|
|
|
|
+ <CheckboxItem
|
|
|
|
|
+ key={a}
|
|
|
|
|
+ onChange={onChange.bind(this, a)}
|
|
|
|
|
+ checked={checkedList.has(a)}>
|
|
|
|
|
+ {a}
|
|
|
|
|
+ </CheckboxItem>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Checkbox
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+type Event = { target: { checked: boolean } }
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| defaultChecked | whether is checked when init | Boolean | |
|
|
|
|
|
+| checked | whether is checked now (Controlled Mode) | Boolean | |
|
|
|
|
|
+| disabled | whether is been disabled | Boolean | false |
|
|
|
|
|
+| indeterminate | The indeterminate checked state of checkbox | Boolean | false |
|
|
|
|
|
+| onChange | callback when check status is changed | (e: `Event`) => void | |
|
|
|
|
|
+
|
|
|
|
|
+### Checkbox.CheckboxItem
|
|
|
|
|
+
|
|
|
|
|
+The encapsulation about `Checkbox` based on `List.Item`, the property `thumb` of `List.Item` will be passed to `Checkbox`, while other properties remain the same.
|
|
|
|
|
+
|
|
|
|
|
+Other APIs are identical with `Checkbox`.
|
|
|
|
|
+
|
|
|
|
|
+### Checkbox.AgreeItem
|
|
|
|
|
+
|
|
|
|
|
+Almost the same as CheckboxItem and be used for special scenes. See demo for details.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Collapse
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/collapse.md
|
|
|
|
|
+
|
|
|
|
|
+# Collapse
|
|
|
|
|
+
|
|
|
|
|
+A content area that can be collapsed/expanded.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- Group and hide complex areas to keep pages tidy.
|
|
|
|
|
+- An accordion is a special type of accordion panel that only allows a single content area to expand.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { ActivityIndicator, Collapse, Icon, List, Result } from '@ant-design/react-native'
|
|
|
|
|
+import React, { useEffect, useState } from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default function CollapseExmple() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List renderHeader="手风琴模式">
|
|
|
|
|
+ <Collapse accordion>
|
|
|
|
|
+ <Collapse.Panel key="1" title="第一项">
|
|
|
|
|
+ 手风琴模式只能同时展开一个
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ <Collapse.Panel key="2" title="第二项">
|
|
|
|
|
+ 手风琴模式只能同时展开一个
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ <Collapse.Panel key="3" title="第三项">
|
|
|
|
|
+ 手风琴模式只能同时展开一个
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ </Collapse>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="自定义折叠图标">
|
|
|
|
|
+ <Collapse
|
|
|
|
|
+ defaultActiveKey={['1']}
|
|
|
|
|
+ arrow={(active) =>
|
|
|
|
|
+ active ? <Icon name="minus" /> : <Icon name="plus" />
|
|
|
|
|
+ }>
|
|
|
|
|
+ <Collapse.Panel key="1" title="第一项">
|
|
|
|
|
+ 你可以通过 Collapse 的 arrow 属性来控制全部面板的箭头
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ <Collapse.Panel
|
|
|
|
|
+ key="2"
|
|
|
|
|
+ title="第二项"
|
|
|
|
|
+ arrow={<Icon name="down-circle" />}>
|
|
|
|
|
+ 也可以通过 Collapse.Panel 的 arrow 属性来自定义单个面板的箭头
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ <Collapse.Panel
|
|
|
|
|
+ key="3"
|
|
|
|
|
+ title="第三项"
|
|
|
|
|
+ arrow={(active) =>
|
|
|
|
|
+ active ? (
|
|
|
|
|
+ <Icon name="check-circle" />
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <Icon name="close-circle" />
|
|
|
|
|
+ )
|
|
|
|
|
+ }>
|
|
|
|
|
+ 如果你给 arrow 属性传入的是是一个渲染函数,那么
|
|
|
|
|
+ @ant-design/react-native 不会为你增加动画,arrow
|
|
|
|
|
+ 属性的效果就完全交由你自己来控制了
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ </Collapse>
|
|
|
|
|
+ </List>
|
|
|
|
|
+
|
|
|
|
|
+ <List renderHeader="动态内容">
|
|
|
|
|
+ <Collapse accordion>
|
|
|
|
|
+ <Collapse.Panel key="1" title="第一项" destroyOnClose>
|
|
|
|
|
+ <DynamicContent message="不可见时销毁 destroyOnClose={true}" />
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ <Collapse.Panel key="2" title="第二项" forceRender>
|
|
|
|
|
+ <DynamicContent message="预加载 forceRender={true}" />
|
|
|
|
|
+ </Collapse.Panel>
|
|
|
|
|
+ </Collapse>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function DynamicContent(props: { message: string }) {
|
|
|
|
|
+ const [finished, setFinished] = useState(false)
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const loadData = async () => {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ setFinished(true)
|
|
|
|
|
+ }, 1000)
|
|
|
|
|
+ }
|
|
|
|
|
+ loadData()
|
|
|
|
|
+ }, [])
|
|
|
|
|
+
|
|
|
|
|
+ return finished ? (
|
|
|
|
|
+ <Result title="处理成功" message={props.message} />
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <ActivityIndicator />
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Collapse
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default |
|
|
|
|
|
+-----------|------------|------|---------|
|
|
|
|
|
+| accordion | Whether to enable accordion mode | `Boolean` | `false` |
|
|
|
|
|
+| activeKey | The `key` of the currently expanded panel | accordion mode: `string | null` <br/> non-accordion mode: `string[]` | - |
|
|
|
|
|
+| arrowIcon | Custom arrow icon. <br/>if you pass a ReactNode, will add a rotate animation for you. | `ReactNode | ((active: boolean) => React.ReactNode)` | - |
|
|
|
|
|
+| defaultActiveKey | The `key` of the expanded panel by default | accordion mode: `string | null` <br/> non-accordion mode: `string[]` | - |
|
|
|
|
|
+| onChange | Triggered when the panel is switched | accordion mode: `(activeKey: string | null) => void` <br/> non-accordion mode: `(activeKey: string[]) => void` | - |
|
|
|
|
|
+| styles | Semantic DOM style | Same as [ListStyle](/components/list#liststyle-interface) & [ListItemStyle](/components/list#listitemstyle-interface) | - |
|
|
|
|
|
+
|
|
|
|
|
+### Collapse.Panel
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default |
|
|
|
|
|
+-----------|------------|------|---------|
|
|
|
|
|
+| arrowIcon | Custom arrow icon | `ReactNode | ((active: boolean) => React.ReactNode)` | - |
|
|
|
|
|
+| destroyOnClose | Destroy `dom` when not visible | `Boolean` | `false` |
|
|
|
|
|
+| disabled | Whether disabled or not | `Boolean` | `false` |
|
|
|
|
|
+| forceRender | Whether to render the `DOM` structure when hidden | `Boolean` | `false` |
|
|
|
|
|
+| key | The unique identifier | `String` | - |
|
|
|
|
|
+| onPress | The click event of title bar | `(event: GestureResponderEvent) => void` | - |
|
|
|
|
|
+| styles | Semantic DOM style | Same as [ListStyle](/components/list#liststyle-interface) | - |
|
|
|
|
|
+| title | The content on the left side of the title bar | `ReactNode` | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## DatePicker
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/date-picker.md
|
|
|
|
|
+
|
|
|
|
|
+# DatePicker
|
|
|
|
|
+
|
|
|
|
|
+Used to select a date or time.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- At most accurate to seconds.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { DatePicker, List, Provider } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+
|
|
|
|
|
+export default class PopupExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ value: undefined,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange = (value: any) => {
|
|
|
|
|
+ this.setState({ value })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <DatePicker
|
|
|
|
|
+ value={this.state.value}
|
|
|
|
|
+ precision="day"
|
|
|
|
|
+ minDate={new Date(2015, 7, 6)}
|
|
|
|
|
+ maxDate={new Date(2026, 11, 3)}
|
|
|
|
|
+ onChange={this.onChange}
|
|
|
|
|
+ format="YYYY-MM-DD">
|
|
|
|
|
+ <List.Item arrow="horizontal">Select Date</List.Item>
|
|
|
|
|
+ </DatePicker>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+type Precision =
|
|
|
|
|
+ | 'week'
|
|
|
|
|
+ | 'week-day'
|
|
|
|
|
+ | 'year'
|
|
|
|
|
+ | 'month'
|
|
|
|
|
+ | 'day'
|
|
|
|
|
+ | 'hour'
|
|
|
|
|
+ | 'minute'
|
|
|
|
|
+ | 'second'
|
|
|
|
|
+
|
|
|
|
|
+type DatePickerFilter = Partial<
|
|
|
|
|
+ Record<
|
|
|
|
|
+ Precision,
|
|
|
|
|
+ (
|
|
|
|
|
+ val: number,
|
|
|
|
|
+ extend: {
|
|
|
|
|
+ date: Date
|
|
|
|
|
+ }
|
|
|
|
|
+ ) => boolean
|
|
|
|
|
+ >
|
|
|
|
|
+>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|--------|--------
|
|
|
|
|
+| precision | Precision | `Precision` | `day` |`5.1.0`|
|
|
|
|
|
+| value | the currently selected value | Date | - ||
|
|
|
|
|
+| defaultValue | the default selected value | Date | - ||
|
|
|
|
|
+| minDate | minimum date | Date | 2000-1-1 ||
|
|
|
|
|
+| maxDate | maximum date | Date | 2030-1-1 ||
|
|
|
|
|
+| onChange | change handler | `(value: Date) => void` | - ||
|
|
|
|
|
+| onValueChange | fire when picker col change | `(value: Date, index: number) => void` | - ||
|
|
|
|
|
+| renderLabel | The function to custom rendering the label shown on a column. `type` means any value in `precision`, `data` means the default number | `(type:Precision / 'now', data: number) => ReactNode` | - ||
|
|
|
|
|
+| locale | international, can override the configuration of the global [Provider](/components/provider)'s `locale` | Object: Object: {okText, dismissText, extra, `DatePickerLocale:{ year,month,day,hour,minute,am,pm }`} | - |
|
|
|
|
|
+| filter | Filter available time | `DatePickerFilter` | - | `5.1.0` |
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+In addition, the following properties of [Picker](/components/picker) are supported: `onPickerChange` `onVisibleChange` `style` `styles` `itemStyle` `itemHeight` `numberOfLines` `title` `okText` `dismissText` `okButtonProps` `dismissButtonProps` `visible` `children` `renderMaskTop` `renderMaskBottom`
|
|
|
|
|
+
|
|
|
|
|
+### Children
|
|
|
|
|
+Same as [Picker](/components/picker#children), except type `format` is different:
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| format | format the selected value |`(value: Date) => date string` | import [Day.js Format](https://day.js.org/docs/en/parse/string-format), precision:`YYYY-MM-DD`,`YYYY-MM-DD HH:mm:ss`|
|
|
|
|
|
+
|
|
|
|
|
+### Ref
|
|
|
|
|
+Same as [Picker](/components/picker#ref)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## DatePickerView
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/date-picker-view.md
|
|
|
|
|
+
|
|
|
|
|
+# DatePickerView
|
|
|
|
|
+
|
|
|
|
|
+DatePickerView's functions like DatePicker, but it is rendered directly in the area instead of the pop-up window.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { DatePickerView, DatePickerFilter } from '@ant-design/react-native'
|
|
|
|
|
+import React, { useState } from 'react'
|
|
|
|
|
+import { ScrollView, Text } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const now = new Date()
|
|
|
|
|
+
|
|
|
|
|
+export default () => {
|
|
|
|
|
+ const [value, setValue] = useState<Date>(now)
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView nestedScrollEnabled>
|
|
|
|
|
+ <Text style={{ margin: 16 }}>基础用法</Text>
|
|
|
|
|
+ <DatePickerView />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 16 }}>受控模式</Text>
|
|
|
|
|
+ <DatePickerView
|
|
|
|
|
+ value={value}
|
|
|
|
|
+ onChange={(val) => {
|
|
|
|
|
+ setValue(val)
|
|
|
|
|
+ console.log('onChange', val)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 16 }}>自定义每列的渲染内容</Text>
|
|
|
|
|
+ <DatePickerView defaultValue={now} renderLabel={labelRenderer} />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 16 }}>周选择器</Text>
|
|
|
|
|
+ <DatePickerView
|
|
|
|
|
+ onChange={(val) => console.log('onChange', val)}
|
|
|
|
|
+ precision="week-day"
|
|
|
|
|
+ defaultValue={now}
|
|
|
|
|
+ renderLabel={weekdayLabelRenderer}
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 16 }}>过滤可供选择的时间</Text>
|
|
|
|
|
+ <DatePickerView
|
|
|
|
|
+ defaultValue={now}
|
|
|
|
|
+ precision="hour"
|
|
|
|
|
+ renderLabel={labelRenderer}
|
|
|
|
|
+ filter={dateFilter}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const labelRenderer = (type: string, data: number) => {
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case 'year':
|
|
|
|
|
+ return data + '年'
|
|
|
|
|
+ case 'month':
|
|
|
|
|
+ return data + '月'
|
|
|
|
|
+ case 'day':
|
|
|
|
|
+ return data + '日'
|
|
|
|
|
+ case 'hour':
|
|
|
|
|
+ return data + '时'
|
|
|
|
|
+ case 'minute':
|
|
|
|
|
+ return data + '分'
|
|
|
|
|
+ case 'second':
|
|
|
|
|
+ return data + '秒'
|
|
|
|
|
+ default:
|
|
|
|
|
+ return data
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const weekdayLabelRenderer = (type: string, data: number) => {
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case 'year':
|
|
|
|
|
+ return data + '年'
|
|
|
|
|
+ case 'week':
|
|
|
|
|
+ return data + '周'
|
|
|
|
|
+ case 'week-day':
|
|
|
|
|
+ return weekdayToZh(data)
|
|
|
|
|
+ default:
|
|
|
|
|
+ return data
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const dateFilter: DatePickerFilter = {
|
|
|
|
|
+ day: (_val, { date }) => {
|
|
|
|
|
+ // 去除所有周末
|
|
|
|
|
+ if (date.getDay() > 5 || date.getDay() === 0) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ return true
|
|
|
|
|
+ },
|
|
|
|
|
+ hour: (val: number) => {
|
|
|
|
|
+ // 只保留每天的14点到18点
|
|
|
|
|
+ if (val < 14 || val > 18) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ return true
|
|
|
|
|
+ },
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const weekdayToZh = (weekday: number) => {
|
|
|
|
|
+ switch (weekday) {
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ return '周一'
|
|
|
|
|
+ case 2:
|
|
|
|
|
+ return '周二'
|
|
|
|
|
+ case 3:
|
|
|
|
|
+ return '周三'
|
|
|
|
|
+ case 4:
|
|
|
|
|
+ return '周四'
|
|
|
|
|
+ case 5:
|
|
|
|
|
+ return '周五'
|
|
|
|
|
+ case 6:
|
|
|
|
|
+ return '周六'
|
|
|
|
|
+ case 7:
|
|
|
|
|
+ return '周日'
|
|
|
|
|
+ default:
|
|
|
|
|
+ return weekday
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+type Precision =
|
|
|
|
|
+ | 'week'
|
|
|
|
|
+ | 'week-day'
|
|
|
|
|
+ | 'year'
|
|
|
|
|
+ | 'month'
|
|
|
|
|
+ | 'day'
|
|
|
|
|
+ | 'hour'
|
|
|
|
|
+ | 'minute'
|
|
|
|
|
+ | 'second'
|
|
|
|
|
+
|
|
|
|
|
+type DatePickerFilter = Partial<
|
|
|
|
|
+ Record<
|
|
|
|
|
+ Precision,
|
|
|
|
|
+ (
|
|
|
|
|
+ val: number,
|
|
|
|
|
+ extend: {
|
|
|
|
|
+ date: Date
|
|
|
|
|
+ }
|
|
|
|
|
+ ) => boolean
|
|
|
|
|
+ >
|
|
|
|
|
+>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|---------|---------
|
|
|
|
|
+| precision | Precision | `Precision` | `day` |`5.1.0`|
|
|
|
|
|
+| value | the currently selected value | Date | - |
|
|
|
|
|
+| defaultValue | the default selected value | Date | - ||
|
|
|
|
|
+| minDate | minimum date | Date | 2000-1-1 |
|
|
|
|
|
+| maxDate | maximum date | Date | 2030-1-1 |
|
|
|
|
|
+| onChange | change handler | `(value: Date) => void` | - ||
|
|
|
|
|
+| onValueChange | fire when picker col change | `(value: Date, index: number) => void` | - ||
|
|
|
|
|
+| renderLabel | The function to custom rendering the label shown on a column. `type` means any value in `precision`, `data` means the default number | `(type:Precision / 'now', data: number) => ReactNode` | - ||
|
|
|
|
|
+| filter | Filter available time | `DatePickerFilter` | - | `5.1.0` |
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+In addition, the following properties of [PickerView](/components/picker-view) are supported: `style` `styles` `itemStyle` `itemHeight` `numberOfLines` `renderMaskTop` `renderMaskBottom`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## DatePickerView
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/image-picker.md
|
|
|
|
|
+
|
|
|
|
|
+# DatePickerView
|
|
|
|
|
+
|
|
|
|
|
+Deprecated since `5.1.0`.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Drawer
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/drawer.md
|
|
|
|
|
+
|
|
|
|
|
+# Drawer
|
|
|
|
|
+
|
|
|
|
|
+Drawer is a panel that displays the app's navigation options on the left edge of the screen.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Recommended way to show navigation options on Android, it is a common pattern found in Android APPs.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Drawer, List, WhiteSpace } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const styles = StyleSheet.create({
|
|
|
|
|
+ container: {
|
|
|
|
|
+ flex: 1,
|
|
|
|
|
+ },
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+export default class DrawerExample extends React.Component<any, any> {
|
|
|
|
|
+ drawer: any
|
|
|
|
|
+
|
|
|
|
|
+ onOpenChange = (isOpen: any) => {
|
|
|
|
|
+ /* tslint:disable: no-console */
|
|
|
|
|
+ console.log('是否打开了 Drawer', isOpen.toString())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const itemArr = Array.apply(null, Array(20))
|
|
|
|
|
+ .map(function (_: any, i: any) {
|
|
|
|
|
+ return i
|
|
|
|
|
+ })
|
|
|
|
|
+ .map((_i: any, index: any) => {
|
|
|
|
|
+ if (index === 0) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ thumb="https://zos.alipayobjects.com/rmsportal/eOZidTabPoEbPeU.png"
|
|
|
|
|
+ multipleLine>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ justifyContent: 'space-between',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Text>Categories - {index}</Text>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ onPress={() => this.drawer.closeDrawer()}>
|
|
|
|
|
+ close drawer
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ return (
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ thumb="https://zos.alipayobjects.com/rmsportal/eOZidTabPoEbPeU.png">
|
|
|
|
|
+ <Text>Categories - {index}</Text>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ )
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // Todo: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
|
|
|
+ const sidebar = (
|
|
|
|
|
+ <ScrollView style={[styles.container as any]}>
|
|
|
|
|
+ <List>{itemArr}</List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Drawer
|
|
|
|
|
+ sidebar={sidebar}
|
|
|
|
|
+ position="left"
|
|
|
|
|
+ open={false}
|
|
|
|
|
+ drawerRef={(el: any) => (this.drawer = el)}
|
|
|
|
|
+ onOpenChange={this.onOpenChange}
|
|
|
|
|
+ drawerBackgroundColor="#ccc">
|
|
|
|
|
+ <View style={{ flex: 1, marginTop: 114, padding: 8 }}>
|
|
|
|
|
+ <Button onPress={() => this.drawer && this.drawer.openDrawer()}>
|
|
|
|
|
+ Open drawer
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Drawer>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| sidebar | The sidebar content. | ReactNode | - |
|
|
|
|
|
+| onOpenChange | Callback called when open state of `Drawer` changes. | (open: bool): void | - |
|
|
|
|
|
+| open | If the sidebar should be open. | Boolean | false |
|
|
|
|
|
+| position | Position of `Drawer`. | String | 'left', enum{'left', 'right'} |
|
|
|
|
|
+| drawerWidth | Width of `Drawer` | Number | 300 |
|
|
|
|
|
+| drawerBackgroundColor | Background color of `Drawer` | String | - |
|
|
|
|
|
+| openDrawer | Opens the `Drawer`. | (): void | - |
|
|
|
|
|
+| closeDrawer | Closes the `Drawer`. | (): void | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Flex
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/flex.md
|
|
|
|
|
+
|
|
|
|
|
+# Flex
|
|
|
|
|
+
|
|
|
|
|
+Flex is a wrap of Flexible Box.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Flex, WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, Text, TouchableWithoutFeedback, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const Circle = (props: any) => {
|
|
|
|
|
+ const size = props.size || 20
|
|
|
|
|
+ const style = {
|
|
|
|
|
+ borderRadius: size / 2,
|
|
|
|
|
+ backgroundColor: '#527fe4',
|
|
|
|
|
+ width: size,
|
|
|
|
|
+ height: size,
|
|
|
|
|
+ margin: 1,
|
|
|
|
|
+ }
|
|
|
|
|
+ return <View style={style} />
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default class FlexExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ style={{ flex: 1 }}
|
|
|
|
|
+ automaticallyAdjustContentInsets={false}
|
|
|
|
|
+ showsHorizontalScrollIndicator={false}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 20, marginBottom: 5 }}>
|
|
|
|
|
+ <Text style={{ marginBottom: 10 }}>项目的排列方向</Text>
|
|
|
|
|
+ <Text>direction="row":主轴为水平方向,起点在左端</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Flex.Item style={{ paddingLeft: 4, paddingRight: 4 }}>
|
|
|
|
|
+ <Button size="small">按钮1</Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item style={{ paddingLeft: 4, paddingRight: 4 }}>
|
|
|
|
|
+ <Button size="small">按钮2</Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item style={{ paddingLeft: 4, paddingRight: 4 }}>
|
|
|
|
|
+ <Button size="small">按钮3</Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>direction="column":主轴为垂直方向,起点在上沿</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex direction="column">
|
|
|
|
|
+ <Flex.Item style={{ paddingBottom: 4 }}>
|
|
|
|
|
+ <Button size="small">按钮1</Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item style={{ paddingBottom: 4 }}>
|
|
|
|
|
+ <Button size="small">按钮2</Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ <Flex.Item style={{ paddingBottom: 4 }}>
|
|
|
|
|
+ <Button size="small">按钮3</Button>
|
|
|
|
|
+ </Flex.Item>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text style={{ marginTop: 20, marginBottom: 20 }}>
|
|
|
|
|
+ 项目在主轴上的对齐方式
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text>justify="start":左对齐</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex justify="start">
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>justify="center":居中</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex justify="center">
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>justify="end":右对齐</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex justify="end">
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>justify="between":两端对齐,项目之间的间隔都相等</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex justify="between">
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>justify="around":每个项目两侧的间隔相等</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex justify="around">
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ <Circle />
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text style={{ marginTop: 20, marginBottom: 20 }}>
|
|
|
|
|
+ 项目在交叉轴上的对齐方式
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text>align="start":交叉轴的起点对齐</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex align="start" style={{ height: 30 }}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 18,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 16,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>align="center":交叉轴的中点对齐</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex align="center" style={{ height: 30 }}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 18,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 16,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>align="end":交叉轴的终点对齐</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex align="end" style={{ height: 30 }}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 18,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 16,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>
|
|
|
|
|
+ align="stretch":如果项目未设置高度或设为auto,将占满整个容器的高度
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Flex align="stretch" style={{ height: 70 }}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 20,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 18,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 16,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ borderStyle: 'solid',
|
|
|
|
|
+ borderColor: '#527fe4',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 兜兜
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text style={{ marginBottom: 10 }}>是否折行</Text>
|
|
|
|
|
+ <Text>wrap="wrap":换行</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <TouchableWithoutFeedback onPress={() => ({})}>
|
|
|
|
|
+ <Flex wrap="wrap">
|
|
|
|
|
+ {'ooooooooooooooooooooooooooooo'.split('').map((char, i) => (
|
|
|
|
|
+ <Circle key={`${i}-${char}`} />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </TouchableWithoutFeedback>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginTop: 5, marginBottom: 5 }}>
|
|
|
|
|
+ <Text>wrap="nowrap":不换行</Text>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WingBlank style={{ marginBottom: 5 }}>
|
|
|
|
|
+ <Flex wrap="nowrap" onPress={() => ({})}>
|
|
|
|
|
+ {'ooooooooooooooooooooooooooooo'.split('').map((char, i) => (
|
|
|
|
|
+ <Circle key={`${i}-${char}`} />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Flex
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| direction | how flex items are placed in the flex container,value could be `row`,`row-reverse`,`column`,`column-reverse`, RN only support `row`,`column` | String | `row` |
|
|
|
|
|
+| wrap | the wrap way of sub-elements,option `nowrap`,`wrap`,`wrap-reverse`,RN only support `nowrap`,`wrap` | String | `nowrap` |
|
|
|
|
|
+| justify | the way of alignment for sub-elements of main axis, option `start`,`end`,`center`,`between`,`around` | String | `start` |
|
|
|
|
|
+| align | the way of alignment for sub-elements of cross-axis, option `start`,`center`,`end`,`baseline`,`stretch` RN only support `start`,`end`,`center`,`stretch` | String | `center` |
|
|
|
|
|
+
|
|
|
|
|
+### Flex.Item
|
|
|
|
|
+
|
|
|
|
|
+Flex.Item component has style `flex:1` as default, ensure all items average division width, Flex container‘s children maybe not Flex.Item.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Form
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/form.md
|
|
|
|
|
+
|
|
|
|
|
+# Form
|
|
|
|
|
+
|
|
|
|
|
+High-performance form component with data domain management. Includes data entry, validation, and corresponding styles. Base on [rc-field-form](https://www.npmjs.com/package/rc-field-form).
|
|
|
|
|
+
|
|
|
|
|
+Example from https://ant.design/components/form-cn
|
|
|
|
|
+
|
|
|
|
|
+## When to use
|
|
|
|
|
+
|
|
|
|
|
+- When you need to create an instance or collect information.
|
|
|
|
|
+- When you need to validate fields in certain rules.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ Button,
|
|
|
|
|
+ Form,
|
|
|
|
|
+ Input,
|
|
|
|
|
+ Picker,
|
|
|
|
|
+ Provider,
|
|
|
|
|
+ Radio,
|
|
|
|
|
+ Flex as Row,
|
|
|
|
|
+ Switch,
|
|
|
|
|
+} from '@ant-design/react-native'
|
|
|
|
|
+import type { FormProps } from '@ant-design/react-native/lib/form'
|
|
|
|
|
+import { district } from 'antd-mobile-demo-data'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+const Col = Row.Item
|
|
|
|
|
+
|
|
|
|
|
+type FieldType = {
|
|
|
|
|
+ username?: string
|
|
|
|
|
+ password?: string
|
|
|
|
|
+ remember?: string
|
|
|
|
|
+ isDefault?: boolean
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const FormExample: React.FC = () => {
|
|
|
|
|
+ const [form] = Form.useForm()
|
|
|
|
|
+
|
|
|
|
|
+ const onSubmit = () => {
|
|
|
|
|
+ form.submit()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
|
|
|
|
|
+ console.log('Success:', values)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (
|
|
|
|
|
+ errorInfo,
|
|
|
|
|
+ ) => {
|
|
|
|
|
+ console.log('Failed:', errorInfo)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const pickerRef = React.useRef<any>(null)
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <KeyboardAvoidingView
|
|
|
|
|
+ behavior="padding"
|
|
|
|
|
+ keyboardVerticalOffset={Platform.OS === 'ios' ? 100 : undefined}>
|
|
|
|
|
+ <ScrollView keyboardShouldPersistTaps="handled">
|
|
|
|
|
+ <Form
|
|
|
|
|
+ name="basic"
|
|
|
|
|
+ form={form}
|
|
|
|
|
+ onFinish={onFinish}
|
|
|
|
|
+ onFinishFailed={onFinishFailed}
|
|
|
|
|
+ initialValues={{
|
|
|
|
|
+ doorNumber: '',
|
|
|
|
|
+ username: '',
|
|
|
|
|
+ phoneNumber: '',
|
|
|
|
|
+ isDefault: false,
|
|
|
|
|
+ }}
|
|
|
|
|
+ renderHeader="水平布局菜单">
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ label="地址"
|
|
|
|
|
+ name="address"
|
|
|
|
|
+ rules={[{ required: true, message: '地址不能为空' }]}
|
|
|
|
|
+ arrow="horizontal"
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ pickerRef.current.toggle()
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Picker data={district} cols={3} ref={pickerRef}>
|
|
|
|
|
+ {({ extra, value, toggle }) => (
|
|
|
|
|
+ <Input
|
|
|
|
|
+ value={value?.length ? extra : undefined}
|
|
|
|
|
+ onFocus={toggle}
|
|
|
|
|
+ placeholder="省/市/区"
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ label="收货人"
|
|
|
|
|
+ name="username"
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Form.Item name="gender" noStyle>
|
|
|
|
|
+ <Radio.Group>
|
|
|
|
|
+ <Row>
|
|
|
|
|
+ <Radio value={1}>先生</Radio>
|
|
|
|
|
+ <Radio value={2}>女士</Radio>
|
|
|
|
|
+ </Row>
|
|
|
|
|
+ </Radio.Group>
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ }>
|
|
|
|
|
+ <Input placeholder="请输入收货人姓名" />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ label="手机号"
|
|
|
|
|
+ name="phoneNumber"
|
|
|
|
|
+ hasFeedback
|
|
|
|
|
+ validateDebounce={500}
|
|
|
|
|
+ rules={[{ pattern: /^1[3456789]\d{9}$/ }, { required: true }]}>
|
|
|
|
|
+ <Input type="number" placeholder="请输入手机号" />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ label="设为默认"
|
|
|
|
|
+ name="isDefault"
|
|
|
|
|
+ wrapperStyle={{ alignItems: 'flex-end' }}
|
|
|
|
|
+ valuePropName="checked">
|
|
|
|
|
+ <Switch />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+
|
|
|
|
|
+ <Form.Item>
|
|
|
|
|
+ <Row>
|
|
|
|
|
+ <Col style={{ marginRight: 10 }}>
|
|
|
|
|
+ <Button onPress={() => form.resetFields()}>重置</Button>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ <Col>
|
|
|
|
|
+ <Button type="primary" onPress={onSubmit}>
|
|
|
|
|
+ 保存
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Col>
|
|
|
|
|
+ </Row>
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+ <Form name="vertical" layout="vertical" renderHeader="垂直布局菜单">
|
|
|
|
|
+ <Form.Item label="问题描述">
|
|
|
|
|
+ <Input.TextArea
|
|
|
|
|
+ placeholder="请填写10个字以上的问题描述,以便我们提供更好的服务。"
|
|
|
|
|
+ maxLength={200}
|
|
|
|
|
+ showCount
|
|
|
|
|
+ rows={6}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ label="联系电话"
|
|
|
|
|
+ name="phone"
|
|
|
|
|
+ help="如您选择填写联系方式,该信息将同步至开发者">
|
|
|
|
|
+ <Input type="number" placeholder="选填,请填写您的手机号码" />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </KeyboardAvoidingView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default FormExample
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Form
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| disabled | Set form component disable, only available for `@ant-design/react-native` components | boolean | false |
|
|
|
|
|
+| component | Set the Form rendering element. Do not create a ReactNode for `false` | ComponentType \| false | `List` |
|
|
|
|
|
+| fields | Control of form fields through state management (such as redux). Not recommended for non-strong demand. View [example](https://ant.design/components/form#components-form-demo-global-state) | [FieldData](#fielddata)\[] | - |
|
|
|
|
|
+| form | Form control instance created by `Form.useForm()`. Automatically created when not provided | [FormInstance](#forminstance) | - |
|
|
|
|
|
+| feedbackIcons | Can be passed custom icons while `Form.Item` element has `hasFeedback` | [FeedbackIcons](#feedbackicons) | - |
|
|
|
|
|
+| initialValues | Set value by Form initialization or reset | object | - |
|
|
|
|
|
+| labelStyle | The label style | `ViewStyle \| TextStyle` | - |
|
|
|
|
|
+| layout | Form layout | `horizontal` \| `vertical` | `horizontal` |
|
|
|
|
|
+| name | Form name. Will be the prefix of Field `id` | string | - |
|
|
|
|
|
+| preserve | Keep field value even when field removed. You can get the preserve field value by `getFieldsValue(true)` | boolean | true |
|
|
|
|
|
+| requiredMark | Required mark style. Can use required mark or optional mark. You can not config to single Form.Item since this is a Form level config | boolean \| `optional` \| ((label: ReactNode, info: { required: boolean }) => ReactNode) | true |
|
|
|
|
|
+| validateMessages | Validation prompt template, description [see below](#validatemessages) | [ValidateMessages](https://github.com/ant-design/ant-design/blob/6234509d18bac1ac60fbb3f92a5b2c6a6361295a/components/locale/en_US.ts#L88-L134) | - |
|
|
|
|
|
+| validateTrigger | Config field validate trigger | string \| string\[] | `onChange` |
|
|
|
|
|
+| wrapperStyle | The layout for input controls, same as `labelStyle` | `ViewStyle` | - |
|
|
|
|
|
+| onFieldsChange | Trigger when field updated | function(changedFields, allFields) | - |
|
|
|
|
|
+| onFinish | Trigger after submitting the form and verifying data successfully | function(values) | - |
|
|
|
|
|
+| onFinishFailed | Trigger after submitting the form and verifying data failed | function({ values, errorFields, outOfDate }) | - |
|
|
|
|
|
+| onValuesChange | Trigger when value updated | function(changedValues, allValues) | - |
|
|
|
|
|
+| styles | Semantic DOM style | Same as [ListStyle](/components/list#liststyle-interface) | - |
|
|
|
|
|
+
|
|
|
|
|
+### validateMessages
|
|
|
|
|
+
|
|
|
|
|
+Form provides [default verification error messages](https://github.com/ant-design/ant-design/blob/6234509d18bac1ac60fbb3f92a5b2c6a6361295a/components/locale/en_US.ts#L88-L134). You can modify the template by configuring `validateMessages` property. A common usage is to configure localization:
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+const validateMessages = {
|
|
|
|
|
+ required: "'${name}' is required!",
|
|
|
|
|
+ // ...
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+<Form validateMessages={validateMessages} />;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Form.Item
|
|
|
|
|
+
|
|
|
|
|
+Form field component for data bidirectional binding, validation, layout, and so on.
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| dependencies | Set the dependency field. See [below](#dependencies) | [NamePath](#namepath)\[] | - |
|
|
|
|
|
+| getValueFromEvent | Specify how to get value from event or other onChange arguments | (..args: any\[]) => any | - |
|
|
|
|
|
+| getValueProps | Additional props with sub component (It's not recommended to generate dynamic function prop by `getValueProps`. Please pass it to child component directly) | (value: any) => Record<string, any> | - |
|
|
|
|
|
+| hasFeedback | Used with `validateStatus`, this option specifies the validation status icon. Recommended to be used only with `Input`. Also, It can get feedback icons via icons prop. | boolean \| { icons: [FeedbackIcons](#feedbackicons) } | false |
|
|
|
|
|
+| help | The prompt message. If not provided, the prompt message will be generated by the validation rule. | ReactNode | - |
|
|
|
|
|
+| hidden | Whether to hide Form.Item (still collect and validate value) | boolean | false |
|
|
|
|
|
+| initialValue | Config sub default value. Form `initialValues` get higher priority when conflict | string | - |
|
|
|
|
|
+| label | Label text | ReactNode | - |
|
|
|
|
|
+| labelStyle | The label style. You can set `labelCol` on Form which will not affect nest Item. If both exists, use Item first | `ViewStyle \| TextStyle` | - |
|
|
|
|
|
+| messageVariables | The default validate field info | Record<string, string> | - |
|
|
|
|
|
+| name | Field name, support array | [NamePath](#namepath) | - |
|
|
|
|
|
+| normalize | Normalize value from component value before passing to Form instance. Do not support async | (value, prevValue, prevValues) => any | - |
|
|
|
|
|
+| noStyle | No style for `true`, used as a pure field control. Will inherit parent Form.Item `validateStatus` if self `validateStatus` not configured | boolean | false |
|
|
|
|
|
+| preserve | Keep field value even when field removed | boolean | true |
|
|
|
|
|
+| required | Display required style. It will be generated by the validation rule | boolean | false |
|
|
|
|
|
+| rules | Rules for field validation. Click [here](https://ant.design/components/form#components-form-demo-basic) to see an example | [Rule](#rule)\[] | - |
|
|
|
|
|
+| shouldUpdate | Custom field update logic. See [below](#shouldupdate) | boolean \| (prevValue, curValue) => boolean | false |
|
|
|
|
|
+| styles | Semantic DOM style | [FormItemStyle](#formitemstyle-interface) & [ValidateStatusStyle](#validatestatusstyle-interface) | - |
|
|
|
|
|
+| trigger | When to collect the value of children node. Click [here](https://ant.design/components/form#components-form-demo-customized-form-controls) to see an example | string | `onChange` |
|
|
|
|
|
+| validateDebounce | Delay milliseconds to start validation | number | - |
|
|
|
|
|
+| validateFirst | Whether stop validate on first rule of error for this field. Will parallel validate when `parallel` configured | boolean \| `parallel` | false |
|
|
|
|
|
+| validateStatus | The validation status. If not provided, it will be generated by validation rule. options: `success` `warning` `error` `validating` | string | - |
|
|
|
|
|
+| validateTrigger | When to validate the value of children node | string \| string\[] | `onChange` |
|
|
|
|
|
+| valuePropName | Props of children node, for example, the prop of Switch or Checkbox is `checked`. This prop is an encapsulation of `getValueProps`, which will be invalid after customizing `getValueProps` | string | `value` |
|
|
|
|
|
+| wrapperStyle | The layout for input controls, same as `labelStyle`. You can set `wrapperStyle` on Form which will not affect nest Item. If both exists, use Item first | `ViewStyle` | - |
|
|
|
|
|
+
|
|
|
|
|
+The layout of Form.Item is based on List.Item. So it also supports these props of [List.Item](/components/list/#List.Item)
|
|
|
|
|
+
|
|
|
|
|
+`arrow` `extra` `thumb`
|
|
|
|
|
+
|
|
|
|
|
+After wrapped by `Form.Item` with `name` property, `value`(or other property defined by `valuePropName`) `onChange`(or other property defined by `trigger`) props will be added to form controls, the flow of form data will be handled by Form which will cause:
|
|
|
|
|
+
|
|
|
|
|
+1. You shouldn't use `onChange` on each form control to **collect data**(use `onValuesChange` of Form), but you can still listen to `onChange`.
|
|
|
|
|
+2. You cannot set value for each form control via `value` or `defaultValue` prop, you should set default value with `initialValues` of Form. Note that `initialValues` cannot be updated by `setState` dynamically, you should use `setFieldsValue` in that situation.
|
|
|
|
|
+3. You shouldn't call `setState` manually, please use `form.setFieldsValue` to change value programmatically.
|
|
|
|
|
+
|
|
|
|
|
+### dependencies
|
|
|
|
|
+
|
|
|
|
|
+Used when there are dependencies between fields. If a field has the `dependencies` prop, this field will automatically trigger updates and validations when upstream is updated. A common scenario is a user registration form with "password" and "confirm password" fields. The "Confirm Password" validation depends on the "Password" field. After setting `dependencies`, the "Password" field update will re-trigger the validation of "Check Password".
|
|
|
|
|
+
|
|
|
|
|
+`dependencies` shouldn't be used together with `shouldUpdate`, since it may result in conflicting update logic.
|
|
|
|
|
+
|
|
|
|
|
+### FeedbackIcons
|
|
|
|
|
+
|
|
|
|
|
+`({ status: ValidateStatus, errors: ReactNode, warnings: ReactNode }) => Record<ValidateStatus, ReactNode>`
|
|
|
|
|
+
|
|
|
|
|
+### shouldUpdate
|
|
|
|
|
+
|
|
|
|
|
+Form updates only the modified field-related components for performance optimization purposes by incremental update. In most cases, you only need to write code or do validation with the [`dependencies`](#dependencies) property. In some specific cases, such as when a new field option appears with a field value changed, or you just want to keep some area updating by form update, you can modify the update logic of Form.Item via the `shouldUpdate`.
|
|
|
|
|
+
|
|
|
|
|
+When `shouldUpdate` is `true`, any Form update will cause the Form.Item to be re-rendered. This is very helpful for custom rendering some areas. It should be noted that the child component should be returned in a function, otherwise `shouldUpdate` won't behave correctly:
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<Form.Item shouldUpdate>
|
|
|
|
|
+ {() => {
|
|
|
|
|
+ return <pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre>;
|
|
|
|
|
+ }}
|
|
|
|
|
+</Form.Item>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+When `shouldUpdate` is a function, it will be called by form values update. Providing original values and current value to compare. This is very helpful for rendering additional fields based on values:
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<Form.Item shouldUpdate={(prevValues, curValues) => prevValues.additional !== curValues.additional}>
|
|
|
|
|
+ {() => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Form.Item name="other">
|
|
|
|
|
+ <Input />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ );
|
|
|
|
|
+ }}
|
|
|
|
|
+</Form.Item>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### messageVariables
|
|
|
|
|
+
|
|
|
|
|
+You can modify the default verification information of Form.Item through `messageVariables`.
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<Form>
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ messageVariables={{ another: 'good' }}
|
|
|
|
|
+ label="user"
|
|
|
|
|
+ rules={[{ required: true, message: '${another} is required' }]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Input />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ <Form.Item
|
|
|
|
|
+ messageVariables={{ label: 'good' }}
|
|
|
|
|
+ label={<span>user</span>}
|
|
|
|
|
+ rules={[{ required: true, message: '${label} is required' }]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Input />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+</Form>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Form.List
|
|
|
|
|
+
|
|
|
|
|
+Provides array management for fields.
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| children | Render function | (fields: Field\[], operation: { add, remove, move }, meta: { errors }) => React.ReactNode | - |
|
|
|
|
|
+| initialValue | Config sub default value. Form `initialValues` get higher priority when conflict | any\[] | - |
|
|
|
|
|
+| name | Field name, support array. List is also a field, so it will return all the values by `getFieldsValue`. You can change this logic by [config](#getfieldsvalue) | [NamePath](#namepath) | - |
|
|
|
|
|
+| rules | Validate rules, only support customize validator. Should work with [ErrorList](#formerrorlist) | { validator, message }\[] | - |
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+<Form.List>
|
|
|
|
|
+ {(fields) => (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {fields.map((field) => (
|
|
|
|
|
+ <Form.Item {...field}>
|
|
|
|
|
+ <Input />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+</Form.List>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Note: You should not configure Form.Item `initialValue` under Form.List. It always should be configured by Form.List `initialValue` or Form `initialValues`.
|
|
|
|
|
+
|
|
|
|
|
+## operation
|
|
|
|
|
+
|
|
|
|
|
+Some operator functions in render form of Form.List.
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| add | add form item | (defaultValue?: any, insertIndex?: number) => void | insertIndex |
|
|
|
|
|
+| move | move form item | (from: number, to: number) => void | - |
|
|
|
|
|
+| remove | remove form item | (index: number \| number\[]) => void | number\[] |
|
|
|
|
|
+
|
|
|
|
|
+## Form.ErrorList
|
|
|
|
|
+
|
|
|
|
|
+Show error messages, should only work with `rules` of Form.List. See [example](https://ant.design/components/form#components-form-demo-dynamic-form-item).
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| -------- | ----------- | ------------ | ------- |
|
|
|
|
|
+| errors | Error list | ReactNode\[] | - |
|
|
|
|
|
+| styles | Semantic DOM style | [ValidateStatusStyle](#validatestatusstyle-interface) | - |
|
|
|
|
|
+
|
|
|
|
|
+## Form.Provider
|
|
|
|
|
+
|
|
|
|
|
+Provide linkage between forms. If a sub form with `name` prop update, it will auto trigger Provider related events. See [example](https://ant.design/components/form#components-form-demo-form-context).
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| onFormChange | Triggered when a sub form field updates | function(formName: string, info: { changedFields, forms }) | - |
|
|
|
|
|
+| onFormFinish | Triggered when a sub form submits | function(formName: string, info: { values, forms }) | - |
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<Form.Provider
|
|
|
|
|
+ onFormFinish={(name) => {
|
|
|
|
|
+ if (name === 'form1') {
|
|
|
|
|
+ // Do something...
|
|
|
|
|
+ }
|
|
|
|
|
+ }}
|
|
|
|
|
+>
|
|
|
|
|
+ <Form name="form1">...</Form>
|
|
|
|
|
+ <Form name="form2">...</Form>
|
|
|
|
|
+</Form.Provider>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### FormInstance
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type |
|
|
|
|
|
+| --- | --- | --- |
|
|
|
|
|
+| getFieldError | Get the error messages by the field name | (name: [NamePath](#namepath)) => string\[] |
|
|
|
|
|
+| getFieldInstance | Get field instance | (name: [NamePath](#namepath)) => any |
|
|
|
|
|
+| getFieldsError | Get the error messages by the fields name. Return as an array | (nameList?: [NamePath](#namepath)\[]) => FieldError\[] |
|
|
|
|
|
+| getFieldsValue | Get values by a set of field names. Return according to the corresponding structure. Default return mounted field value, but you can use `getFieldsValue(true)` to get all values | [GetFieldsValue](#getfieldsvalue) |
|
|
|
|
|
+| getFieldValue | Get the value by the field name | (name: [NamePath](#namepath)) => any |
|
|
|
|
|
+| isFieldsTouched | Check if fields have been operated. Check if all fields is touched when `allTouched` is `true` | (nameList?: [NamePath](#namepath)\[], allTouched?: boolean) => boolean |
|
|
|
|
|
+| isFieldTouched | Check if a field has been operated | (name: [NamePath](#namepath)) => boolean |
|
|
|
|
|
+| isFieldValidating | Check field if is in validating | (name: [NamePath](#namepath)) => boolean |
|
|
|
|
|
+| resetFields | Reset fields to `initialValues` | (fields?: [NamePath](#namepath)\[]) => void |
|
|
|
|
|
+| scrollToField | Scroll to field position | (name: [NamePath](#namepath), options: \[[ScrollOptions](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options)]) => void |
|
|
|
|
|
+| setFields | Set fields status | (fields: [FieldData](#fielddata)\[]) => void |
|
|
|
|
|
+| setFieldValue | Set fields value(Will directly pass to form store and **reset validation message**. If you do not want to modify passed object, please clone first) | (name: [NamePath](#namepath), value: any) => void |
|
|
|
|
|
+| setFieldsValue | Set fields value(Will directly pass to form store and **reset validation message**. If you do not want to modify passed object, please clone first). Use `setFieldValue` instead if you want to only config single value in Form.List | (values) => void |
|
|
|
|
|
+| submit | Submit the form. It's same as click `submit` button | () => void |
|
|
|
|
|
+| validateFields | Validate fields. Use `recursive` to validate all the field in the path | (nameList?: [NamePath](#namepath)\[], config?: [ValidateConfig](#validateFields)) => Promise |
|
|
|
|
|
+
|
|
|
|
|
+#### validateFields
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+export interface ValidateConfig {
|
|
|
|
|
+ // Only validate content and not show error message on UI.
|
|
|
|
|
+ validateOnly?: boolean;
|
|
|
|
|
+ // Recursively validate the provided `nameList` and its sub-paths.
|
|
|
|
|
+ recursive?: boolean;
|
|
|
|
|
+ // Validate dirty fields (touched + validated).
|
|
|
|
|
+ // It's useful to validate fields only when they are touched or validated.
|
|
|
|
|
+ dirty?: boolean;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+return sample:
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+validateFields()
|
|
|
|
|
+ .then((values) => {
|
|
|
|
|
+ /*
|
|
|
|
|
+ values:
|
|
|
|
|
+ {
|
|
|
|
|
+ username: 'username',
|
|
|
|
|
+ password: 'password',
|
|
|
|
|
+ }
|
|
|
|
|
+ */
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((errorInfo) => {
|
|
|
|
|
+ /*
|
|
|
|
|
+ errorInfo:
|
|
|
|
|
+ {
|
|
|
|
|
+ values: {
|
|
|
|
|
+ username: 'username',
|
|
|
|
|
+ password: 'password',
|
|
|
|
|
+ },
|
|
|
|
|
+ errorFields: [
|
|
|
|
|
+ { name: ['password'], errors: ['Please input your Password!'] },
|
|
|
|
|
+ ],
|
|
|
|
|
+ outOfDate: false,
|
|
|
|
|
+ }
|
|
|
|
|
+ */
|
|
|
|
|
+ });
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### FormItemStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface FormItemStyle extends ListItemStyle {
|
|
|
|
|
+ // label prop
|
|
|
|
|
+ formItemLabel: ViewStyle // { minWidth: 65 }
|
|
|
|
|
+ formItemLabelText: ViewStyle | TextStyle
|
|
|
|
|
+
|
|
|
|
|
+ // children style
|
|
|
|
|
+ formItemControl: ViewStyle
|
|
|
|
|
+
|
|
|
|
|
+ // required={true}
|
|
|
|
|
+ asterisk: TextStyle
|
|
|
|
|
+ // requiredMark="optional"
|
|
|
|
|
+ optional: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### ValidateStatusStyle interface
|
|
|
|
|
+when set `validateStatus` prop
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface ValidateStatusStyle {
|
|
|
|
|
+ error: TextStyle
|
|
|
|
|
+ warning: TextStyle
|
|
|
|
|
+ success: TextStyle
|
|
|
|
|
+ validating: TextStyle
|
|
|
|
|
+ feedbackIcon: ViewStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Hooks
|
|
|
|
|
+
|
|
|
|
|
+### Form.useForm
|
|
|
|
|
+
|
|
|
|
|
+`type Form.useForm = (): [FormInstance]`
|
|
|
|
|
+
|
|
|
|
|
+Create Form instance to maintain data store.
|
|
|
|
|
+
|
|
|
|
|
+### Form.useFormInstance
|
|
|
|
|
+
|
|
|
|
|
+`type Form.useFormInstance = (): FormInstance`
|
|
|
|
|
+
|
|
|
|
|
+Get current context form instance to avoid pass as props between components:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+const Sub = () => {
|
|
|
|
|
+ const form = Form.useFormInstance();
|
|
|
|
|
+
|
|
|
|
|
+ return <Button onClick={() => form.setFieldsValue({})} />;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export default () => {
|
|
|
|
|
+ const [form] = Form.useForm();
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Form form={form}>
|
|
|
|
|
+ <Sub />
|
|
|
|
|
+ </Form>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Form.useWatch
|
|
|
|
|
+
|
|
|
|
|
+`type Form.useWatch = (namePath: NamePath | (selector: (values: Store) => any), formInstance?: FormInstance | WatchOptions): Value`
|
|
|
|
|
+
|
|
|
|
|
+Watch the value of a field. You can use this to interact with other hooks like `useSWR` to reduce development costs:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+const Demo = () => {
|
|
|
|
|
+ const [form] = Form.useForm();
|
|
|
|
|
+ const userName = Form.useWatch('username', form);
|
|
|
|
|
+
|
|
|
|
|
+ const { data: options } = useSWR(`/api/user/${userName}`, fetcher);
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Form form={form}>
|
|
|
|
|
+ <Form.Item name="username">
|
|
|
|
|
+ <AutoComplete options={options} />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+If your component is wrapped by `Form.Item`, you can omit the second argument, `Form.useWatch` will find the nearest `FormInstance` automatically.
|
|
|
|
|
+
|
|
|
|
|
+By default `useWatch` only watches the registered field. If you want to watch the unregistered field, please use `preserve`:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+const Demo = () => {
|
|
|
|
|
+ const [form] = Form.useForm();
|
|
|
|
|
+
|
|
|
|
|
+ const age = Form.useWatch('age', { form, preserve: true });
|
|
|
|
|
+ console.log(age);
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Button onClick={() => form.setFieldValue('age', 2)}>Update</Button>
|
|
|
|
|
+ <Form form={form}>
|
|
|
|
|
+ <Form.Item name="name">
|
|
|
|
|
+ <Input />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Form.Item.useStatus
|
|
|
|
|
+
|
|
|
|
|
+`type Form.Item.useStatus = (): { status: ValidateStatus | undefined, errors: ReactNode[], warnings: ReactNode[] }`
|
|
|
|
|
+
|
|
|
|
|
+Could be used to get validate status of Form.Item. If this hook is not used under Form.Item, `status` would be `undefined`. `error` and `warnings` could be used to get error messages and warning messages of Form.Item:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+const CustomInput = ({ value, onChange }) => {
|
|
|
|
|
+ const { status, errors } = Form.Item.useStatus();
|
|
|
|
|
+ return (
|
|
|
|
|
+ <input
|
|
|
|
|
+ value={value}
|
|
|
|
|
+ onChange={onChange}
|
|
|
|
|
+ className={`custom-input-${status}`}
|
|
|
|
|
+ placeholder={(errors.length && errors[0]) || ''}
|
|
|
|
|
+ />
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+export default () => (
|
|
|
|
|
+ <Form>
|
|
|
|
|
+ <Form.Item name="username">
|
|
|
|
|
+ <CustomInput />
|
|
|
|
|
+ </Form.Item>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Difference between other data fetching method
|
|
|
|
|
+
|
|
|
|
|
+Form only update the Field which changed to avoid full refresh perf issue. Thus you can not get real time value with `getFieldsValue` in render. And `useWatch` will rerender current component to sync with latest value. You can also use Field renderProps to get better performance if only want to do conditional render. If component no need care field value change, you can use `onValuesChange` to give to parent component to avoid current one rerender.
|
|
|
|
|
+
|
|
|
|
|
+### Interface
|
|
|
|
|
+
|
|
|
|
|
+#### NamePath
|
|
|
|
|
+
|
|
|
|
|
+`string | number | (string | number)[]`
|
|
|
|
|
+
|
|
|
|
|
+#### GetFieldsValue
|
|
|
|
|
+
|
|
|
|
|
+`getFieldsValue` provides overloaded methods:
|
|
|
|
|
+
|
|
|
|
|
+##### getFieldsValue(nameList?: true | [NamePath](#namepath)\[], filterFunc?: FilterFunc)
|
|
|
|
|
+
|
|
|
|
|
+When `nameList` is empty, return all registered fields, including values of List (even if List has no Item children).
|
|
|
|
|
+
|
|
|
|
|
+When `nameList` is `true`, return all values in store, including unregistered fields. For example, if you set the value of an unregistered Item through `setFieldsValue`, you can also get all values through `true`.
|
|
|
|
|
+
|
|
|
|
|
+When `nameList` is an array, return the value of the specified path. Note that `nameList` is a nested array. For example, you need the value of a certain path as follows:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+// Single path
|
|
|
|
|
+form.getFieldsValue([['user', 'age']]);
|
|
|
|
|
+
|
|
|
|
|
+// multiple path
|
|
|
|
|
+form.getFieldsValue([
|
|
|
|
|
+ ['user', 'age'],
|
|
|
|
|
+ ['preset', 'account'],
|
|
|
|
|
+]);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+##### getFieldsValue({ strict?: boolean, filter?: FilterFunc })
|
|
|
|
|
+
|
|
|
|
|
+Accept configuration parameters. When `strict` is `true`, only the value of Item will be matched. For example, in `{ list: [{ bamboo: 1, little: 2 }] }`, if List is only bound to the `bamboo` field, then `getFieldsValue({ strict: true })` will only get `{ list: [{ bamboo: 1 }] }`.
|
|
|
|
|
+
|
|
|
|
|
+#### FilterFunc
|
|
|
|
|
+
|
|
|
|
|
+To filter certain field values, `meta` will provide information related to the fields. For example, it can be used to retrieve values that have only been modified by the user, and so on.
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+type FilterFunc = (meta: { touched: boolean; validating: boolean }) => boolean;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### FieldData
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type |
|
|
|
|
|
+| ---------- | ------------------------ | ------------------------ |
|
|
|
|
|
+| errors | Error messages | string\[] |
|
|
|
|
|
+| warnings | Warning messages | string\[] |
|
|
|
|
|
+| name | Field name path | [NamePath](#namepath)\[] |
|
|
|
|
|
+| touched | Whether is operated | boolean |
|
|
|
|
|
+| validating | Whether is in validating | boolean |
|
|
|
|
|
+| value | Field value | any |
|
|
|
|
|
+
|
|
|
|
|
+#### Rule
|
|
|
|
|
+
|
|
|
|
|
+Rule supports a config object, or a function returning config object:
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+type Rule = RuleConfig | ((form: FormInstance) => RuleConfig);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type |
|
|
|
|
|
+| --- | --- | --- |
|
|
|
|
|
+| defaultField | Validate rule for all array elements, valid when `type` is `array` | [rule](#rule) |
|
|
|
|
|
+| enum | Match enum value. You need to set `type` to `enum` to enable this | any\[] |
|
|
|
|
|
+| fields | Validate rule for child elements, valid when `type` is `array` or `object` | Record<string, [rule](#rule)> |
|
|
|
|
|
+| len | Length of string, number, array | number |
|
|
|
|
|
+| max | `type` required: max length of `string`, `number`, `array` | number |
|
|
|
|
|
+| message | Error message. Will auto generate by [template](#validatemessages) if not provided | string |
|
|
|
|
|
+| min | `type` required: min length of `string`, `number`, `array` | number |
|
|
|
|
|
+| pattern | Regex pattern | RegExp |
|
|
|
|
|
+| required | Required field | boolean |
|
|
|
|
|
+| transform | Transform value to the rule before validation | (value) => any |
|
|
|
|
|
+| type | Normally `string` \|`number` \|`boolean` \|`url` \| `email`. More type to ref [here](https://github.com/yiminghe/async-validator#type) | string |
|
|
|
|
|
+| validateTrigger | Set validate trigger event. Must be the sub set of `validateTrigger` in Form.Item | string \| string\[] |
|
|
|
|
|
+| validator | Customize validation rule. Accept Promise as return. See [example](https://ant.design/components/form#components-form-demo-register) | ([rule](#rule), value) => Promise |
|
|
|
|
|
+| warningOnly | Warning only. Not block form submit | boolean |
|
|
|
|
|
+| whitespace | Failed if only has whitespace, only work with `type: 'string'` rule | boolean |
|
|
|
|
|
+
|
|
|
|
|
+#### WatchOptions
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| form | Form instance | FormInstance | Current form in context |
|
|
|
|
|
+| preserve | Whether to watch the field which has no matched `Form.Item` | boolean | false |
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### Why can't Switch、Checkbox、Radio bind data?
|
|
|
|
|
+
|
|
|
|
|
+Form.Item default bind value to `value` prop, but Switch or Checkbox value prop is `checked`. You can use `valuePropName` to change bind value prop.
|
|
|
|
|
+
|
|
|
|
|
+```tsx | pure
|
|
|
|
|
+<Form.Item name="fieldA" valuePropName="checked">
|
|
|
|
|
+ <Switch />
|
|
|
|
|
+</Form.Item>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### How does Form.Item work with Picker / DatePicker?
|
|
|
|
|
+
|
|
|
|
|
+When Picker's `children` is `List.Item`, it can be used directly.
|
|
|
|
|
+<br/>Note: Form.Item need `noStyle` prop
|
|
|
|
|
+```tsx
|
|
|
|
|
+<Form.Item name="address" noStyle>
|
|
|
|
|
+ <Picker data={data} cols={3}>
|
|
|
|
|
+ <List.Item>地址</List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+</Form.Item>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+However, we recommend the composition layout of `Form.Item` and `Input`, so how to use it when `children` is not `List.Item`?
|
|
|
|
|
+<br/>
|
|
|
|
|
+When `children` is a **function**, the `toggle` parameter will be provided to control the display/hide of Picker.
|
|
|
|
|
+```tsx
|
|
|
|
|
+<Form.Item label="地址" name="address">
|
|
|
|
|
+ <Picker data={data} cols={3} >
|
|
|
|
|
+ {({ extra, value, toggle }: any) => (
|
|
|
|
|
+ <Input
|
|
|
|
|
+ value={value?.length ? extra : undefined}
|
|
|
|
|
+ onFocus={toggle}
|
|
|
|
|
+ placeholder="省/市/区"
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+</Form.Item>
|
|
|
|
|
+```
|
|
|
|
|
+Secondly, you can use `ref`
|
|
|
|
|
+```tsx
|
|
|
|
|
+const pickerRef = useRef();
|
|
|
|
|
+
|
|
|
|
|
+<Form.Item label="地址" name="address" onPress={()=>pickerRef.current?.toggle()}>
|
|
|
|
|
+ <Picker data={data} cols={3} ref={pickerRef}>
|
|
|
|
|
+ <Input placeholder="省/市/区"/>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+</Form.Item>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### Is there any more reference documentation?
|
|
|
|
|
+
|
|
|
|
|
+https://ant.design/components/form-cn
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Grid
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/grid.md
|
|
|
|
|
+
|
|
|
|
|
+# Grid
|
|
|
|
|
+
|
|
|
|
|
+We divided the design area into a number of aliquots in horizontal and vertical.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- The contents of the blocks should have the same type. eg: they are all pictures or icons with text.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Grid } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const data = Array.from(new Array(9)).map((_val, i) => ({
|
|
|
|
|
+ icon: 'https://os.alipayobjects.com/rmsportal/IptWdCkrtkAUfjE.png',
|
|
|
|
|
+ text: `Name${i}`,
|
|
|
|
|
+}))
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicGridExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <View style={[{ margin: 10 }]}>
|
|
|
|
|
+ <Text>Simple</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={[{ padding: 10 }]}>
|
|
|
|
|
+ <Grid data={data} hasLine={false} />
|
|
|
|
|
+ </View>
|
|
|
|
|
+
|
|
|
|
|
+ <View style={[{ margin: 10 }]}>
|
|
|
|
|
+ <Text>Carousel</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Grid
|
|
|
|
|
+ data={data}
|
|
|
|
|
+ columnNum={3}
|
|
|
|
|
+ isCarousel
|
|
|
|
|
+ carouselProps={{
|
|
|
|
|
+ style: {
|
|
|
|
|
+ width: '100%',
|
|
|
|
|
+ height: 320,
|
|
|
|
|
+ },
|
|
|
|
|
+ }}
|
|
|
|
|
+ onPress={(_el: any, index: any) => alert(index)}
|
|
|
|
|
+ />
|
|
|
|
|
+ <View style={[{ margin: 10 }]}>
|
|
|
|
|
+ <Text>Custom GridCell Style</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Grid
|
|
|
|
|
+ data={data}
|
|
|
|
|
+ columnNum={3}
|
|
|
|
|
+ itemStyle={{ height: 150, backgroundColor: '#ffff00' }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Description | Type | Default |
|
|
|
|
|
+| -------------- | ------------------------------------------------------------- | --------------------------------- | ----------- |
|
|
|
|
|
+| data | data record array to be rendered | `Array<{icon, text}>` | [] |
|
|
|
|
|
+| onPress | Handler to be called when the user taps the grid | (el: Object, index: number): void | - |
|
|
|
|
|
+| columnNum | the number of columns | number | `4` |
|
|
|
|
|
+| hasLine | whether to show border | boolean | `true` |
|
|
|
|
|
+| isCarousel | whether to be played as a Carousel | boolean | `false` |
|
|
|
|
|
+| carouselProps | Carousel Props | CarouselProps | `{}` |
|
|
|
|
|
+| carouselMaxRow | the max number of rows to be showed each page of the Carousel | number | `2` |
|
|
|
|
|
+| renderItem | custom function to create each grid item | (el, index) => React.Node | - |
|
|
|
|
|
+| itemStyle | Custom GridCell Style | object | {} |
|
|
|
|
|
+When `isCarousel = true`, the APIs of [carousel](https://mobile.ant.design/components/carousel) also can be delivered.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Icon
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/icon.md
|
|
|
|
|
+
|
|
|
|
|
+# Icon
|
|
|
|
|
+
|
|
|
|
|
+## How to Use
|
|
|
|
|
+
|
|
|
|
|
+### 安装依赖
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+npm install @ant-design/icons-react-native@latest
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### Linking
|
|
|
|
|
+
|
|
|
|
|
+ - Add assets to your `react-native.config.js` ( If not exist, please create in project’s root directory )
|
|
|
|
|
+
|
|
|
|
|
+ ```js
|
|
|
|
|
+ module.exports = {
|
|
|
|
|
+ assets: ['node_modules/@ant-design/icons-react-native/fonts'],
|
|
|
|
|
+ };
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ - Run the [`react-native-asset`](https://github.com/unimonkiez/react-native-asset)'s command and linking + unlinking is automatic
|
|
|
|
|
+
|
|
|
|
|
+ ```bash
|
|
|
|
|
+ npx react-native-asset
|
|
|
|
|
+ ```
|
|
|
|
|
+ will copy fonts to `ios` and `android` assets folder.
|
|
|
|
|
+ - If you have an Expo managed project, skip the previous two steps and use [expo-font](https://docs.expo.dev/versions/latest/sdk/font/) to load the font directly:
|
|
|
|
|
+ ```jsx
|
|
|
|
|
+ import { useFonts } from 'expo-font';
|
|
|
|
|
+
|
|
|
|
|
+ const [fontsLoaded] = useFonts({
|
|
|
|
|
+ antoutline: require('@ant-design/icons-react-native/fonts/antoutline.ttf'),
|
|
|
|
|
+ })
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ outlineGlyphMap,
|
|
|
|
|
+ OutlineGlyphMapType,
|
|
|
|
|
+} from '@ant-design/icons-react-native/lib/outline'
|
|
|
|
|
+import { Grid, Icon, SearchBar, Toast } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+const data = Object.keys(outlineGlyphMap).map((item: OutlineGlyphMapType) => ({
|
|
|
|
|
+ icon: <Icon name={item} />,
|
|
|
|
|
+ text: item,
|
|
|
|
|
+}))
|
|
|
|
|
+export default class IConDemo extends React.Component<any, any> {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ data,
|
|
|
|
|
+ }
|
|
|
|
|
+ handlePress = (dataItem: { icon?: any; text?: string }) => {
|
|
|
|
|
+ Toast.show(`<Icon name="${dataItem.text}" />`)
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <SearchBar
|
|
|
|
|
+ placeholder="Search by icon name"
|
|
|
|
|
+ onChange={(text) => {
|
|
|
|
|
+ this.setState(() => ({
|
|
|
|
|
+ data: data.filter((d) => d.text.match(new RegExp(text, 'gi'))),
|
|
|
|
|
+ }))
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Grid
|
|
|
|
|
+ data={this.state.data}
|
|
|
|
|
+ columnNum={3}
|
|
|
|
|
+ hasLine={false}
|
|
|
|
|
+ onPress={this.handlePress}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const title = 'Icon'
|
|
|
|
|
+export const description = 'Icon Example'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Description | Type | Default |
|
|
|
|
|
+| ---------- | ------------------- | ---------------------------------- | ------- |
|
|
|
|
|
+| name | `OutlineGlyphMapType` | string |
|
|
|
|
|
+| size | icon size | 'xxs'/'xs'/'sm'/'md'/'lg' / number | `md` |
|
|
|
|
|
+| color | icon color | Color | '#000' |
|
|
|
|
|
+
|
|
|
|
|
+ - Tips1: Clicking the icon in the demo will automatically copy the code to the `<Icon />`.
|
|
|
|
|
+ - Tips2: By default, Icon uses the `outline` icon in `ant-design-icons`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Input
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/input.md
|
|
|
|
|
+
|
|
|
|
|
+# Input
|
|
|
|
|
+
|
|
|
|
|
+Entering content through the keyboard is the most basic form field wrapper.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- It is generally used in form pages to collect information, and provides two types of text boxes and text-area boxes.
|
|
|
|
|
+- The Input component is layout-independent. It can be used with the `List` component for quick layout; it also has built-in linkage interaction with the `Form` component.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Input, List } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default function InputExample() {
|
|
|
|
|
+ const [value, setValue] = React.useState('')
|
|
|
|
|
+ return (
|
|
|
|
|
+ <KeyboardAvoidingView
|
|
|
|
|
+ behavior="padding"
|
|
|
|
|
+ keyboardVerticalOffset={Platform.OS === 'ios' ? 100 : undefined}>
|
|
|
|
|
+ <ScrollView keyboardShouldPersistTaps="handled">
|
|
|
|
|
+ <List renderHeader="基本用法">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input placeholder="请输入内容" />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="受控模式">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ placeholder="请输入内容"
|
|
|
|
|
+ value={value}
|
|
|
|
|
+ onChangeText={setValue}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="带清除按钮">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input allowClear placeholder="allowClear" />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="前缀和后缀">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input prefix="前缀" suffix="后缀" placeholder="prefix / suffix" />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="带字数提示">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input showCount placeholder="showCount" />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ maxLength={5}
|
|
|
|
|
+ showCount={{
|
|
|
|
|
+ formatter: ({ count, maxLength }) => `${count}/${maxLength}`,
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="showCount.formatter"
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="TextArea">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input.TextArea
|
|
|
|
|
+ rows={4}
|
|
|
|
|
+ maxLength={100}
|
|
|
|
|
+ showCount
|
|
|
|
|
+ allowClear
|
|
|
|
|
+ placeholder="固定行数 row={4}"
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="根据内容自动调整高度">
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input.TextArea autoSize placeholder="autoSize={true}" />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Input.TextArea
|
|
|
|
|
+ autoSize={{ minRows: 2, maxRows: 6 }}
|
|
|
|
|
+ placeholder="autoSize={{ minRows: 2, maxRows: 6 }}"
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </KeyboardAvoidingView>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Input
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| allowClear | If allow to remove input content with clear icon | `boolean` \| `{ clearIcon: ReactNode }` | - |
|
|
|
|
|
+| defaultValue | The initial input content | string | - |
|
|
|
|
|
+| disabled | Whether the input is disabled | boolean | false |
|
|
|
|
|
+| maxLength | The maximum number of characters in Input | number | - |
|
|
|
|
|
+| prefix | The prefix icon for the Input | ReactNode | - |
|
|
|
|
|
+| showCount | Whether to show character count | `boolean` \| `{ formatter: (info: { value: string, count: number, maxLength?: number }) => ReactNode }` | false |
|
|
|
|
|
+| status | Set validation status | 'error' \| 'warning' | - |
|
|
|
|
|
+| inputStyle | TextInput style | `StyleProp<TextStyle>` | - |
|
|
|
|
|
+| style | Container style | `StyleProp<ViewStyle>` | - |
|
|
|
|
|
+| styles | Semantic DOM style | [InputStyle](#inputstyle-interface) | - |
|
|
|
|
|
+| suffix | The suffix icon for the Input | ReactNode | - |
|
|
|
|
|
+| type | Declare the Input type, the same as the native [keyboardType](http://facebook.github.io/react-native/docs/textinput.html#keyboardtype) attribute | 'text' \| 'number' \| 'password' \| KeyboardTypeOptions | `text` |
|
|
|
|
|
+| value | The input content value | string | - |
|
|
|
|
|
+| onChange | Callback when user input, extra return `e.target.value` | `(e: NativeSyntheticEvent<TextInputChangeEventData>) => void;` | - |
|
|
|
|
|
+
|
|
|
|
|
+The rest of the props of Input are exactly the same as the react-native [TextInput](http://facebook.github.io/react-native/docs/textinput.html).
|
|
|
|
|
+
|
|
|
|
|
+### Input.TextArea
|
|
|
|
|
+
|
|
|
|
|
+Same as Input, and more:
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| autoSize | Height auto size feature, can be set to `true` \| `false` or an object `{ minRows: 2, maxRows: 6 }` | boolean \| object | false |
|
|
|
|
|
+| rows | sets the number of lines for a textarea. Prioritize`autoSize` | number | 2 |
|
|
|
|
|
+| styles | Semantic DOM style | [InputStyle](#inputstyle-interface) | - |
|
|
|
|
|
+
|
|
|
|
|
+### InputStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface InputStyle {
|
|
|
|
|
+ container: ViewStyle // Same as `style` prop
|
|
|
|
|
+ input: ViewStyle // Same as `inputStyle` prop
|
|
|
|
|
+ clearIcon: ViewStyle
|
|
|
|
|
+ prefix: ViewStyle | TextStyle
|
|
|
|
|
+ showCount: TextStyle
|
|
|
|
|
+ suffix: ViewStyle | TextStyle
|
|
|
|
|
+ warning: TextStyle
|
|
|
|
|
+ error: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Ref
|
|
|
|
|
+Ref to [TextInput](http://facebook.github.io/react-native/docs/textinput.html)
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+## When setting `allowClear` on the Android platform, why does it not work when I click clearIcon?
|
|
|
|
|
+
|
|
|
|
|
+In Android, clearIcon will only appear when you are in editing state (`focus`).
|
|
|
|
|
+<br/>When this component is wrapped by `ScrollView`, set the `keyboardShouldPersistTaps` property to `handled` or `always`, the icon will respond correctly to the click event
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<ScrollView keyboardShouldPersistTaps="always">
|
|
|
|
|
+...
|
|
|
|
|
+</ScrollView>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Why Input in control can make `value` exceed `maxLength`?
|
|
|
|
|
+
|
|
|
|
|
+When in control, component should show as what it set to avoid submit value not align with store value in Form.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## InputItem
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/input-item.md
|
|
|
|
|
+
|
|
|
|
|
+# InputItem
|
|
|
|
|
+
|
|
|
|
|
+> This package has been deprecated in `5.2.1`, recommend [components/Input](/components/input)
|
|
|
|
|
+
|
|
|
|
|
+A foundational component for inputting text into the app via a keyboard.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- Support text input via keyboard or clipboard.
|
|
|
|
|
+- The cursor can be moved horizontally.
|
|
|
|
|
+- Handle text with a specific format, eg: hide password.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, InputItem, List } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, Text } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+declare var jest: any
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicInputItemExample extends React.Component<any, any> {
|
|
|
|
|
+ inputRef: any
|
|
|
|
|
+
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ value1: '',
|
|
|
|
|
+ value2: '',
|
|
|
|
|
+ value3: '',
|
|
|
|
|
+ value4: '',
|
|
|
|
|
+ labelnum1: '',
|
|
|
|
|
+ labelnum2: '',
|
|
|
|
|
+ labelnum3: '',
|
|
|
|
|
+ text: '',
|
|
|
|
|
+ bankCard: '',
|
|
|
|
|
+ phone: '',
|
|
|
|
|
+ password: '',
|
|
|
|
|
+ number: '',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ style={{ flex: 1 }}
|
|
|
|
|
+ automaticallyAdjustContentInsets={false}
|
|
|
|
|
+ showsHorizontalScrollIndicator={false}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}
|
|
|
|
|
+ keyboardShouldPersistTaps={'handled'}>
|
|
|
|
|
+ <List renderHeader={'基本'}>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ error
|
|
|
|
|
+ value={this.state.value}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ extra="元"
|
|
|
|
|
+ placeholder="有标签">
|
|
|
|
|
+ 输入框
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ value="不可编辑"
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ extra={<Text>元</Text>}
|
|
|
|
|
+ placeholder="不可编辑"
|
|
|
|
|
+ editable={false}>
|
|
|
|
|
+ 输入框
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ value="disabled"
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ extra={<Text>元</Text>}
|
|
|
|
|
+ placeholder="disabled"
|
|
|
|
|
+ disabled>
|
|
|
|
|
+ 输入框
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ value={this.state.value1}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value1: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="无标签"
|
|
|
|
|
+ />
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ defaultValue="xx"
|
|
|
|
|
+ clear
|
|
|
|
|
+ placeholder="自动获取光标"
|
|
|
|
|
+ autoFocus={
|
|
|
|
|
+ /* TODO: https://github.com/facebook/jest/issues/3707 */ typeof jest ===
|
|
|
|
|
+ 'undefined'
|
|
|
|
|
+ }>
|
|
|
|
|
+ 标题
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ placeholder="点击下方按钮该输入框会获取光标"
|
|
|
|
|
+ ref={(el: any) => (this.inputRef = el)}>
|
|
|
|
|
+ 标题
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ this.inputRef.focus()
|
|
|
|
|
+ }}
|
|
|
|
|
+ type="primary">
|
|
|
|
|
+ 点击获取光标
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'固定标签字数'}>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ value={this.state.labelnum1}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ labelnum1: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ labelNumber={2}
|
|
|
|
|
+ placeholder="两个字标签">
|
|
|
|
|
+ 姓名
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ value={this.state.labelnum2}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ labelnum2: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ labelNumber={3}
|
|
|
|
|
+ placeholder="三个字标签">
|
|
|
|
|
+ 校验码
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ value={this.state.labelnum3}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ labelnum3: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ labelNumber={4}
|
|
|
|
|
+ placeholder="四个字标签(默认)">
|
|
|
|
|
+ 四字标签
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'格式'}>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ error
|
|
|
|
|
+ value={this.state.text}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ text: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="text">
|
|
|
|
|
+ 文本输入
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ type="bankCard"
|
|
|
|
|
+ value={this.state.bankcard}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ bankcard: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="bankCard">
|
|
|
|
|
+ 银行卡
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ type="phone"
|
|
|
|
|
+ value={this.state.phone}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ phone: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="phone">
|
|
|
|
|
+ 手机号
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ type="password"
|
|
|
|
|
+ value={this.state.password}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ password: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="password">
|
|
|
|
|
+ 密码
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ <InputItem
|
|
|
|
|
+ clear
|
|
|
|
|
+ type="number"
|
|
|
|
|
+ value={this.state.number}
|
|
|
|
|
+ onChange={(value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ number: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}
|
|
|
|
|
+ placeholder="number">
|
|
|
|
|
+ 数字
|
|
|
|
|
+ </InputItem>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+**`InputItem` must wrapped by a [List](https://mobile.ant.design/components/list)**
|
|
|
|
|
+
|
|
|
|
|
+Properties | Description | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| type | can be `bankCard`; `phone`(which the maxLength is 11 and setting will be ignored); `password`; `number`(in order to evoke the 'numeric keyboard with decimal', this type is not a native number, but `<input type="text" pattern="[0-9]*"/>`); `digit`(represent the native type number); As well as other standard html input type values. | String | `text` |
|
|
|
|
|
+| value | the value of input (see [react doc](https://facebook.github.io/react/docs/forms.html) for more information about controled component) | String | |
|
|
|
|
|
+| defaultValue | provides an initial value that will change when the user starts typing. | String | - |
|
|
|
|
|
+| placeholder | the string that will be rendered before text input has been entered. | String | '' |
|
|
|
|
|
+| editable | whether is editable | bool | true |
|
|
|
|
|
+| disabled | whether is disabled | bool | true |
|
|
|
|
|
+| clear | whether to display clear(it takes effect only `editable` is `true` and `disabled` is `false` has been set) | bool | false |
|
|
|
|
|
+| maxLength | limits the maximum number of characters that can be entered | number | |
|
|
|
|
|
+| onChange | callback that is called when the text input's text changes | (val: string): void | - |
|
|
|
|
|
+| onBlur | callback that is called when the text input is blurred | (val: string): void | - |
|
|
|
|
|
+| onFocus | callback that is called when the text input is focused | (val: string): void | - |
|
|
|
|
|
+| error | whether to display error | bool | false |
|
|
|
|
|
+| onErrorClick | callback that is called when the error icon is clicked | (e: Object): void | |
|
|
|
|
|
+| extra | the right content of `InputItem` | string or node | '' |
|
|
|
|
|
+| onExtraClick | callback that is called when the extra content is clicked | (e: Object): void | |
|
|
|
|
|
+| onVirtualKeyboardConfirm | callback that is called when "confirm" button of virtual keyboard is clicked | (val: string): void | |
|
|
|
|
|
+| labelNumber | number of label text, valid value is 2 to 7 | number | `5` |
|
|
|
|
|
+| locale | 国际化,可覆盖全局`[LocaleProvider](https://mobile.ant.design/components/locale-provider)`的配置, when`type`is`money`,can cunstom the keyboard confirm item's label | Object: { confirmLabel } | 无 |
|
|
|
|
|
+| last | If it is the last item, the `borderBottom` will be removed, the default has `borderBottom` | bool | false |
|
|
|
|
|
+
|
|
|
|
|
+> More available react-native `InputItem` API can be found at [react-native TextInput](http://facebook.github.io/react-native/docs/textinput.html)
|
|
|
|
|
+
|
|
|
|
|
+> Note: `InputItem` does not support negative number if `type` is text, you can use `type=text` to do that.
|
|
|
|
|
+
|
|
|
|
|
+## InputItem Instance methods
|
|
|
|
|
+
|
|
|
|
|
+Property | Description | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| focus | Force focus back onto the input node | (): void | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## List
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/list.md
|
|
|
|
|
+
|
|
|
|
|
+# List
|
|
|
|
|
+
|
|
|
|
|
+A single and continuous block content is vertically arranged to display current contents, status and available operations. eg:Contact List.
|
|
|
|
|
+
|
|
|
|
|
+In case you need an infinite scroll list - consider using [ListView](https://mobile.ant.design/components/list-view/) component.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- Generally `List` consists of main infomation, main operations, secondary infomation and secondary operations.
|
|
|
|
|
+- The main infomation and main operations are placed on the left side of list, and secondary infomation and secondary operations are placed on the right side.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Image, ScrollView, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const Item = List.Item
|
|
|
|
|
+const Brief = Item.Brief
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicListExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ style={{ flex: 1, backgroundColor: '#f5f5f9' }}
|
|
|
|
|
+ automaticallyAdjustContentInsets={false}
|
|
|
|
|
+ showsHorizontalScrollIndicator={false}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}>
|
|
|
|
|
+ <List renderHeader={'basic'}>
|
|
|
|
|
+ <Item data-seed="logId">
|
|
|
|
|
+ 标题文字点击无反馈,文字超长则隐藏,文字超长则隐藏
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item wrap>
|
|
|
|
|
+ 文字超长折行文字超长折行文字超长折行文字超长折行文字超长折行
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item disabled extra="箭头向右" arrow="horizontal" onPress={() => {}}>
|
|
|
|
|
+ 标题文字
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item extra="箭头向下" arrow="down" onPress={() => {}}>
|
|
|
|
|
+ 标题文字
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item extra="箭头向上" arrow="up" onPress={() => {}}>
|
|
|
|
|
+ 标题文字
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item extra="没有箭头" arrow="empty">
|
|
|
|
|
+ 标题文字
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <View>
|
|
|
|
|
+ 内容内容
|
|
|
|
|
+ <Brief style={{ textAlign: 'right' }}>辅助文字内容</Brief>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ multipleLine>
|
|
|
|
|
+ 垂直居中对齐
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item extra="内容内容" multipleLine>
|
|
|
|
|
+ 垂直居中对齐<Brief>辅助文字内容</Brief>
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item
|
|
|
|
|
+ wrap
|
|
|
|
|
+ extra="文字超长折行文字超长折行文字超长折行文字超长折行文字超长折行文字超长折行文字超长折行"
|
|
|
|
|
+ multipleLine
|
|
|
|
|
+ align="top"
|
|
|
|
|
+ arrow="horizontal">
|
|
|
|
|
+ 顶部对齐
|
|
|
|
|
+ <Brief>辅助文字内容辅助文字内容辅助文字内容辅助文字内容</Brief>
|
|
|
|
|
+ <Brief>辅助文字内容</Brief>
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <View>
|
|
|
|
|
+ 内容内容
|
|
|
|
|
+ <Brief style={{ textAlign: 'right' }}>辅助文字内容</Brief>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ multipleLine
|
|
|
|
|
+ align="bottom">
|
|
|
|
|
+ 底部对齐
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'带缩略图'}>
|
|
|
|
|
+ <Item thumb="https://os.alipayobjects.com/rmsportal/mOoPurdIfmcuqtr.png">
|
|
|
|
|
+ thumb
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item
|
|
|
|
|
+ thumb="https://os.alipayobjects.com/rmsportal/mOoPurdIfmcuqtr.png"
|
|
|
|
|
+ arrow="horizontal">
|
|
|
|
|
+ thumb
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ <Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Image
|
|
|
|
|
+ source={{
|
|
|
|
|
+ uri: 'https://os.alipayobjects.com/rmsportal/mOoPurdIfmcuqtr.png',
|
|
|
|
|
+ }}
|
|
|
|
|
+ style={{ width: 29, height: 29 }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }
|
|
|
|
|
+ arrow="horizontal">
|
|
|
|
|
+ extra为Image
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const title = 'List'
|
|
|
|
|
+export const description = 'List Example'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### List
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+-----------|------------|------|---------|---------|
|
|
|
|
|
+| renderHeader | list heder | (): void | | |
|
|
|
|
|
+| renderFooter | list footer | (): void | | |
|
|
|
|
|
+| styles | Semantic DOM style | [ListStyle](#liststyle-interface) | - | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+### List.Item
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+-----------|------------|------|---------|---------|
|
|
|
|
|
+| thumb | thumbnail on the left side of `List`(string type will be used to set img src) | String \| React.Element | | |
|
|
|
|
|
+| extra | extra content on the right side of `List` | String \| React.Element | | |
|
|
|
|
|
+| arrow | arrow direction, options: `horizontal`,`up`,`down`, `empty`; `empty` option may hide the dom | String | | |
|
|
|
|
|
+| align | vertical alignment of child elements,options: `top`,`middle`,`bottom` | String | `middle` | | |
|
|
|
|
|
+| onPress | callback is called when list is clicked | Same as [TouchableHighlightProps['onPress']](#touchablehighlightprops) | | |
|
|
|
|
|
+| multipleLine | multiple line | Boolean | `false` | |
|
|
|
|
|
+| wrap | Whether to wrap long texts, otherwise it will be hidden by default. | Boolean | `false` | |
|
|
|
|
|
+| styles | Semantic DOM style | [ListItemStyle](#listitemstyle-interface) | - | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+### TouchableHighlightProps
|
|
|
|
|
+
|
|
|
|
|
+New in `5.2.1`. In addition, all properties of [TouchableHighlightProps](https://reactnative.dev/docs/touchablehighlight) are supported;
|
|
|
|
|
+when setting `onPress` props, it has a default touch style:
|
|
|
|
|
+<br/> `{ underlayColor:'#dddddd', activeOpacity: 0.5 }`
|
|
|
|
|
+
|
|
|
|
|
+### List.Item.Brief
|
|
|
|
|
+
|
|
|
|
|
+Brief infomation
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+-----------|------------|------|---------|---------|
|
|
|
|
|
+| wrap | Whether to wrap long texts, otherwise it will be hidden by default. | Boolean | `false` | |
|
|
|
|
|
+| styles | Semantic DOM style | [BriefStyle](#briefstyle-interface) | - | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+### ListStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface ListStyle {
|
|
|
|
|
+ List: ViewStyle
|
|
|
|
|
+ Header: TextStyle
|
|
|
|
|
+ Footer: TextStyle
|
|
|
|
|
+ Body: ViewStyle
|
|
|
|
|
+ BodyBottomLine: ViewStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+### ListItemStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface ListItemStyle {
|
|
|
|
|
+ underlayColor: ViewStyle // ListItem is a TouchableHighlight
|
|
|
|
|
+
|
|
|
|
|
+ Item: ViewStyle // ListItem wrap
|
|
|
|
|
+ Line: ViewStyle // borderBottom
|
|
|
|
|
+
|
|
|
|
|
+ Thumb: ImageStyle
|
|
|
|
|
+ Content: TextStyle
|
|
|
|
|
+ Extra: TextStyle
|
|
|
|
|
+
|
|
|
|
|
+ Arrow: TextStyle // horizontal arrow
|
|
|
|
|
+ ArrowV: TextStyle // up/down arrow
|
|
|
|
|
+ multipleLine: ViewStyle
|
|
|
|
|
+ multipleThumb: ImageStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+### BriefStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface BriefStyle {
|
|
|
|
|
+ Brief: ViewStyle
|
|
|
|
|
+ BriefText: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## ListView
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/list-view.md
|
|
|
|
|
+
|
|
|
|
|
+# ListView
|
|
|
|
|
+
|
|
|
|
|
+Documentation please checkout https://github.com/gameboyVito/react-native-ultimate-listview
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { ListView } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicListExample extends React.Component<any, any> {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ layout: 'list',
|
|
|
|
|
+ }
|
|
|
|
|
+ sleep = (time: any) =>
|
|
|
|
|
+ new Promise((resolve) => setTimeout(() => resolve(''), time))
|
|
|
|
|
+ onFetch = async (
|
|
|
|
|
+ page = 1,
|
|
|
|
|
+ startFetch: (arg0: string[], arg1: number) => void,
|
|
|
|
|
+ abortFetch: () => void,
|
|
|
|
|
+ ) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ //This is required to determinate whether the first loading list is all loaded.
|
|
|
|
|
+ let pageLimit = 30
|
|
|
|
|
+ if (this.state.layout === 'grid') {
|
|
|
|
|
+ pageLimit = 60
|
|
|
|
|
+ }
|
|
|
|
|
+ const skip = (page - 1) * pageLimit
|
|
|
|
|
+
|
|
|
|
|
+ //Generate dummy data
|
|
|
|
|
+ let rowData = Array.from(
|
|
|
|
|
+ { length: pageLimit },
|
|
|
|
|
+ (_, index) => `item -> ${index + skip}`,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ //Simulate the end of the list if there is no more data returned from the server
|
|
|
|
|
+ if (page === 3) {
|
|
|
|
|
+ rowData = []
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //Simulate the network loading in ES7 syntax (async/await)
|
|
|
|
|
+ await this.sleep(2000)
|
|
|
|
|
+ startFetch(rowData, pageLimit)
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ abortFetch() //manually stop the refresh or pagination if it encounters network error
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ renderItem = (item: any) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ padding: 10 }}>
|
|
|
|
|
+ <Text>{item}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ListView
|
|
|
|
|
+ onFetch={this.onFetch}
|
|
|
|
|
+ keyExtractor={(item: any, index: any) =>
|
|
|
|
|
+ `${this.state.layout} - ${item} - ${index}`
|
|
|
|
|
+ }
|
|
|
|
|
+ renderItem={this.renderItem}
|
|
|
|
|
+ numColumns={this.state.layout === 'list' ? 1 : 3}
|
|
|
|
|
+ />
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const title = 'ListView'
|
|
|
|
|
+export const description = 'ListView Example'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Modal
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/modal.md
|
|
|
|
|
+
|
|
|
|
|
+# Modal
|
|
|
|
|
+
|
|
|
|
|
+Use to show important information for the system, and ask for user feedback. eg: When deleting an important content, pop up a Modal for secondary confirmation.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- Use as few as possible. Modal will interrupt user operation, only use it at important situation.
|
|
|
|
|
+- Title should be concise, do not exceed 1 line; description should be concise and complete, generally no more than 2 lines.
|
|
|
|
|
+- Operation buttons are up to 3(vertical), generally 1-2(horizontal); [ActionSheet](/components/action-sheet) is preferred when there are more than 3 actions.
|
|
|
|
|
+- Generally put the most likely clicked button on the right side. In addition, the cancel button should always be on the left.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ Button,
|
|
|
|
|
+ List,
|
|
|
|
|
+ Modal,
|
|
|
|
|
+ Provider,
|
|
|
|
|
+ Switch,
|
|
|
|
|
+ Toast,
|
|
|
|
|
+ WhiteSpace,
|
|
|
|
|
+ WingBlank,
|
|
|
|
|
+} from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicModalExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ visible: false,
|
|
|
|
|
+ visible1: false,
|
|
|
|
|
+ visible2: false,
|
|
|
|
|
+ modalType: 'portal',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onClose = () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ visible: false,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onClose1 = () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ visible1: false,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onClose2 = () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ visible2: false,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClick = () => {
|
|
|
|
|
+ Modal.alert('Title', 'alert content', [
|
|
|
|
|
+ { text: 'Cancel', onPress: () => console.log('cancel'), style: 'cancel' },
|
|
|
|
|
+ { text: 'OK', onPress: () => console.log('ok') },
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClickPromise = () => {
|
|
|
|
|
+ Modal.alert('Title', 'promise button', [
|
|
|
|
|
+ {
|
|
|
|
|
+ text: 'Cancel',
|
|
|
|
|
+ onPress: () => {
|
|
|
|
|
+ Toast.info('onPress promise resolve', 1)
|
|
|
|
|
+ return new Promise((resolve) => {
|
|
|
|
|
+ setTimeout(resolve, 1000)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ style: 'cancel',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ text: 'Hold on',
|
|
|
|
|
+ onPress: () => {
|
|
|
|
|
+ Toast.info('onPress promise reject', 1)
|
|
|
|
|
+ return new Promise((_, reject) => {
|
|
|
|
|
+ setTimeout(reject, 1000)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClick2 = () => {
|
|
|
|
|
+ Modal.operation([
|
|
|
|
|
+ { text: '标为未读', onPress: () => console.log('标为未读被点击了') },
|
|
|
|
|
+ { text: '置顶聊天', onPress: () => console.log('置顶聊天被点击了') },
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClick3 = () => {
|
|
|
|
|
+ Modal.prompt(
|
|
|
|
|
+ 'Login',
|
|
|
|
|
+ 'Pleas input login information',
|
|
|
|
|
+ (login: any, password: any) =>
|
|
|
|
|
+ console.log(`login: ${login}, password: ${password}`),
|
|
|
|
|
+ 'login-password',
|
|
|
|
|
+ '',
|
|
|
|
|
+ ['Please input name', 'Please input password'],
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClick4 = () => {
|
|
|
|
|
+ Modal.prompt(
|
|
|
|
|
+ 'Input password',
|
|
|
|
|
+ 'password message',
|
|
|
|
|
+ (password: any) => console.log(`password: ${password}`),
|
|
|
|
|
+ 'secure-text',
|
|
|
|
|
+ 'defaultValue',
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClick5 = () => {
|
|
|
|
|
+ Modal.prompt(
|
|
|
|
|
+ 'Name',
|
|
|
|
|
+ 'name message',
|
|
|
|
|
+ (password: any) => console.log(`password: ${password}`),
|
|
|
|
|
+ 'default',
|
|
|
|
|
+ '',
|
|
|
|
|
+ ['please input name'],
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onButtonClick6 = () => {
|
|
|
|
|
+ Modal.operation(
|
|
|
|
|
+ [
|
|
|
|
|
+ { text: '标为未读', onPress: () => console.log('标为未读被点击了') },
|
|
|
|
|
+ { text: '置顶聊天', onPress: () => console.log('置顶聊天被点击了') },
|
|
|
|
|
+ ],
|
|
|
|
|
+ () => {
|
|
|
|
|
+ console.log('返回键点击')
|
|
|
|
|
+ return false
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const footerButtons = [
|
|
|
|
|
+ { text: 'Cancel', onPress: () => console.log('cancel') },
|
|
|
|
|
+ { text: 'Ok', onPress: () => console.log('ok') },
|
|
|
|
|
+ ]
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <ScrollView style={{ marginTop: 20 }}>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ style={{ width: 70 }}
|
|
|
|
|
+ checked={this.state.modalType === 'modal'}
|
|
|
|
|
+ onChange={(val) => {
|
|
|
|
|
+ this.setState({ modalType: val ? 'modal' : 'portal' })
|
|
|
|
|
+ }}
|
|
|
|
|
+ checkedChildren="modal"
|
|
|
|
|
+ unCheckedChildren="portal"
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ 切换modalType
|
|
|
|
|
+ <List.Item.Brief>
|
|
|
|
|
+ `modalType='modal'`时将调用原生Modal{' '}
|
|
|
|
|
+ </List.Item.Brief>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Button onPress={() => this.setState({ visible: true })}>
|
|
|
|
|
+ showModal
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={() => this.setState({ visible1: true })}>
|
|
|
|
|
+ transparent:false
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={() => this.setState({ visible2: true })}>
|
|
|
|
|
+ popup
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClick}>Modal.alert</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClickPromise}>
|
|
|
|
|
+ Modal.alert (promise)
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClick2}>Modal.opertation</Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClick6}>
|
|
|
|
|
+ Modal.opertation (onBackHandler)
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClick5}>
|
|
|
|
|
+ Modal.prompt (default)
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClick3}>
|
|
|
|
|
+ Modal.prompt (login-password)
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Button onPress={this.onButtonClick4}>
|
|
|
|
|
+ Modal.prompt (secure-text)
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ <Modal
|
|
|
|
|
+ title="Title"
|
|
|
|
|
+ transparent
|
|
|
|
|
+ modalType={this.state.modalType}
|
|
|
|
|
+ onClose={this.onClose}
|
|
|
|
|
+ maskClosable
|
|
|
|
|
+ visible={this.state.visible}
|
|
|
|
|
+ closable
|
|
|
|
|
+ footer={footerButtons}>
|
|
|
|
|
+ <View style={{ paddingVertical: 20 }}>
|
|
|
|
|
+ <Text style={{ textAlign: 'center' }}>Content...</Text>
|
|
|
|
|
+ <Text style={{ textAlign: 'center' }}>Content...</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Button type="primary" onPress={this.onClose}>
|
|
|
|
|
+ close modal
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Modal>
|
|
|
|
|
+ <Modal
|
|
|
|
|
+ transparent={false}
|
|
|
|
|
+ modalType={this.state.modalType}
|
|
|
|
|
+ visible={this.state.visible1}
|
|
|
|
|
+ animationType="slide-up"
|
|
|
|
|
+ onClose={this.onClose1}>
|
|
|
|
|
+ <View style={{ paddingVertical: 220 }}>
|
|
|
|
|
+ <Text style={{ textAlign: 'center' }}>Content...</Text>
|
|
|
|
|
+ <Text style={{ textAlign: 'center' }}>Content...</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ style={{ marginBottom: 10 }}
|
|
|
|
|
+ onPress={() => Toast.info('Hello Toast in Modal now works')}>
|
|
|
|
|
+ {this.state.modalType === 'portal'
|
|
|
|
|
+ ? 'Hello Toast in Modal now works'
|
|
|
|
|
+ : "Hello Toast not works when modalType='portal'"}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button type="primary" onPress={this.onClose1}>
|
|
|
|
|
+ close modal
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Modal>
|
|
|
|
|
+ <Modal
|
|
|
|
|
+ popup
|
|
|
|
|
+ modalType={this.state.modalType}
|
|
|
|
|
+ visible={this.state.visible2}
|
|
|
|
|
+ animationType="slide-up"
|
|
|
|
|
+ onClose={this.onClose2}>
|
|
|
|
|
+ <View style={{ paddingVertical: 20, paddingHorizontal: 20 }}>
|
|
|
|
|
+ <Text style={{ textAlign: 'center' }}>Content...</Text>
|
|
|
|
|
+ <Text style={{ textAlign: 'center' }}>Content...</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Button type="primary" onPress={this.onClose2}>
|
|
|
|
|
+ close modal
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Modal>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Modal
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|---------|---------|
|
|
|
|
|
+| visible | Determine whether a modal dialog is visible or not | Boolean | false | |
|
|
|
|
|
+| closable | Determine whether a close (x) button is visible or not | Boolean | false | |
|
|
|
|
|
+| maskClosable | Determine whether to close the modal dialog when clicked mask of it | Boolean | true | |
|
|
|
|
|
+| onClose | Callback for clicking close icon x or mask | (): void | - | |
|
|
|
|
|
+| transparent | transparent mode or full screen mode | Boolean | false | |
|
|
|
|
|
+| popup | popup mode | Boolean | false | |
|
|
|
|
|
+| animationDuration | Animation duration, in ms | Number | 300 | `5.3.0` |
|
|
|
|
|
+| animationType | Options: 'fade' / 'slide' | String | |fade |
|
|
|
|
|
+| modalType | The type of the popup. <br/>When it is `'portal'`, it is inserted from the `<Provider />` root node (default). <br/>When it is `'modal'`, it is the same as [`react-native/Modal`](https://reactnative.dev/docs/modal) (used to get the current context). <br/>When it is `'view'`, it is the same as `react-native/View` (used to nest popups in popups). | `'portal'`\| `'modal'` \| `'view'` | `'portal'` | `5.3.0` |
|
|
|
|
|
+| title | title | React.Element | - | |
|
|
|
|
|
+| footer | footer content | Array [{text, onPress}] | [] | |
|
|
|
|
|
+| onRequestClose | The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV. Returns `true` to prevent `BackHandler` events when modal is open.| (): boolean | false | |
|
|
|
|
|
+| style | style same as `styles.innerContainer` | `ViewStyle` | - | |
|
|
|
|
|
+| styles | Semantic DOM style | [ModalStyle](#modalstyle-interface) | - | |
|
|
|
|
|
+
|
|
|
|
|
+### ModalStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface ModalStyle {
|
|
|
|
|
+ container: ViewStyle // Set `z-index`
|
|
|
|
|
+ wrap: ViewStyle // Set modal flex layout: `{justifyContent: 'center',alignItems: 'center'}`
|
|
|
|
|
+ innerContainer: ViewStyle // modal content view, default: `{ widh:286 }`
|
|
|
|
|
+
|
|
|
|
|
+ // modal content fields
|
|
|
|
|
+ footer: ViewStyle
|
|
|
|
|
+ header: TextStyle
|
|
|
|
|
+ body: ViewStyle
|
|
|
|
|
+ closeWrap: ViewStyle
|
|
|
|
|
+ close: TextStyle
|
|
|
|
|
+ buttonGroupH: ViewStyle
|
|
|
|
|
+ buttonGroupV: ViewStyle
|
|
|
|
|
+ buttonWrapH: ViewStyle
|
|
|
|
|
+ buttonWrapV: ViewStyle
|
|
|
|
|
+ buttonText: TextStyle
|
|
|
|
|
+
|
|
|
|
|
+ // popup
|
|
|
|
|
+ popupContainer: ViewStyle
|
|
|
|
|
+ popupSlideUp: ViewStyle
|
|
|
|
|
+ popupSlideDown: ViewStyle
|
|
|
|
|
+ // operation
|
|
|
|
|
+ operationContainer: ViewStyle
|
|
|
|
|
+ operationBody: ViewStyle
|
|
|
|
|
+ buttonTextOperation: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Modal.useModal()
|
|
|
|
|
+
|
|
|
|
|
+When you need using Context, you can use `contextHolder` which created by `Modal.useModal` to insert into children. Modal created by hooks will get all the context where `contextHolder` are. Created `modal` has the same creating function with [`Modal.method`](#static-method)(Static method).
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+const [modal, contextHolder] = Modal.useModal();
|
|
|
|
|
+
|
|
|
|
|
+React.useEffect(() => {
|
|
|
|
|
+ modal.alert(
|
|
|
|
|
+ // ...
|
|
|
|
|
+ );
|
|
|
|
|
+}, []);
|
|
|
|
|
+
|
|
|
|
|
+return <View>{contextHolder}</View>;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Static method
|
|
|
|
|
+
|
|
|
|
|
+### Modal.alert(title, message, actions?)
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| title | title | String or React.Element | - |
|
|
|
|
|
+| message | message | String or React.Element | - |
|
|
|
|
|
+| actions | button group, [{text, onPress, style}] | Array | - |
|
|
|
|
|
+| onBackHandler | Callback of the back key (not required), returns true to close modal, false to prevent modal from closing| (): boolean | 无 |
|
|
|
|
|
+
|
|
|
|
|
+### Modal.prompt(title, message, callbackOrActions, type?, defaultValue?)
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| title | title | String or React.Element | - |
|
|
|
|
|
+| message | message | String or React.Element | - |
|
|
|
|
|
+| callbackOrActions | button group [{text, onPress}] or callback | Array or Function | - |
|
|
|
|
|
+| type | prompt style | String (`default`, `secure-text`, `login-password`)| `default` |
|
|
|
|
|
+| defaultValue | Default(input whick type is password is not supported) | String | - |
|
|
|
|
|
+| placeholders | ['', ''] | String[] | - |
|
|
|
|
|
+| onBackHandler | Callback of the back key (not required), returns true to close modal, false to prevent modal from closing| (): boolean | 无 |
|
|
|
|
|
+
|
|
|
|
|
+### Modal.operation(actions?, onBackHandler?)
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| actions | button group, [{text, onPress, style}] | Array | - |
|
|
|
|
|
+| onBackHandler | Callback of the back key (not required), returns true to close modal, false to prevent modal from closing| (): boolean | 无 |
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### How to close the static Modal.method()?
|
|
|
|
|
+
|
|
|
|
|
+You need to use `Portal.remove(key)` method; Take `Modal.alert` as an example
|
|
|
|
|
+```jsx
|
|
|
|
|
+import { Modal, Portal } from '@ant-design/react-native'
|
|
|
|
|
+import { useRef } from 'react'
|
|
|
|
|
+
|
|
|
|
|
+function App() {
|
|
|
|
|
+ const key = useRef()
|
|
|
|
|
+
|
|
|
|
|
+ const onOpen = () => {
|
|
|
|
|
+ key.current = Modal.alert({})
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const onClose = () => {
|
|
|
|
|
+ // close the Modal.alert
|
|
|
|
|
+ Portal.remove(key)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+When using `Modal.useModal`, use the `modal.remove(key)` method:
|
|
|
|
|
+```jsx
|
|
|
|
|
+import { Modal, Portal } from '@ant-design/react-native'
|
|
|
|
|
+import { useRef } from 'react'
|
|
|
|
|
+
|
|
|
|
|
+function App() {
|
|
|
|
|
+ const [modal, contextHolder] = Modal.useModal();
|
|
|
|
|
+ const key = useRef()
|
|
|
|
|
+
|
|
|
|
|
+ const onOpen = () => {
|
|
|
|
|
+ key.current = modal.alert({})
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const onClose = () => {
|
|
|
|
|
+ // close the modal.alert
|
|
|
|
|
+ modal.remove(key)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ ...
|
|
|
|
|
+ {contextHolder}
|
|
|
|
|
+ </>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Why I can not access context,redux,useRouter in `<Modal />` or `Modal.xxx`?
|
|
|
|
|
+
|
|
|
|
|
+Rendering `<Modal>` or calling Modal methods directly is dynamically inserted into the `<Provider>` root node through `Portal.add` by default. At this time, its context is different from the context of the current code, so the context information cannot be obtained.
|
|
|
|
|
+
|
|
|
|
|
+When you need context info, <br/>
|
|
|
|
|
+**1.** you can use `Modal.useModal` to get `modal` instance and `contextHolder` node. And put it in your children:
|
|
|
|
|
+```tsx
|
|
|
|
|
+const [modal, contextHolder] = Modal.useModal();
|
|
|
|
|
+
|
|
|
|
|
+// then call modal.confirm instead of Modal.confirm
|
|
|
|
|
+
|
|
|
|
|
+return (
|
|
|
|
|
+ <Context1.Provider value="Ant">
|
|
|
|
|
+ {/* contextHolder is in Context1, which means modal will get context of Context1 */}
|
|
|
|
|
+ {contextHolder}
|
|
|
|
|
+ <Context2.Provider value="Design">
|
|
|
|
|
+ {/* contextHolder is out of Context2, which means modal will not get context of Context2 */}
|
|
|
|
|
+ </Context2.Provider>
|
|
|
|
|
+ </Context1.Provider>
|
|
|
|
|
+);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Note**: You must insert `contextHolder` into your children with hooks. You can use origin method if you do not need context connection.
|
|
|
|
|
+
|
|
|
|
|
+**2.** When using `<Modal />`, by setting `modalType='modal'`, the **native Modal component** will be used internally to maintain the context:
|
|
|
|
|
+```tsx
|
|
|
|
|
+<Modal modelType="modal" ...>
|
|
|
|
|
+ ...
|
|
|
|
|
+</Modal>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## NoticeBar
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/notice-bar.md
|
|
|
|
|
+
|
|
|
|
|
+# NoticeBar
|
|
|
|
|
+
|
|
|
|
|
+Component to display a system message, event notice and etc. Which is under the navigation bar.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Be used to attract user's attension, the importance level is lower than `Modal` and higher than `Toast`.
|
|
|
|
|
+- It can also achieve a lightweight marquee effect.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ Icon,
|
|
|
|
|
+ List,
|
|
|
|
|
+ NoticeBar,
|
|
|
|
|
+ Picker,
|
|
|
|
|
+ Provider,
|
|
|
|
|
+ Slider,
|
|
|
|
|
+ Switch,
|
|
|
|
|
+ WhiteSpace,
|
|
|
|
|
+} from '@ant-design/react-native'
|
|
|
|
|
+import React, { useState } from 'react'
|
|
|
|
|
+import { ScrollView, Text } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default function NoticeBarExample() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <ScrollView style={{ marginBottom: 40 }}>
|
|
|
|
|
+ {true && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <List renderHeader={'自定义颜色'}>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar>默认</NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ styles={{
|
|
|
|
|
+ font: { color: '#ffffff' },
|
|
|
|
|
+ background: { backgroundColor: '#f4333c' },
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 错误
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ styles={{
|
|
|
|
|
+ font: { color: '#108ee9' },
|
|
|
|
|
+ background: { backgroundColor: '#d0e4ff' },
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 信息
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'可关闭'}>
|
|
|
|
|
+ <NoticeBar mode="closable">这条通知可以关闭</NoticeBar>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'超长滚动'}>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar marqueeProps={{ loop: true }}>
|
|
|
|
|
+ Notice: I can be a React component, multiple React components,
|
|
|
|
|
+ or just some text.
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ marqueeProps={{
|
|
|
|
|
+ loop: true,
|
|
|
|
|
+ autoFill: true,
|
|
|
|
|
+ trailing: 0,
|
|
|
|
|
+ spacing: 10,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ autoFill&spacing
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'自定义'}>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ mode="link"
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ console.log('onPress')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ mode="link"
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ mode="closable"
|
|
|
|
|
+ icon={<Icon name="compass" style={{ color: '#f4333c' }} />}
|
|
|
|
|
+ action={
|
|
|
|
|
+ <Icon name="close-circle" style={{ color: '#f4333c' }} />
|
|
|
|
|
+ }>
|
|
|
|
|
+ 自定义图标
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ marqueeProps={{ loop: true, autoFill: true }}
|
|
|
|
|
+ mode="closable"
|
|
|
|
|
+ action={<Text style={{ color: '#a1a1a1' }}>不再提示</Text>}>
|
|
|
|
|
+ 自定义右侧功能区 Closable demo for `action`.
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ <List renderHeader={'方向/播放/暂停控制'}>
|
|
|
|
|
+ <ControlDemo />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function ControlDemo() {
|
|
|
|
|
+ const [play, setPlay] = useState(true)
|
|
|
|
|
+ const [autoFill, setAutoFill] = useState(false)
|
|
|
|
|
+ const [direction, setDirection] = useState<'left' | 'right' | 'up' | 'down'>(
|
|
|
|
|
+ 'left',
|
|
|
|
|
+ )
|
|
|
|
|
+ const [fps, setFps] = useState(40)
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <NoticeBar
|
|
|
|
|
+ marqueeProps={{
|
|
|
|
|
+ play,
|
|
|
|
|
+ autoFill,
|
|
|
|
|
+ direction,
|
|
|
|
|
+ fps,
|
|
|
|
|
+ loop: 0,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ Notice: I can be a React component, multiple React components, or just
|
|
|
|
|
+ some text.
|
|
|
|
|
+ </NoticeBar>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <List.Item extra={<Switch checked={play} onChange={setPlay} />}>
|
|
|
|
|
+ Play
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item extra={<Switch checked={autoFill} onChange={setAutoFill} />}>
|
|
|
|
|
+ AutoFill
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ data={[
|
|
|
|
|
+ { label: 'Left', value: 'left' },
|
|
|
|
|
+ { label: 'Right', value: 'right' },
|
|
|
|
|
+ { label: 'Up', value: 'up' },
|
|
|
|
|
+ { label: 'Down', value: 'down' },
|
|
|
|
|
+ ]}
|
|
|
|
|
+ value={[direction]}
|
|
|
|
|
+ onChange={(val) => setDirection(val[0] as any)}>
|
|
|
|
|
+ <List.Item arrow="horizontal">Direction</List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <List.Item.Brief>速度fps: {fps}</List.Item.Brief>
|
|
|
|
|
+ <Slider
|
|
|
|
|
+ onAfterChange={setFps}
|
|
|
|
|
+ ticks
|
|
|
|
|
+ step={10}
|
|
|
|
|
+ defaultValue={fps}
|
|
|
|
|
+ popover
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+|------------|------------|------|---------|---------|
|
|
|
|
|
+| action | text which is used to replace right icon | `ReactNode` | - | |
|
|
|
|
|
+| children | The children rendered inside the marquee | `ReactNode` | - | |
|
|
|
|
|
+| icon | Set the icon at the start position | `ReactNode` | `<Icon name="sound" color={theme.brand_error} />`| |
|
|
|
|
|
+| marqueeProps | marquee params | [MarqueeProps](#marquee-props) | `{loop: false, leading: 500, trailing: 800, fps: 40}` | |
|
|
|
|
|
+| mode | Type of NoticeBar. Invalid when `action` is present | `closable`\|`link` | - | |
|
|
|
|
|
+| onClose | A callback function, can be executed when you click the `action` icon. Only valid in `mode="closable"` | `() => void` | - | `5.2.1` |
|
|
|
|
|
+| onPress | A callback function, can be executed when you click on the operating area | `() => void` | - | |
|
|
|
|
|
+| style | Container style | `StyleProp<ViewStyle>` | - | |
|
|
|
|
|
+| styles | Semantic DOM style | [NoticeBarStyle](#noticebarstyle-interface) | - | |
|
|
|
|
|
+
|
|
|
|
|
+- Theme color [theme.brand_error](https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/style/themes/default.tsx#L35) = `#f4333c`
|
|
|
|
|
+
|
|
|
|
|
+### Marquee props
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+|------------|------------|------|---------|---------|
|
|
|
|
|
+| autoFill | Whether to automatically fill blank space in the marquee with copies of the children or not | `Boolean` | false | `5.2.1` |
|
|
|
|
|
+| direction | The direction the marquee slides | `'left'` \| `'right'` \| `'up'` \| `'down'` | `'left'` | `5.2.2` add `'up'`&`'down'` |
|
|
|
|
|
+| fps | Speed calculated as pixels/second | `Number` | 40 | |
|
|
|
|
|
+| leading | Duration to delay the animation after first render, in millisecond | `Number` | 500 | |
|
|
|
|
|
+| loop | The number of times the marquee should loop, `true/0` is equivalent to infinite | `Boolean` \| `Number` | false | |
|
|
|
|
|
+| onFinish | A callback for when the marquee finishes scrolling and stops. Only calls if loop is non-zero or false. | `() => void` | - | `5.2.1` |
|
|
|
|
|
+| onCycleComplete | A callback for when the marquee finishes a loop. Does not call if maximum loops are reached (use onFinish instead). | `() => void` | - | `5.2.1` |
|
|
|
|
|
+| play | Whether to play or pause the marquee | `Boolean` | true | `5.2.1` |
|
|
|
|
|
+| spacing | Spacing between repeting elements, valid when `autoFill={true}` | `Number` | 0 | `5.2.1` |
|
|
|
|
|
+| style | The marquee Text style | `TextStyle` | - | |
|
|
|
|
|
+| trailing | Duration to delay the animation after previous loop, valid when `autoFill={false}`, in millisecond | `Number` | 800 | |
|
|
|
|
|
+| wrapStyle | Marquee wrap view style | `ViewStyle` | - | |
|
|
|
|
|
+
|
|
|
|
|
+> Design Reference: [https://github.com/justin-chu/react-fast-marquee](https://github.com/justin-chu/react-fast-marquee), can be used as a marquee component alone
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+// New in 5.2.2
|
|
|
|
|
+import { Marquee } from '@ant-design/react-native'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## NoticeBarStyle interface
|
|
|
|
|
+
|
|
|
|
|
+`5.2.1`refactored the styles
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+interface NoticeBarStyle {
|
|
|
|
|
+ container: ViewStyle, // Outermost container style, default: {minHeight: 36(theme.notice_bar_height)}
|
|
|
|
|
+ font: TextStyle, // Font style, default: {color: #f4333c(theme.brand_error)}
|
|
|
|
|
+ background: ViewStyle, // Background color, default: {backgroundColor: #fffada}
|
|
|
|
|
+
|
|
|
|
|
+ marquee: TextStyle, // marquee font style
|
|
|
|
|
+
|
|
|
|
|
+ iconWrap: ViewStyle, // left icon wrap
|
|
|
|
|
+ actionWrap: ViewStyle, // right action wrap
|
|
|
|
|
+ close: ViewStyle, // mode="closeable" icon
|
|
|
|
|
+ link: ViewStyle // mode="link" icon
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Ref
|
|
|
|
|
+
|
|
|
|
|
+New in `5.2.1`. Ref to MarqueeActions.
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type|
|
|
|
|
|
+|-----|------|------|
|
|
|
|
|
+| play | Start the marquee text rolling | `() => void` |
|
|
|
|
|
+| pause | Pause the marquee text | `() => void` |
|
|
|
|
|
+| stop | Return the marquee text to the original position | `() => void` |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Pagination
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/pagination.md
|
|
|
|
|
+
|
|
|
|
|
+# Pagination
|
|
|
|
|
+
|
|
|
|
|
+A long list can be divided into several pages by `Pagination`, and only one page will be loaded at a time.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+
|
|
|
|
|
+- When it will take a long time to load/render all items.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Pagination, WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+
|
|
|
|
|
+const locale = {
|
|
|
|
|
+ prevText: '上一步',
|
|
|
|
|
+ nextText: '下一步',
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicPaginationExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <Pagination total={5} current={1} locale={locale} />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <Pagination simple total={5} current={1} locale={locale} />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <Pagination mode="number" total={5} current={3} />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <Pagination mode="pointer" total={5} current={2} />
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| mode | the mode of `Pagination` which can be one of `button`,`number`,`pointer` | string | `button` |
|
|
|
|
|
+| current | current page index | number | 1 |
|
|
|
|
|
+| total | total number of data | number | 0 |
|
|
|
|
|
+| simple | whether to hide number | boolean | false |
|
|
|
|
|
+| disabled | whether is disabled | boolean | false |
|
|
|
|
|
+| locale | [i18n](/components/locale-provider/) setting, you can override the configuration of the global `LocaleProvider | Object:{prevText, nextText} | |
|
|
|
|
|
+| onChange | invoked with the new index when the value changes. | (index: Number): void | |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Picker
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/picker.md
|
|
|
|
|
+
|
|
|
|
|
+# Picker
|
|
|
|
|
+
|
|
|
|
|
+Choose from a set of data, e.g. Country choice.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- Try to use Picker to help users complete the input, to avoid the user through the keyboard directly input.
|
|
|
|
|
+- DatePicker is Picker's specific pattern.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ Button,
|
|
|
|
|
+ List,
|
|
|
|
|
+ Picker,
|
|
|
|
|
+ PickerValue,
|
|
|
|
|
+ PickerValueExtend,
|
|
|
|
|
+ Provider,
|
|
|
|
|
+} from '@ant-design/react-native'
|
|
|
|
|
+import { district } from 'antd-mobile-demo-data'
|
|
|
|
|
+import React, { useState } from 'react'
|
|
|
|
|
+import { Text, TouchableOpacity, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const CustomChildren = (props: any) => (
|
|
|
|
|
+ <TouchableOpacity onPress={props.onPress}>
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ height: 36,
|
|
|
|
|
+ paddingLeft: 15,
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Text style={{ flex: 1 }}>{props.children}</Text>
|
|
|
|
|
+ <Text style={{ textAlign: 'right', color: '#888', marginRight: 15 }}>
|
|
|
|
|
+ {props.extra}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+// visible用法
|
|
|
|
|
+function BasicDemo() {
|
|
|
|
|
+ const [visible, setVisible] = useState(false)
|
|
|
|
|
+ const [value, setValue] = useState<any[]>([])
|
|
|
|
|
+ const [extend, setExtend] = useState<any>()
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ paddingVertical: 5,
|
|
|
|
|
+ paddingLeft: 16,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ setVisible(true)
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 选择
|
|
|
|
|
+ </Button>
|
|
|
|
|
+
|
|
|
|
|
+ {/* extend渲染所选值 */}
|
|
|
|
|
+ <Text>
|
|
|
|
|
+ {extend?.items?.map((item: any) => item.label).join(',') || ' 未选择'}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+
|
|
|
|
|
+ {/* visible控制显示/隐藏 */}
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ data={district}
|
|
|
|
|
+ cols={3}
|
|
|
|
|
+ onChange={setValue}
|
|
|
|
|
+ onVisibleChange={(v) => {
|
|
|
|
|
+ setVisible(v)
|
|
|
|
|
+ }}
|
|
|
|
|
+ visible={visible}
|
|
|
|
|
+ value={value}
|
|
|
|
|
+ onOk={(v: PickerValue[], ext: PickerValueExtend) => {
|
|
|
|
|
+ setValue(v)
|
|
|
|
|
+ setExtend(ext)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default class PopupExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ data: [],
|
|
|
|
|
+ value: [],
|
|
|
|
|
+ pickerValue: [],
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ onPress = () => {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ data: district,
|
|
|
|
|
+ })
|
|
|
|
|
+ }, 500)
|
|
|
|
|
+ }
|
|
|
|
|
+ onChange = (value: any) => {
|
|
|
|
|
+ this.setState({ value })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <List renderHeader={'List Children'}>
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ data={district}
|
|
|
|
|
+ cols={3}
|
|
|
|
|
+ value={this.state.value}
|
|
|
|
|
+ onChange={this.onChange}>
|
|
|
|
|
+ <List.Item arrow="horizontal">省市选择</List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ data={this.state.data}
|
|
|
|
|
+ cols={2}
|
|
|
|
|
+ value={this.state.value}
|
|
|
|
|
+ onChange={this.onChange}>
|
|
|
|
|
+ <List.Item arrow="horizontal" onPress={this.onPress}>
|
|
|
|
|
+ 省市选择(异步加载)
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ title="选择地区"
|
|
|
|
|
+ data={district}
|
|
|
|
|
+ cols={2}
|
|
|
|
|
+ value={this.state.pickerValue}
|
|
|
|
|
+ onChange={(v: any) => this.setState({ pickerValue: v })}
|
|
|
|
|
+ onOk={(v: any) => this.setState({ pickerValue: v })}>
|
|
|
|
|
+ <CustomChildren>Customized children</CustomChildren>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'visible 控制显示/隐藏'}>
|
|
|
|
|
+ <BasicDemo />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Props
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+type PickerColumnItem = {
|
|
|
|
|
+ label: string | ReactNode
|
|
|
|
|
+ value: string | number
|
|
|
|
|
+ key?: string | number
|
|
|
|
|
+ children?: PickerColumnItem[]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+type PickerColumn = PickerColumnItem[]
|
|
|
|
|
+
|
|
|
|
|
+type PickerValue = string | number
|
|
|
|
|
+
|
|
|
|
|
+type PickerValueExtend = {
|
|
|
|
|
+ columns: PickerColumn[]
|
|
|
|
|
+ items: (PickerColumnItem | undefined)[]
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|--------|--------
|
|
|
|
|
+| data | data source | `PickerColumn` / `PickerColumn[]` | - | |
|
|
|
|
|
+| value | Selected options | `PickerValue[]` | - | |
|
|
|
|
|
+| defaultValue | Default selected options | `PickerValue[]` | - | |
|
|
|
|
|
+| cascade | whether cascade <br/>child cascade get from `data[].children` | Boolean | `true` | |
|
|
|
|
|
+| cols | col numbers | Number | `3` | |
|
|
|
|
|
+| onChange | selected callback function, can use [Form](/components/form) | `(value: PickerValue[], extend: PickerValueExtend) => void` | - | |
|
|
|
|
|
+| onPickerChange | trigger on each column of selected data is changed | `(value: PickerValue[], index: number) => void` | - | |
|
|
|
|
|
+| onVisibleChange | visible state change callback | `(visible: bool): void` | - | |
|
|
|
|
|
+| renderLabel | The function to custom rendering the label shown on a column | `(item: PickerColumnItem, itemIndex: number, colIndex: number) => ReactNode` | `(item) => item.label` | `5.2.2` |
|
|
|
|
|
+| locale | international, can override the configuration of the global [Provider](/components/provider)'s `locale` | Object: Object: {okText, dismissText, extra} | - | |
|
|
|
|
|
+| title | title | ReactNode | - | |
|
|
|
|
|
+| okText | ok text | String | `确定` | |
|
|
|
|
|
+| dismissText | dismiss text | String | `取消` | |
|
|
|
|
|
+| onOk | handler called when click ok | `(value: PickerValue[], extend: PickerValueExtend) => void` | - | |
|
|
|
|
|
+| onDismiss | handler called when click cancel | (): void | - | |
|
|
|
|
|
+| okButtonProps | The ok button props | [TouchableHighlightProps](https://reactnative.dev/docs/touchablehighlight) | `{ activeOpacity:1, underlayColor:'#ddd' }` | `5.1.3` |
|
|
|
|
|
+| dismissButtonProps | The dismiss button props | [TouchableHighlightProps](https://reactnative.dev/docs/touchablehighlight) | `{ activeOpacity:1, underlayColor:'#ddd' }` | `5.1.3` |
|
|
|
|
|
+| visible | Whether to show or hide the Picker | Boolean | - | |
|
|
|
|
|
+| loading | Should the Picker displays as loading state | Boolean | - | `5.1.0` |
|
|
|
|
|
+| loadingContent | The loading content displayed in loading state | ReactNode | - | `5.1.0` |
|
|
|
|
|
+| indicatorStyle | style of default Indicator | Object | - | |
|
|
|
|
|
+
|
|
|
|
|
+### Custom Style
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|---------|---------
|
|
|
|
|
+| style | style | `StyleProp<ViewStyle>` | - | |
|
|
|
|
|
+| styles | inner component styles | [PickerStyle](#pickerstyle-interface) & [PickerViewStyle](/components/picker-view/#pickerviewstyle-interface) | - | `5.1.0`refactored |
|
|
|
|
|
+| itemStyle| style to apply to each of the item labels | `StyleProp<TextStyle>` | - | |
|
|
|
|
|
+| itemHeight | Height of option item, calculated by `numberOfLines` when without value; `itemStyle` was not allowed to set `{height}` | Number | - | |
|
|
|
|
|
+| numberOfLines | Used to truncate the text with an ellipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number | Number | `1` | |
|
|
|
|
|
+
|
|
|
|
|
+### PickerStyle interface
|
|
|
|
|
+```jsx
|
|
|
|
|
+interface PickerStyle extends Partial<PickerViewStyle> {
|
|
|
|
|
+ // modal style
|
|
|
|
|
+ modal: ViewStyle
|
|
|
|
|
+ container: ViewStyle
|
|
|
|
|
+ header: ViewStyle
|
|
|
|
|
+ headerItem: ViewStyle
|
|
|
|
|
+ actionText: TextStyle
|
|
|
|
|
+ title: TextStyle
|
|
|
|
|
+ okText: TextStyle
|
|
|
|
|
+ dismissText: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Mask View
|
|
|
|
|
+
|
|
|
|
|
+New in `5.1.0`. Support custom mask style, such as using the gradient component `<LinearGradient />`. Default is white translucency.
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| renderMaskTop | The function to custom rendering the mask top half view | `()=> ReactNode` | `<View style={{ flex: 1, opacity:0.8, backgroundColor: theme.fill_base }} />` |
|
|
|
|
|
+| renderMaskBottom | The function to custom rendering the mask bottom half view | `()=> ReactNode` | `<View style={{ flex: 1, opacity:0.8, backgroundColor: theme.fill_base }} />` |
|
|
|
|
|
+
|
|
|
|
|
+- Theme color [theme.fill_base](https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/style/themes/default.tsx#L24) = `#ffffff`
|
|
|
|
|
+
|
|
|
|
|
+### Custom Children
|
|
|
|
|
+Picker's children is best to [List.Item](/components/list/#List.Item), if not, need to be a custom component (the `onPress`/`extra` props need to be handled in the component):
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+-----------|------------|------|--------|--------
|
|
|
|
|
+| children| usually `List.Item` | `ReactNode`/`({disabled, extra, value, toggle})=>ReactNode` | - | `5.2.1` add function as Children |
|
|
|
|
|
+| extra | Picker's children `extra` prop, display when no `value`(Similar to a placeholder) | String | `please select` | |
|
|
|
|
|
+| format | a function that formats the selected value | (labels: string[]): any | `(labels) => { return labels.join(','); } ` | |
|
|
|
|
|
+| triggerType | Press event name | String | `onPress` | |
|
|
|
|
|
+| disabled | set disabled | Boolean | `false` | |
|
|
|
|
|
+
|
|
|
|
|
+### PickerActions
|
|
|
|
|
+Properties | Descrition | Type
|
|
|
|
|
+-----------|------------|-----
|
|
|
|
|
+| close | Close Picker | `() => void` |
|
|
|
|
|
+| open | Open Picker | `() => void` |
|
|
|
|
|
+| toggle | Toggle the visible state of Picker | `() => void` |
|
|
|
|
|
+
|
|
|
|
|
+### Ref
|
|
|
|
|
+Same as PickerActions
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### Why is the Picker hidden when it popup in the native Modal?
|
|
|
|
|
+
|
|
|
|
|
+By default, `<Picker />` is dynamically inserted into the `<Provider>` root node via `Portal.add`, and the zIndex level of the native Modal is above everything, including its root node.
|
|
|
|
|
+
|
|
|
|
|
+So if you must use the `<Picker />` component in the native Modal, you can set `modalType='modal'` to keep it at the same level as the native Modal.
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {Modal} from 'react-native';
|
|
|
|
|
+import {Picker} from '@ant-design/react-native';
|
|
|
|
|
+
|
|
|
|
|
+<Modal>
|
|
|
|
|
+ ...
|
|
|
|
|
+
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ modalType="modal" // add here
|
|
|
|
|
+ visible={visible}
|
|
|
|
|
+ data={data}>
|
|
|
|
|
+ <List.Item arrow="horizontal">省市选择</List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+
|
|
|
|
|
+</Modal>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## PickerView
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/picker-view.md
|
|
|
|
|
+
|
|
|
|
|
+# PickerView
|
|
|
|
|
+
|
|
|
|
|
+PickerView's functions like Picker, but it is rendered directly in the area instead of the pop-up window.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List, PickerView } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const basicColumns = [
|
|
|
|
|
+ [
|
|
|
|
|
+ { label: '周一', value: 'Mon' },
|
|
|
|
|
+ { label: '周二', value: 'Tues' },
|
|
|
|
|
+ { label: '周三', value: 'Wed' },
|
|
|
|
|
+ { label: '周四', value: 'Thur' },
|
|
|
|
|
+ { label: '周五', value: 'Fri' },
|
|
|
|
|
+ ],
|
|
|
|
|
+ [
|
|
|
|
|
+ { label: '上午', value: 'am' },
|
|
|
|
|
+ { label: '下午', value: 'pm' },
|
|
|
|
|
+ ],
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+export default class PickerViewExample extends React.Component {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ value: undefined,
|
|
|
|
|
+ }
|
|
|
|
|
+ onChange = (value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ nestedScrollEnabled // 🚩 Enables nested scrolling for Android API level 21+. Nested scrolling is supported by default on iOS.
|
|
|
|
|
+ >
|
|
|
|
|
+ <List renderHeader={'基础用法'}>
|
|
|
|
|
+ <PickerView data={basicColumns} cascade={false} />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'自定义高度'}>
|
|
|
|
|
+ <PickerView
|
|
|
|
|
+ data={basicColumns}
|
|
|
|
|
+ cascade={false}
|
|
|
|
|
+ style={{ height: 450 }}
|
|
|
|
|
+ itemHeight={55}
|
|
|
|
|
+ itemStyle={{
|
|
|
|
|
+ padding: 0,
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'受控模式'}>
|
|
|
|
|
+ <PickerView
|
|
|
|
|
+ onChange={this.onChange}
|
|
|
|
|
+ value={this.state.value}
|
|
|
|
|
+ data={basicColumns}
|
|
|
|
|
+ cascade={false}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Props
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|---------|---------
|
|
|
|
|
+| data | data source | `PickerColumn` / `PickerColumn[]` | - | |
|
|
|
|
|
+| value | Selected options | `PickerValue[]` | - | |
|
|
|
|
|
+| defaultValue | Default selected options | `PickerValue[]` | - | |
|
|
|
|
|
+| cascade | whether cascade <br/>child cascade get from `data[].children` | Boolean | `true` | |
|
|
|
|
|
+| cols | col numbers | Number | `3` | |
|
|
|
|
|
+| onChange | selected callback function, can use [Form](/components/form) | `(value: PickerValue[], extend: PickerValueExtend) => void` | - | |
|
|
|
|
|
+| renderLabel | The function to custom rendering the label shown on a column | `(item: PickerColumnItem, itemIndex: number, colIndex: number) => ReactNode` | `(item) => item.label` | `5.2.2` |
|
|
|
|
|
+| loading | Should the Picker displays as loading state | Boolean | - | `5.1.0` |
|
|
|
|
|
+| loadingContent | The loading content displayed in loading state | ReactNode | `<ActivityIndicator/>` | `5.1.0` |
|
|
|
|
|
+| indicatorStyle | style of default Indicator | Object | - | |
|
|
|
|
|
+
|
|
|
|
|
+For the type definition of `PickerColumnItem` `PickerColumn` `PickerValue` `PickerValueExtend`, please refer to the document of [Picker](/components/picker/).
|
|
|
|
|
+
|
|
|
|
|
+### Custom Style
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Version
|
|
|
|
|
+-----------|------------|------|---------|---------
|
|
|
|
|
+| style | style | `StyleProp<ViewStyle>` | - | |
|
|
|
|
|
+| styles | Semantic DOM style | [PickerViewStyle](#pickerviewstyle-interface) | - | `5.1.0`refactored |
|
|
|
|
|
+| itemStyle| style to apply to each of the item labels | `StyleProp<TextStyle>` | - | |
|
|
|
|
|
+| itemHeight | Height of option item, calculated by `numberOfLines` when without value; `itemStyle` was not allowed to set `{height}` | Number | - | |
|
|
|
|
|
+| numberOfLines | Used to truncate the text with an ellipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number | Number | `1` | |
|
|
|
|
|
+
|
|
|
|
|
+#### PickerViewStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+interface PickerViewStyle {
|
|
|
|
|
+ wrappper: ViewStyle
|
|
|
|
|
+ wheelWrapper: ViewStyle
|
|
|
|
|
+
|
|
|
|
|
+ // item style
|
|
|
|
|
+ itemWrap: ViewStyle
|
|
|
|
|
+ itemStyle: TextStyle
|
|
|
|
|
+ itemActiveStyle: TextStyle // New in `5.2.2`
|
|
|
|
|
+
|
|
|
|
|
+ // mask view
|
|
|
|
|
+ mask: ViewStyle
|
|
|
|
|
+ maskTop: ViewStyle
|
|
|
|
|
+ maskMiddle: ViewStyle
|
|
|
|
|
+ maskBottom: ViewStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### Mask View
|
|
|
|
|
+
|
|
|
|
|
+New in `5.1.0`. Support custom mask style, such as using the gradient component `<LinearGradient />`. Default is white translucency.
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| renderMaskTop | The function to custom rendering the mask top half view | `()=> ReactNode` | `<View style={{ flex: 1, opacity:0.8, backgroundColor: theme.fill_base }} />` |
|
|
|
|
|
+| renderMaskBottom | The function to custom rendering the mask bottom half view | `()=> ReactNode` | `<View style={{ flex: 1, opacity:0.8, backgroundColor: theme.fill_base }} />` |
|
|
|
|
|
+
|
|
|
|
|
+- Theme color [theme.fill_base](https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/style/themes/default.tsx#L24) = `#ffffff`
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### On the Android platform, when using `PickerView` nested in `ScrollView`, the Picker Item cannot slide. What should I do?
|
|
|
|
|
+
|
|
|
|
|
+Support in `5.1.3`. Set the `nestedScrollEnabled` property of `ScrollView` to `true`.
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<ScrollView nestedScrollEnabled={true}>
|
|
|
|
|
+ ...
|
|
|
|
|
+ <PickerView />
|
|
|
|
|
+</ScrollView>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Popover
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/popover.md
|
|
|
|
|
+
|
|
|
|
|
+# Popover
|
|
|
|
|
+
|
|
|
|
|
+> This package has been deprecated in `5.2.1`, recommend [components/Tooltip](/components/tooltip)
|
|
|
|
|
+
|
|
|
|
|
+After clicking on a control or an area, a Popover menu appears for doing more.
|
|
|
|
|
+If set mask prop, it is recommended to exit by clicking on any of the mask layers.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List, Popover } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Easing, StyleSheet, Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const Item = Popover.Item
|
|
|
|
|
+
|
|
|
|
|
+export default class PopoverExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ selected: '',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onSelect = (value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ // visible: false,
|
|
|
|
|
+ selected: value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ let overlay = [1, 2, 3].map((i, index) => (
|
|
|
|
|
+ <Item key={index} value={`option ${i}`}>
|
|
|
|
|
+ <Text>option {i}</Text>
|
|
|
|
|
+ </Item>
|
|
|
|
|
+ ))
|
|
|
|
|
+ overlay = overlay.concat([
|
|
|
|
|
+ <Item key="4" value="disabled" disabled>
|
|
|
|
|
+ <Text style={{ color: '#ddd' }}>disabled opt</Text>
|
|
|
|
|
+ </Item>,
|
|
|
|
|
+ <Item key="6" value="button ct" style={{ backgroundColor: '#efeff4' }}>
|
|
|
|
|
+ <Text>关闭</Text>
|
|
|
|
|
+ </Item>,
|
|
|
|
|
+ ])
|
|
|
|
|
+ return (
|
|
|
|
|
+ <React.Fragment>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ {[1, 2, 3, 4, 5, 6, 7, 8].map((item) =>
|
|
|
|
|
+ this.renderList(overlay, item),
|
|
|
|
|
+ )}
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <Popover
|
|
|
|
|
+ overlay={
|
|
|
|
|
+ <Popover.Item value={'test'}>
|
|
|
|
|
+ <Text>自定义组件 x</Text>
|
|
|
|
|
+ </Popover.Item>
|
|
|
|
|
+ }
|
|
|
|
|
+ renderOverlayComponent={(nodes) => (
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ paddingHorizontal: 9,
|
|
|
|
|
+ paddingTop: 16,
|
|
|
|
|
+ color: '#2b2b2b',
|
|
|
|
|
+ fontWeight: 'bold',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 我是自定义组件title
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ {nodes}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ margin: 16,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 自定义组件
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Popover>
|
|
|
|
|
+ <Popover
|
|
|
|
|
+ overlay={overlay}
|
|
|
|
|
+ useNativeDriver
|
|
|
|
|
+ duration={200}
|
|
|
|
|
+ easing={(show) => (show ? Easing.in(Easing.ease) : Easing.step0)}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ margin: 16,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 自定义动画
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Popover>
|
|
|
|
|
+ <View style={{ alignItems: 'center' }}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ margin: 16,
|
|
|
|
|
+ color: 'red',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 如果你设置了 placement 属性请确保你的内容够位置显示,默认是 auto
|
|
|
|
|
+ 自动计算位置
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ {['left', 'right', 'top', 'bottom'].map((p) => (
|
|
|
|
|
+ <Popover
|
|
|
|
|
+ key={p}
|
|
|
|
|
+ overlay={
|
|
|
|
|
+ <Popover.Item value={p}>
|
|
|
|
|
+ <Text>自定义组件 {p}</Text>
|
|
|
|
|
+ </Popover.Item>
|
|
|
|
|
+ }
|
|
|
|
|
+ placement={p as any}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ margin: 16,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ {p}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Popover>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </React.Fragment>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private renderList(overlay: React.ReactNode[], key: number) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ key={key}
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Popover
|
|
|
|
|
+ overlay={overlay}
|
|
|
|
|
+ triggerStyle={styles.triggerStyle}
|
|
|
|
|
+ onSelect={(v) =>
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ [`selected${key}`]: v,
|
|
|
|
|
+ })
|
|
|
|
|
+ }>
|
|
|
|
|
+ <Text>菜单</Text>
|
|
|
|
|
+ </Popover>
|
|
|
|
|
+ }>
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Text>选择了:{this.state[`selected${key}`]}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const styles = StyleSheet.create({
|
|
|
|
|
+ triggerStyle: {
|
|
|
|
|
+ paddingHorizontal: 6,
|
|
|
|
|
+ },
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+export const title = 'Popover'
|
|
|
|
|
+export const description = 'Popover example'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Popover
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| overlay | Popup layer content | ReactNode | - |
|
|
|
|
|
+| placement | How to position the popover | 'top | right | bottom | left | auto' | auto |
|
|
|
|
|
+| onSelect | when an option is selected | (value: any): void | - |
|
|
|
|
|
+| triggerStyle | trigger style | ViewStyle | - |
|
|
|
|
|
+| renderOverlayComponent | A function that renders takes in the MenuOptions element and renders a container element that contains the options. Default function wraps options with a `ScrollView`. e.g. `(nodes) => <View>{nodes}</View>` | (node: React.ReactNode) => React.ReactNode | - |
|
|
|
|
|
+| duration | Animation duration | number | 300 |
|
|
|
|
|
+| easing | Function that returns easing function for show or hide animation, depending on `show` argument | (show: boolean) => (value: number) => number | show => show ? Easing.out(Easing.back(1.70158)) : Easing.inOut(Easing.quad) |
|
|
|
|
|
+| useNativeDriver | Defines if animations should use native driver | boolean | false |
|
|
|
|
|
+| onDismiss | Callback to be fired after the popup closes | function | - |
|
|
|
|
|
+
|
|
|
|
|
+### Popover.Item
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| disabled | set disabled | Boolean | false |
|
|
|
|
|
+| style | item style | ViewStyle | - |
|
|
|
|
|
+| value | can be used as the selected option ID | any | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Progress
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/progress.md
|
|
|
|
|
+
|
|
|
|
|
+# Progress
|
|
|
|
|
+
|
|
|
|
|
+Progress Bar to indicate your task's progress.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- When you need a accurate progress,otherwise you should use ActivityIndicator.
|
|
|
|
|
+- Hide the unfilled part when used with NavBar for better visual feeling.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Progress, WhiteSpace } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Text, View, ViewStyle } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicProgressExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ percent: 40,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onAdd = () => {
|
|
|
|
|
+ let p = this.state.percent + 10
|
|
|
|
|
+ if (this.state.percent >= 100) {
|
|
|
|
|
+ p = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ this.setState({ percent: p })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const style = {
|
|
|
|
|
+ marginTop: 80,
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ justifyContent: 'space-between',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ }
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Progress percent={90} position="fixed" />
|
|
|
|
|
+
|
|
|
|
|
+ <View style={[style as ViewStyle]}>
|
|
|
|
|
+ <View style={{ marginRight: 10, height: 4, flex: 1 }}>
|
|
|
|
|
+ <Progress percent={this.state.percent} />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Text>{this.state.percent}%</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ style={{ width: 50, marginLeft: 10 }}
|
|
|
|
|
+ type="ghost"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ onPress={this.onAdd}>
|
|
|
|
|
+ (+-)10
|
|
|
|
|
+ </Button>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Progress percent={5} />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+percent | percent value of progress | number | 0
|
|
|
|
|
+position | position of progress bar, optional:`fixed` `normal` | string | `fixed`
|
|
|
|
|
+unfilled | whether to fill unfinished part of progress | boolean | true
|
|
|
|
|
+style | the style of container | object | {}
|
|
|
|
|
+barStyle | the style of bar | object | {}
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Provider
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/provider.md
|
|
|
|
|
+
|
|
|
|
|
+# Provider
|
|
|
|
|
+
|
|
|
|
|
+`Provider` provides a uniform localization support for built-in text of components.
|
|
|
|
|
+
|
|
|
|
|
+## When to use
|
|
|
|
|
+
|
|
|
|
|
+ - You want to use other languages than `Chinese`
|
|
|
|
|
+ - You want to change the default theme color.
|
|
|
|
|
+ - You want to add vibration feedback to built-in component.
|
|
|
|
|
+ - You want to use the `Portal component`.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ DatePicker,
|
|
|
|
|
+ List,
|
|
|
|
|
+ Pagination,
|
|
|
|
|
+ Picker,
|
|
|
|
|
+ Provider,
|
|
|
|
|
+ SearchBar,
|
|
|
|
|
+ WhiteSpace,
|
|
|
|
|
+ WingBlank,
|
|
|
|
|
+} from '@ant-design/react-native'
|
|
|
|
|
+import enUS from '@ant-design/react-native/lib/locale-provider/en_US'
|
|
|
|
|
+import esES from '@ant-design/react-native/lib/locale-provider/es_ES'
|
|
|
|
|
+import faIR from '@ant-design/react-native/lib/locale-provider/fa_IR'
|
|
|
|
|
+import koKR from '@ant-design/react-native/lib/locale-provider/ko_KR'
|
|
|
|
|
+import ptBR from '@ant-design/react-native/lib/locale-provider/pt_BR'
|
|
|
|
|
+import ruRU from '@ant-design/react-native/lib/locale-provider/ru_RU'
|
|
|
|
|
+import svSE from '@ant-design/react-native/lib/locale-provider/sv_SE'
|
|
|
|
|
+import zhCN from '@ant-design/react-native/lib/locale-provider/zh_CN'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const maxDate = new Date(2018, 11, 3, 22, 0)
|
|
|
|
|
+const minDate = new Date(2015, 7, 6, 8, 30)
|
|
|
|
|
+
|
|
|
|
|
+const seasons = [
|
|
|
|
|
+ [
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '2013',
|
|
|
|
|
+ value: '2013',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '2014',
|
|
|
|
|
+ value: '2014',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ [
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '春',
|
|
|
|
|
+ value: '春',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ label: '夏',
|
|
|
|
|
+ value: '夏',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+const Page = React.memo(() => (
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Pagination total={5} current={1} />
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <List style={{ backgroundColor: 'white' }}>
|
|
|
|
|
+ <DatePicker
|
|
|
|
|
+ mode="date"
|
|
|
|
|
+ title="Select date"
|
|
|
|
|
+ minDate={minDate}
|
|
|
|
|
+ maxDate={maxDate}>
|
|
|
|
|
+ <List.Item arrow="horizontal">DatePicker</List.Item>
|
|
|
|
|
+ </DatePicker>
|
|
|
|
|
+ <Picker data={seasons} cascade={false}>
|
|
|
|
|
+ <List.Item arrow="horizontal">Picker</List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <SearchBar placeholder="Search" showCancelButton />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </View>
|
|
|
|
|
+))
|
|
|
|
|
+
|
|
|
|
|
+export default class LocaleProviderExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ locale: 'English',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange = (value: any) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ locale: value[0],
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const { locale } = this.state
|
|
|
|
|
+ const languages: Array<any> = [
|
|
|
|
|
+ {
|
|
|
|
|
+ value: '中国',
|
|
|
|
|
+ label: '中国',
|
|
|
|
|
+ language: zhCN,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 'English',
|
|
|
|
|
+ label: 'English',
|
|
|
|
|
+ language: enUS,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 'Русский',
|
|
|
|
|
+ label: 'Русский',
|
|
|
|
|
+ language: ruRU,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 'Español',
|
|
|
|
|
+ label: 'Español',
|
|
|
|
|
+ language: esES,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 'Português - BR',
|
|
|
|
|
+ label: 'Português - BR',
|
|
|
|
|
+ language: ptBR,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 'Sverige',
|
|
|
|
|
+ label: 'Sverige',
|
|
|
|
|
+ language: svSE,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 'Persian',
|
|
|
|
|
+ label: 'Persian',
|
|
|
|
|
+ language: faIR,
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: '한국',
|
|
|
|
|
+ label: '한국',
|
|
|
|
|
+ language: koKR,
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ const currentLocale = languages.find(
|
|
|
|
|
+ (item) => item.value === locale,
|
|
|
|
|
+ ).language
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider locale={currentLocale}>
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Picker
|
|
|
|
|
+ data={languages}
|
|
|
|
|
+ onChange={this.onChange}
|
|
|
|
|
+ cols={1}
|
|
|
|
|
+ value={[locale]}>
|
|
|
|
|
+ <List.Item arrow="horizontal">Choose language</List.Item>
|
|
|
|
|
+ </Picker>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Page />
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Portal Component
|
|
|
|
|
+
|
|
|
|
|
+`ActionSheet` `Modal` `Picker` `Toast` `ToolTip` belongs to Portal component;
|
|
|
|
|
+
|
|
|
|
|
+To use these components, you must wrap your root component (usually in App.js) with `Provider` component.
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+| Property | Description | Type | Default | Version |
|
|
|
|
|
+| -----|-----|-----|-------|------|
|
|
|
|
|
+| locale | Language package setting(`The default language is Chinese`), <br/>you can find the packages in this path: [`@ant-design/react-native/lib/locale-provider/`](https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/locale-provider) | [Locale](https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/locale-provider/index.tsx#L4) | - | |
|
|
|
|
|
+| theme | Theme customization, you can override some or all variables as needed | [Theme](https://github.com/ant-design/ant-design-mobile-rn/blob/master/components/style/themes/default.tsx) | - | |
|
|
|
|
|
+| onHaptics | Set the vibration engine. This method will be triggered when the built-in component needs vibration feedback. | `(componentName: 'picker' | 'stepper' | 'slider' | 'switch') => void` | - | `5.2.1` |
|
|
|
|
|
+| isRTL | Whether use Right-to-Left (RTL) languages. <br/>Currently only applies to `<SwipeAction/>` | `Boolean` | `I18nManager.isRTL` | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### How do I customize my theme?
|
|
|
|
|
+
|
|
|
|
|
+For example: Modifying the following theme variables has a relatively large impact
|
|
|
|
|
+```jsx
|
|
|
|
|
+<Provider theme={{
|
|
|
|
|
+ brand_primary: palette[5], // Brand base color #108ee9
|
|
|
|
|
+ fill_base: palette[0], // Component default background color #ffffff
|
|
|
|
|
+ primary_button_fill: palette[5], // <Button type="primary"> background color
|
|
|
|
|
+ primary_button_fill_tap: palette[3], // <Button type="primary"> onTap background color
|
|
|
|
|
+ color_icon_base: palette[4], // Background color for many icons
|
|
|
|
|
+}}>
|
|
|
|
|
+...
|
|
|
|
|
+</Provider>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Dark Mode
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "fill_body": "#262629",
|
|
|
|
|
+ "fill_base": "#1a1a1a",
|
|
|
|
|
+ "fill_tap": "#2b2b2b",
|
|
|
|
|
+ "fill_grey": "#0a0a0a",
|
|
|
|
|
+ "color_text_base": "#e6e6e6",
|
|
|
|
|
+ "color_text_placeholder": "#4d4d4d",
|
|
|
|
|
+ "border_color_base": "#2b2b2b",
|
|
|
|
|
+ "border_color_thin": "#2b2b2b",
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### How to activate component vibration?
|
|
|
|
|
+Since the vibration engines of different platforms are different, we expose the vibration events and execute them by the plug-in engine.
|
|
|
|
|
+
|
|
|
|
|
+Usually, the `expo-haptics` engine is used in Expo; the `react-native-haptic-feedback` engine is used in React-Native-CLI;
|
|
|
|
|
+
|
|
|
|
|
+Here we take Expo CLI as an example
|
|
|
|
|
+```jsx
|
|
|
|
|
+import * as Haptics from 'expo-haptics'
|
|
|
|
|
+import { Platform } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+<Provider
|
|
|
|
|
+ onHaptics={() => Platform.OS !== 'web' && Haptics.impactAsync('light')}
|
|
|
|
|
+>
|
|
|
|
|
+...
|
|
|
|
|
+</Provider>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Radio
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/radio.md
|
|
|
|
|
+
|
|
|
|
|
+# Radio
|
|
|
|
|
+
|
|
|
|
|
+Radio.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Flex, List, Radio, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+const RadioItem = Radio.RadioItem
|
|
|
|
|
+
|
|
|
|
|
+type RadioValue = string | number
|
|
|
|
|
+interface EventRadioGroup {
|
|
|
|
|
+ target: { value: RadioValue }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+interface EventRadioItem {
|
|
|
|
|
+ target: { checked: boolean }
|
|
|
|
|
+}
|
|
|
|
|
+export default class BasicRadioExample extends React.Component<any, any> {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ disabled: false,
|
|
|
|
|
+ part1Value: 1,
|
|
|
|
|
+ part2Value: 1,
|
|
|
|
|
+ part3Value: 1,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ toggleDisabled = () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ disabled: !this.state.disabled,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange = (part1Value: any, e: EventRadioItem) => {
|
|
|
|
|
+ if (e.target.checked) {
|
|
|
|
|
+ this.setState({ part1Value })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onGroupChange2 = (e: EventRadioGroup) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ part2Value: e.target.value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onGroupChange3 = (e: EventRadioGroup) => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ part3Value: e.target.value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List renderHeader="基本用法">
|
|
|
|
|
+ <List.Item thumb={<Radio>Radio</Radio>} />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List
|
|
|
|
|
+ renderHeader="不可用"
|
|
|
|
|
+ renderFooter={
|
|
|
|
|
+ <Button type="primary" onPress={this.toggleDisabled}>
|
|
|
|
|
+ Toggle disabled
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ }>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Flex>
|
|
|
|
|
+ <Radio defaultChecked={false} disabled={this.state.disabled}>
|
|
|
|
|
+ Disabled
|
|
|
|
|
+ </Radio>
|
|
|
|
|
+ <WingBlank />
|
|
|
|
|
+ <Radio disabled={this.state.disabled}>Disabled</Radio>
|
|
|
|
|
+ </Flex>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="RadioItem">
|
|
|
|
|
+ <RadioItem
|
|
|
|
|
+ checked={this.state.part1Value === 1}
|
|
|
|
|
+ onChange={this.onChange.bind(this, 1)}>
|
|
|
|
|
+ Use Ant Design Component
|
|
|
|
|
+ </RadioItem>
|
|
|
|
|
+ <RadioItem
|
|
|
|
|
+ checked={this.state.part1Value === 2}
|
|
|
|
|
+ onChange={this.onChange.bind(this, 2)}>
|
|
|
|
|
+ Use Ant Design Component
|
|
|
|
|
+ </RadioItem>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'单选组合 RadioGroup\n一组互斥的 Radio 配合使用'}>
|
|
|
|
|
+ <Radio.Group
|
|
|
|
|
+ onChange={this.onGroupChange2}
|
|
|
|
|
+ value={this.state.part2Value}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ justifyContent: 'space-around',
|
|
|
|
|
+ paddingVertical: 6,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Radio value={1}>A</Radio>
|
|
|
|
|
+ <Radio value={2}>B</Radio>
|
|
|
|
|
+ <Radio value={3}>C</Radio>
|
|
|
|
|
+ <Radio value={4}>D</Radio>
|
|
|
|
|
+ </Radio.Group>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List
|
|
|
|
|
+ renderHeader={
|
|
|
|
|
+ 'Radio.Group 垂直\n垂直的 Radio.Group,配合更多输入框选项'
|
|
|
|
|
+ }>
|
|
|
|
|
+ <Radio.Group
|
|
|
|
|
+ onChange={this.onGroupChange3}
|
|
|
|
|
+ value={this.state.part3Value}>
|
|
|
|
|
+ <RadioItem value={1}>Option A</RadioItem>
|
|
|
|
|
+ <RadioItem value={2}>Option B</RadioItem>
|
|
|
|
|
+ <RadioItem value={3}>Option C</RadioItem>
|
|
|
|
|
+ <RadioItem value={4} left>
|
|
|
|
|
+ More...
|
|
|
|
|
+ </RadioItem>
|
|
|
|
|
+ </Radio.Group>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List
|
|
|
|
|
+ renderHeader={
|
|
|
|
|
+ 'Radio.Group 组合 - 配置方式\n可通过配置 options 参数来渲染单选框。'
|
|
|
|
|
+ }>
|
|
|
|
|
+ <RadioGroupExample />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const plainOptions = ['Apple', 'Pear', 'Orange']
|
|
|
|
|
+const options = [
|
|
|
|
|
+ { label: 'Apple', value: 'Apple' },
|
|
|
|
|
+ { label: 'Pear', value: 'Pear' },
|
|
|
|
|
+ { label: 'Orange', value: 'Orange' },
|
|
|
|
|
+]
|
|
|
|
|
+const optionsWithDisabled = [
|
|
|
|
|
+ { label: 'Apple', value: 'Apple' },
|
|
|
|
|
+ { label: 'Pear', value: 'Pear' },
|
|
|
|
|
+ { label: 'Orange', value: 'Orange', disabled: true },
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+class RadioGroupExample extends React.Component {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ value1: 'Apple',
|
|
|
|
|
+ value2: 'Apple',
|
|
|
|
|
+ value3: 'Apple',
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange1 = (e: EventRadioGroup) => {
|
|
|
|
|
+ console.log('radio1 checked', e.target.value)
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value1: e.target.value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange2 = (e: EventRadioGroup) => {
|
|
|
|
|
+ console.log('radio2 checked', e.target.value)
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value2: e.target.value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange3 = (e: EventRadioGroup) => {
|
|
|
|
|
+ console.log('radio3 checked', e.target.value)
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ value3: e.target.value,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const { value1, value2, value3 } = this.state
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <List renderHeader="PlainOptions">
|
|
|
|
|
+ <Radio.Group
|
|
|
|
|
+ options={plainOptions}
|
|
|
|
|
+ onChange={this.onChange1}
|
|
|
|
|
+ value={value1}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="Options">
|
|
|
|
|
+ <Radio.Group
|
|
|
|
|
+ options={options}
|
|
|
|
|
+ onChange={this.onChange2}
|
|
|
|
|
+ value={value2}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="OptionsWithDisabled">
|
|
|
|
|
+ <Radio.Group
|
|
|
|
|
+ options={optionsWithDisabled}
|
|
|
|
|
+ onChange={this.onChange3}
|
|
|
|
|
+ value={value3}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Type
|
|
|
|
|
+```ts
|
|
|
|
|
+type RadioValue = string | number
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Radio
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| defaultChecked | the initial checked state | Boolean | - |
|
|
|
|
|
+| checked | to set the current checked state | Boolean | - |
|
|
|
|
|
+| disabled | whether disabled | Boolean | false |
|
|
|
|
|
+| onChange | a callback function, can be executed when the checked state changes | (e: { target: { checked: boolean } }) => void | - |
|
|
|
|
|
+| value | Value is carrying identification, used in `Group` mode | `RadioValue` | - |
|
|
|
|
|
+
|
|
|
|
|
+### Radio.RadioItem
|
|
|
|
|
+
|
|
|
|
|
+The encapsulation about `Radio` based on `List.Item`, the property `extra` of `List.Item` will be passed to `Radio`, while other properties remain the same.
|
|
|
|
|
+
|
|
|
|
|
+Other APIs are identical with `Radio`.
|
|
|
|
|
+
|
|
|
|
|
+### Radio.Group `v5.0.0`
|
|
|
|
|
+
|
|
|
|
|
+Radio group can wrap a group of `Radio`。
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+type Event = { target: { value: RadioValue } }
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+----|-----|------|------
|
|
|
|
|
+| defaultValue | Default selected value | `RadioValue` | - |
|
|
|
|
|
+| disabled | Disable all radio buttons | Boolean | false |
|
|
|
|
|
+| options | Set children optional | `string[]` \| `number[]` \| `Array<{ label: string value: string disabled?: boolean }>` | - |
|
|
|
|
|
+| value | Used for setting the currently selected value | `RadioValue` | - |
|
|
|
|
|
+| onChange | The callback function that is triggered when the state changes | (e: `Event`) => void | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Result
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/result.md
|
|
|
|
|
+
|
|
|
|
|
+# Result
|
|
|
|
|
+
|
|
|
|
|
+Result page contains feedback like illustrations, icons and text.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Use for significant feedback like payment success or network failure.
|
|
|
|
|
+- Improve brand value with beautiful illustrations.
|
|
|
|
|
+- Provide obvious operation point for error type result page, eg: reload page.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Result } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Image, ScrollView, Text } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class ResultExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView style={{ backgroundColor: '#F5F5F9', flex: 1 }}>
|
|
|
|
|
+ <Text style={{ margin: 10, color: '#999' }}>URI 图片</Text>
|
|
|
|
|
+ <Result
|
|
|
|
|
+ imgUrl={{
|
|
|
|
|
+ uri: 'https://zos.alipayobjects.com/rmsportal/GcBguhrOdlYvGfnsXgrE.png',
|
|
|
|
|
+ }}
|
|
|
|
|
+ title="验证成功"
|
|
|
|
|
+ message="所提交内容已成功完成验证"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 10, color: '#999' }}>Image source</Text>
|
|
|
|
|
+ <Result
|
|
|
|
|
+ imgUrl={require('./alipay.png')}
|
|
|
|
|
+ title="验证成功"
|
|
|
|
|
+ message="所提交内容已成功完成验证"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 10, color: '#999' }}>Image element</Text>
|
|
|
|
|
+ <Result
|
|
|
|
|
+ img={
|
|
|
|
|
+ <Image
|
|
|
|
|
+ source={require('./alipay.png')}
|
|
|
|
|
+ style={{ width: 60, height: 60 }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }
|
|
|
|
|
+ title="验证成功"
|
|
|
|
|
+ message={<Text>所提交内容已成功完成验证</Text>}
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <Text style={{ margin: 10, color: '#999' }}>含 button 操作</Text>
|
|
|
|
|
+ <Result
|
|
|
|
|
+ img={
|
|
|
|
|
+ <Image
|
|
|
|
|
+ source={require('./alipay.png')}
|
|
|
|
|
+ style={{ width: 60, height: 60 }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }
|
|
|
|
|
+ title="验证成功"
|
|
|
|
|
+ message="所提交内容已成功完成验证"
|
|
|
|
|
+ buttonText="完成"
|
|
|
|
|
+ buttonType="primary"
|
|
|
|
|
+ onButtonClick={(e: any) => alert(e.toString())}
|
|
|
|
|
+ />
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+imgUrl | image url | string / Image Source(rn) | -
|
|
|
|
|
+img | image node (could be `<img src="" />` or `<Icon type="" />`), which will override `imgUrl` | ReactNode | -
|
|
|
|
|
+title | title of result page | ReactNode | -
|
|
|
|
|
+message | message text of result page | ReactNode | -
|
|
|
|
|
+buttonText | text of built-in button | string | -
|
|
|
|
|
+buttonType | type of built-in button | string | -
|
|
|
|
|
+onButtonClick | callback of clicking built-in button | (e: Object): void | -
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## SearchBar
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/search-bar.md
|
|
|
|
|
+
|
|
|
|
|
+# SearchBar
|
|
|
|
|
+
|
|
|
|
|
+Normally located below NavBar, the activation status is exited by the Cancel button.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Should fill some text in placeholder to remind the user to enter the relevant content, such as: "双11特卖".
|
|
|
|
|
+- Below the SearchBar, you can provide useful labels copy to help users complete the input directly by clicking, such as: List some of the most recent search keywords.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { SearchBar } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Alert, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class SearchBarDemo extends React.Component<any, any> {
|
|
|
|
|
+ state = {
|
|
|
|
|
+ value: '美食',
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange = (value: any) => {
|
|
|
|
|
+ this.setState({ value })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ clear = () => {
|
|
|
|
|
+ this.setState({ value: '' })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ marginTop: 30 }}>
|
|
|
|
|
+ <SearchBar defaultValue="初始值" placeholder="搜索" />
|
|
|
|
|
+ <SearchBar
|
|
|
|
|
+ value={this.state.value}
|
|
|
|
|
+ placeholder="搜索"
|
|
|
|
|
+ onSubmit={(value: any) => Alert.alert(value)}
|
|
|
|
|
+ onCancel={this.clear}
|
|
|
|
|
+ onChange={this.onChange}
|
|
|
|
|
+ showCancelButton
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| defaultValue | the uncontrolled default value | String | |
|
|
|
|
|
+| value | the controlled current value | String | |
|
|
|
|
|
+| placeholder | placeholder | String | |
|
|
|
|
|
+| onSubmit | submit event (click the enter on the keyboard) | (val: string): void | |
|
|
|
|
|
+| onChange | change event callback | (val: string): void | |
|
|
|
|
|
+| onFocus | focus event callback | (): void | |
|
|
|
|
|
+| onBlur | blur event callback | (): void | |
|
|
|
|
|
+| onCancel | Click the `Cancel` button to trigger (The text of the input box is no longer automatically cleared) | (val: string): void | |
|
|
|
|
|
+| showCancelButton | Whether the `Cancel` button is always displayed | bool | `false` |
|
|
|
|
|
+| cancelText | Customize the text of the `Cancel` button | String | `取消` |
|
|
|
|
|
+| disabled | Set disabled | bool | `false` |
|
|
|
|
|
+
|
|
|
|
|
+Note: RN version more API please refer to [http://facebook.github.io/react-native/docs/textinput.html](http://facebook.github.io/react-native/docs/textinput.html)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## SegmentedControl
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/segmented-control.md
|
|
|
|
|
+
|
|
|
|
|
+# SegmentedControl
|
|
|
|
|
+
|
|
|
|
|
+Deprecated since `5.2.1`.
|
|
|
|
|
+
|
|
|
|
|
+Please use [@react-native-community/segmented-control](https://github.com/react-native-community/segmented-control#usage) instead.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Slider
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/slider.md
|
|
|
|
|
+
|
|
|
|
|
+# Slider
|
|
|
|
|
+
|
|
|
|
|
+A Slider component for selecting particular value in range, eg: controls the display brightness of the screen.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- By default, the minimum value in the left and maximum value in the right of `Slider` .
|
|
|
|
|
+- Generally `Slider` is positioned horizontally.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List, Provider, Slider, Switch, Toast } from '@ant-design/react-native'
|
|
|
|
|
+import React, { useEffect, useState } from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default function StepperExample() {
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ Toast.config({ stackable: false })
|
|
|
|
|
+ }, [])
|
|
|
|
|
+
|
|
|
|
|
+ const [disabledStep, setDisabledStep] = useState(false)
|
|
|
|
|
+ const [tapToSeek, setTapToSeek] = useState(true)
|
|
|
|
|
+ const marks = {
|
|
|
|
|
+ 0: 0,
|
|
|
|
|
+ // 20: 20,
|
|
|
|
|
+ 40: 40,
|
|
|
|
|
+ 60: '',
|
|
|
|
|
+ 80: 80,
|
|
|
|
|
+ 100: 100,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const toastValue = (value: number | [number, number]) => {
|
|
|
|
|
+ let text = ''
|
|
|
|
|
+ if (typeof value === 'number') {
|
|
|
|
|
+ text = `${value}`
|
|
|
|
|
+ } else {
|
|
|
|
|
+ text = `[${value.join(',')}]`
|
|
|
|
|
+ }
|
|
|
|
|
+ Toast.show({ content: `当前选中值为:${text}`, position: 'top' })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checked={disabledStep}
|
|
|
|
|
+ onChange={(val) => {
|
|
|
|
|
+ setDisabledStep(val)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ Disabled Step
|
|
|
|
|
+ <List.Item.Brief>
|
|
|
|
|
+ 是否禁用步距;禁用后`onChange`将返回带有小数点的值
|
|
|
|
|
+ </List.Item.Brief>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checked={tapToSeek}
|
|
|
|
|
+ onChange={(val) => {
|
|
|
|
|
+ setTapToSeek(val)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ Tap To Seek
|
|
|
|
|
+ <List.Item.Brief>
|
|
|
|
|
+ 是否允许点击滑块轨道来设置slider值
|
|
|
|
|
+ </List.Item.Brief>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List
|
|
|
|
|
+ renderHeader={'基础用法'}
|
|
|
|
|
+ onStartShouldSetResponder={() => true}
|
|
|
|
|
+ onTouchStart={(e) => e.stopPropagation()}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Slider
|
|
|
|
|
+ max={1}
|
|
|
|
|
+ disabledStep={disabledStep}
|
|
|
|
|
+ tapToSeek={tapToSeek}
|
|
|
|
|
+ onChange={toastValue}
|
|
|
|
|
+ onAfterChange={toastValue}
|
|
|
|
|
+ onSlidingStart={(val, index) =>
|
|
|
|
|
+ console.log('onSlidingStart', { val, index })
|
|
|
|
|
+ }
|
|
|
|
|
+ onSlidingComplete={(val, index) =>
|
|
|
|
|
+ console.log('onSlidingComplete', { val, index })
|
|
|
|
|
+ }
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'显示刻度(ticks)并指定步距(step)'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Slider
|
|
|
|
|
+ ticks
|
|
|
|
|
+ step={10}
|
|
|
|
|
+ defaultValue={40}
|
|
|
|
|
+ disabledStep={disabledStep}
|
|
|
|
|
+ tapToSeek={tapToSeek}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'传入刻度标记(marks)'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Slider
|
|
|
|
|
+ marks={marks}
|
|
|
|
|
+ ticks
|
|
|
|
|
+ disabledStep={disabledStep}
|
|
|
|
|
+ tapToSeek={tapToSeek}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'最大(max)/最小值(min)'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Slider
|
|
|
|
|
+ step={100}
|
|
|
|
|
+ min={100}
|
|
|
|
|
+ max={1000}
|
|
|
|
|
+ ticks
|
|
|
|
|
+ onAfterChange={toastValue}
|
|
|
|
|
+ disabledStep={disabledStep}
|
|
|
|
|
+ tapToSeek={tapToSeek}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'双滑块(range)'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Slider
|
|
|
|
|
+ marks={marks}
|
|
|
|
|
+ ticks
|
|
|
|
|
+ range
|
|
|
|
|
+ defaultValue={[60, 40]}
|
|
|
|
|
+ disabledStep={disabledStep}
|
|
|
|
|
+ tapToSeek={tapToSeek}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'在拖动时显示悬浮提示'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Slider popover disabledStep={disabledStep} tapToSeek={tapToSeek} />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Description | Type | Default | Version |
|
|
|
|
|
+| --- | --- | --- | --- | --- |
|
|
|
|
|
+| defaultValue | Default value | `number` \|<br/> `[number, number]` | `range ? [0, 0] : 0` | |
|
|
|
|
|
+| disabled | Whether disabled | `boolean` | `false` | |
|
|
|
|
|
+| disabledStep | Whether disabled step; if `true`, `onChange` will return a value with a decimal point | `boolean` | `false` | `5.3.0` |
|
|
|
|
|
+| icon | The thumb icon of slider | `ReactNode` | - | |
|
|
|
|
|
+| marks | Tick marks | `{ [key: number]: React.ReactNode }` | - | `5.2.1` |
|
|
|
|
|
+| max | Max value | `number` | `100` | |
|
|
|
|
|
+| min | Min value | `number` | `0` | |
|
|
|
|
|
+| onAfterChange | Consistent with the trigger timing of `touchend`, pass the current value as a parameter | `(value: number | [number, number]) => void` | - | |
|
|
|
|
|
+| onChange | Triggered when the slider is dragged, and the current dragged value is passed in as a parameter | `(value: number | [number, number]) => void` | - | |
|
|
|
|
|
+| onSlidingStart | Callback that is called when the user picks up the slider.<br/>The initial value is passed as an argument to the callback handler. | `(value: number | [number, number], index: number) => void` | - | `5.3.0` |
|
|
|
|
|
+| onSlidingComplete | Callback that is called when the user releases the slider, regardless if the value has changed.<br/>The current value is passed as an argument to the callback handler. | `(value: number | [number, number], index: number) => void` | - | `5.3.0` |
|
|
|
|
|
+| popover | Whether to display the popover when dragging. Support passing in function to customize the rendering content. | `boolean | ((value: number) => ReactNode)` | `false` | `5.2.1` |
|
|
|
|
|
+| residentPopover | Whether the `popover` is permanently displayed , this attribute takes effect when `popover` exists | `boolean ` | `false` | `5.2.1` |
|
|
|
|
|
+| range | Whether it is a double sliders | `boolean` | `false` | `5.2.1` |
|
|
|
|
|
+| step | Step distance, the value must be greater than `0`, and `(max-min)` can be divisible by `step`. When `marks` is not null, the configuration of `step` is invalid | `number` | `1` | `5.2.1` |
|
|
|
|
|
+| style | Container style | `StyleProp<ViewStyle>` | - | |
|
|
|
|
|
+| styles | Semantic DOM style | [SliderStyle](#sliderstyle-interface) | - | `5.2.1` |
|
|
|
|
|
+| tapToSeek | Permits tapping on the slider track to set the thumb icon position. | `boolean` | `true` | `5.3.0` |
|
|
|
|
|
+| ticks | Whether to display the scale | `boolean` | `false` | `5.2.1` |
|
|
|
|
|
+| value | Current value | `number` \|<br/> `[number, number]` | - | |
|
|
|
|
|
+
|
|
|
|
|
+> The returned `value` format is `[number, number]` when `range={true}`, otherwise it is `number`.
|
|
|
|
|
+
|
|
|
|
|
+### SliderStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface SliderStyle {
|
|
|
|
|
+ // Same as `style`
|
|
|
|
|
+ slider: ViewStyle // belongs to PanGesture area when `range=false`
|
|
|
|
|
+ disabled: ViewStyle
|
|
|
|
|
+
|
|
|
|
|
+ // Track
|
|
|
|
|
+ trackContianer: ViewStyle // track container
|
|
|
|
|
+ track: ViewStyle // track line
|
|
|
|
|
+ fill: ViewStyle // Filled portion of the track line
|
|
|
|
|
+
|
|
|
|
|
+ // Track button wrap + shadow style
|
|
|
|
|
+ thumb: ViewStyle
|
|
|
|
|
+
|
|
|
|
|
+ // Tick
|
|
|
|
|
+ ticks: ViewStyle
|
|
|
|
|
+ tick: ViewStyle
|
|
|
|
|
+ tickActive: ViewStyle
|
|
|
|
|
+
|
|
|
|
|
+ // Mark within the tick
|
|
|
|
|
+ mark: ViewStyle
|
|
|
|
|
+ markText: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Stepper
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/stepper.md
|
|
|
|
|
+
|
|
|
|
|
+# Stepper
|
|
|
|
|
+
|
|
|
|
|
+`Stepper` can be used to increase or decrease value step by step.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- When you want to make small adjustments to the value, you can use `Stepper`. eg: Adjust the annual return from 4.00% to 4.05%.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List, Provider, Stepper, Toast } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { KeyboardAvoidingView, Platform, ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default function StepperExample() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <KeyboardAvoidingView
|
|
|
|
|
+ behavior="padding"
|
|
|
|
|
+ keyboardVerticalOffset={Platform.OS === 'ios' ? 100 : undefined}>
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List renderHeader={'基础用法'}>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Stepper
|
|
|
|
|
+ defaultValue={1}
|
|
|
|
|
+ onChange={(value) => {
|
|
|
|
|
+ console.log(value)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ 基础用法
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item extra={<Stepper step={10} defaultValue={10} />}>
|
|
|
|
|
+ 步长设置
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item extra={<Stepper min={-5} max={5} />}>
|
|
|
|
|
+ 限制输入范围
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item extra={<Stepper digits={1} />}>
|
|
|
|
|
+ 格式化到一位小数
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Stepper
|
|
|
|
|
+ defaultValue={93}
|
|
|
|
|
+ formatter={(value) => `$ ${value}`}
|
|
|
|
|
+ parser={(text) => parseFloat(text.replace('$', ''))}
|
|
|
|
|
+ onChange={(value) => {
|
|
|
|
|
+ console.log(value, typeof value)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ 自定义格式
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader={'状态/样式'}>
|
|
|
|
|
+ <List.Item extra={<Stepper disabled />}>禁用状态</List.Item>
|
|
|
|
|
+ <List.Item extra={<Stepper readOnly />}>输入框只读状态</List.Item>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Stepper
|
|
|
|
|
+ onFocus={() => {
|
|
|
|
|
+ Toast.info('获得焦点')
|
|
|
|
|
+ }}
|
|
|
|
|
+ onBlur={() => {
|
|
|
|
|
+ Toast.info('失去焦点')
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ 获得/失去焦点
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Stepper
|
|
|
|
|
+ allowEmpty={true}
|
|
|
|
|
+ min={10}
|
|
|
|
|
+ max={20}
|
|
|
|
|
+ onChange={(value) => {
|
|
|
|
|
+ console.log(value)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ 允许清空
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item extra={<Stepper defaultValue={10000} step={10000} />}>
|
|
|
|
|
+ 自定义样式
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <StringModeExample />
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </KeyboardAvoidingView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const StringModeExample = () => {
|
|
|
|
|
+ const [value, setValue] = React.useState('9999999999999999')
|
|
|
|
|
+ return (
|
|
|
|
|
+ <List renderHeader={'stringMode'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Stepper
|
|
|
|
|
+ stringMode
|
|
|
|
|
+ defaultValue="0.000000000000002"
|
|
|
|
|
+ step="0.000000000000001"
|
|
|
|
|
+ onChange={console.log}
|
|
|
|
|
+ style={{ width: '100%' }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List renderHeader={'stringMode control'}>
|
|
|
|
|
+ <List.Item>
|
|
|
|
|
+ <Stepper
|
|
|
|
|
+ stringMode
|
|
|
|
|
+ value={value}
|
|
|
|
|
+ step="13579"
|
|
|
|
|
+ onChange={setValue}
|
|
|
|
|
+ style={{ width: '100%' }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type | Default | Version |
|
|
|
|
|
+| --- | --- | --- | --- | --- |
|
|
|
|
|
+| allowEmpty | Whether to allow empty content. | `boolean` | `false` |
|
|
|
|
|
+| defaultValue | Default value | `number \| null` | `0` |
|
|
|
|
|
+| digits | Format to a fixed number of digits after the decimal point, set to `0` means format to integer. Will use `formatter` as display value when configured | `number` | - | 5.2.1 |
|
|
|
|
|
+| disabled | Whether to disabled Stepper | `boolean` | `false` |
|
|
|
|
|
+| formatter | Format value in input | `(value?: number) => string` | - | 5.2.1 |
|
|
|
|
|
+| inputStyle | TextInput style | `StyleProp<TextStyle>` | - |
|
|
|
|
|
+| max | Max value | `number` | - |
|
|
|
|
|
+| min | Min value | `number` | - |
|
|
|
|
|
+| minusButtonProps | The minus button props | [TouchableHighlightProps](https://reactnative.dev/docs/touchablehighlight) | `{ activeOpacity:1, underlayColor:'#ddd', children: <Text>-</Text>, delayLongPress:500 }` | 5.2.1 |
|
|
|
|
|
+| plusButtonProps | The plus button props | [TouchableHighlightProps](https://reactnative.dev/docs/touchablehighlight) | `{ activeOpacity:1, underlayColor:'#ddd', children: <Text>+</Text>, delayLongPress:500 }` | 5.2.1 |
|
|
|
|
|
+| onChange | Callback when value is changed | `(value: number \| null) => void` | - |
|
|
|
|
|
+| parser | Parse input text into number which should work with `formatter` | `(text: string) => number` | - | 5.2.1 |
|
|
|
|
|
+| step | The value to increase or decrease each time, can be a decimal | `number` | `1` |
|
|
|
|
|
+| stringMode | Set value as string to support high precision decimals. Will set `defaultValue`,`value`, `min`, `max`, `onChange` to `string` type | `boolean` | `false` | 5.2.1 |
|
|
|
|
|
+| styles | Semantic DOM style | [StepperStyle](#stepperstyle-interface) | - | 5.2.1 |
|
|
|
|
|
+| value | Current number, controlled value | `number \| null` | - |
|
|
|
|
|
+
|
|
|
|
|
+ - New in `5.2.1`. In addition, all properties of react-native [TextInput](http://facebook.github.io/react-native/docs/textinput.html) are supported, eg: **`readOnly`** **`onFocus`** **`onBlur`**
|
|
|
|
|
+
|
|
|
|
|
+ - New in `5.2.1`. Support **Long Press To Trigger** increment or decrement; customizable execution timing: `plusButtonProps={{ delayLongPress: 500 }}`.
|
|
|
|
|
+
|
|
|
|
|
+ - When `allowEmpty` is `true`, the `value` parameter of `onChange` may be **`null`**, please pay attention when using it.
|
|
|
|
|
+
|
|
|
|
|
+### StepperStyle interface
|
|
|
|
|
+
|
|
|
|
|
+`5.2.1`refactored the styles
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+export interface StepperStyle extends Partial<InputStyle> {
|
|
|
|
|
+ // extends InputStyle
|
|
|
|
|
+ container: ViewStyle
|
|
|
|
|
+ input: ViewStyle
|
|
|
|
|
+ prefix: ViewStyle // for minus button
|
|
|
|
|
+ suffix: ViewStyle // for plus button
|
|
|
|
|
+
|
|
|
|
|
+ // StepperStyle
|
|
|
|
|
+ inputDisabled: TextStyle
|
|
|
|
|
+ stepWrap: ViewStyle // step button wrap
|
|
|
|
|
+ stepText: TextStyle // step button text
|
|
|
|
|
+ stepDisabled: ViewStyle // step button disabled
|
|
|
|
|
+ disabledStepTextColor: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Ref
|
|
|
|
|
+Same as [component/Input](/components/input#ref)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Steps
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/steps.md
|
|
|
|
|
+
|
|
|
|
|
+# Steps
|
|
|
|
|
+
|
|
|
|
|
+Steps is typically used for displaying the progress of a task, or guiding users through the steps of a complex flow.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Suitable for step-by-step and long-lasting task, e.g. the process of transfer accounts. If the task is continuous and short, such as opening a page, component `Progress` will fit better.
|
|
|
|
|
+- When the task is complicated or has a certain sequence in the series of subtasks, we can decompose it into several steps to make things easier, e.g. register new account.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Icon, Steps, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, Text, View } from 'react-native'
|
|
|
|
|
+const Step = Steps.Step
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicTimelineExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ steps1: [
|
|
|
|
|
+ { title: 'Finished', description: 'This is description' },
|
|
|
|
|
+ { title: 'In Progress', description: 'This is description' },
|
|
|
|
|
+ { title: 'Waiting', description: 'This is description' },
|
|
|
|
|
+ ],
|
|
|
|
|
+ steps2: [
|
|
|
|
|
+ {
|
|
|
|
|
+ title: 'Finished',
|
|
|
|
|
+ description: 'This is description',
|
|
|
|
|
+ status: 'finish',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: 'In Progress',
|
|
|
|
|
+ description: 'This is description',
|
|
|
|
|
+ status: 'process',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: 'Waiting',
|
|
|
|
|
+ description: 'This is description',
|
|
|
|
|
+ status: 'error',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: 'Waiting',
|
|
|
|
|
+ description: 'This is description',
|
|
|
|
|
+ status: 'wait',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ style={{ flex: 1 }}
|
|
|
|
|
+ automaticallyAdjustContentInsets={false}
|
|
|
|
|
+ showsHorizontalScrollIndicator={false}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}>
|
|
|
|
|
+ <View style={{ marginTop: 60 }}>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps size="small" current={1} direction="horizontal">
|
|
|
|
|
+ {this.state.steps1.map((item: any, index: any) => (
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ title={
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Text>title:{item.title}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ status={item.status}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={{ marginTop: 60 }}>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps size="small" current={1}>
|
|
|
|
|
+ {this.state.steps1.map((item: any, index: any) => (
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ title={
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Text>title:{item.title}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ description={
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Text>desc:{item.description}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ status={item.status}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps size="small">
|
|
|
|
|
+ {this.state.steps2.map((item: any, index: any) => (
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ title={item.title}
|
|
|
|
|
+ description={item.description}
|
|
|
|
|
+ status={item.status}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps current={1}>
|
|
|
|
|
+ {this.state.steps1.map((item: any, index: any) => (
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ title={item.title}
|
|
|
|
|
+ description={item.description}
|
|
|
|
|
+ status={item.status}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps>
|
|
|
|
|
+ {this.state.steps2.map((item: any, index: any) => (
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ title={item.title}
|
|
|
|
|
+ description={item.description}
|
|
|
|
|
+ status={item.status}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps current={1}>
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={0}
|
|
|
|
|
+ title="Finished"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="finish"
|
|
|
|
|
+ />
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={1}
|
|
|
|
|
+ title="Progress"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="progress"
|
|
|
|
|
+ />
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={2}
|
|
|
|
|
+ title="Wait"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="wait"
|
|
|
|
|
+ icon={<Icon name="down" size={20} color="white" />}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WingBlank size="lg">
|
|
|
|
|
+ <Steps current={1}>
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={0}
|
|
|
|
|
+ title="Finished"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="finish"
|
|
|
|
|
+ renderIcon={({ starting, waiting, error }) => {
|
|
|
|
|
+ let icon
|
|
|
|
|
+ if (starting) {
|
|
|
|
|
+ icon = <Icon name="home" />
|
|
|
|
|
+ } else if (waiting) {
|
|
|
|
|
+ icon = <Icon name="user" />
|
|
|
|
|
+ } else if (error) {
|
|
|
|
|
+ icon = <Icon name="star" />
|
|
|
|
|
+ }
|
|
|
|
|
+ return icon
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={1}
|
|
|
|
|
+ title="Progress"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="progress"
|
|
|
|
|
+ renderIcon={({ starting, waiting, error }) => {
|
|
|
|
|
+ let icon
|
|
|
|
|
+ if (starting) {
|
|
|
|
|
+ icon = <Icon name="home" />
|
|
|
|
|
+ } else if (waiting) {
|
|
|
|
|
+ icon = <Icon name="user" />
|
|
|
|
|
+ } else if (error) {
|
|
|
|
|
+ icon = <Icon name="star" />
|
|
|
|
|
+ }
|
|
|
|
|
+ return icon
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={2}
|
|
|
|
|
+ title="Wait"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="wait"
|
|
|
|
|
+ renderIcon={({ starting, waiting, error }) => {
|
|
|
|
|
+ let icon
|
|
|
|
|
+ if (starting) {
|
|
|
|
|
+ icon = <Icon name="home" />
|
|
|
|
|
+ } else if (waiting) {
|
|
|
|
|
+ icon = <Icon name="user" />
|
|
|
|
|
+ } else if (error) {
|
|
|
|
|
+ icon = <Icon name="star" />
|
|
|
|
|
+ }
|
|
|
|
|
+ return icon
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Step
|
|
|
|
|
+ key={3}
|
|
|
|
|
+ title="Wait"
|
|
|
|
|
+ description="This is description"
|
|
|
|
|
+ status="error"
|
|
|
|
|
+ renderIcon={({ starting, waiting, error }) => {
|
|
|
|
|
+ let icon
|
|
|
|
|
+ if (starting) {
|
|
|
|
|
+ icon = <Icon name="home" />
|
|
|
|
|
+ } else if (waiting) {
|
|
|
|
|
+ icon = <Icon name="user" />
|
|
|
|
|
+ } else if (error) {
|
|
|
|
|
+ icon = <Icon name="star" />
|
|
|
|
|
+ }
|
|
|
|
|
+ return icon
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Steps>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+<Steps>
|
|
|
|
|
+ <Step title="First" />
|
|
|
|
|
+ <Step title="Second" />
|
|
|
|
|
+ <Step title="Third" />
|
|
|
|
|
+</Steps>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Steps
|
|
|
|
|
+
|
|
|
|
|
+The Steps container.
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default |
|
|
|
|
|
+| ---------- | -------------------------------------------------------------------------------------------------- | --------------------------------- | ---------- |
|
|
|
|
|
+| current | To set the current step, counting from 0. You can overwrite this state by using `status` of `Step` | number | `0` |
|
|
|
|
|
+| size | To specify the size of the step bar, a smaller size can be achieved by setting it to `small` | string | - |
|
|
|
|
|
+| direction | To specify the direction of the step bar(now only support `vertical` for react-native) | Enum { 'vertical', 'horizontal' } | `vertical` |
|
|
|
|
|
+
|
|
|
|
|
+### Steps.Step
|
|
|
|
|
+
|
|
|
|
|
+A single step used as child component of the Step.
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default |
|
|
|
|
|
+| ----------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------- |
|
|
|
|
|
+| status | To specify the status. It will be automatically set by `current` of `Steps` if not configured. | Enum { 'wait', 'process', 'finish', 'error' } | `wait` |
|
|
|
|
|
+| title | Title of the step | React.Element | - |
|
|
|
|
|
+| description | Detail of the step(optional property) | React.Element | - |
|
|
|
|
|
+| icon | Icon of the step(optional property) | object/React.Element | - |
|
|
|
|
|
+| renderIcon | customize step icon(optional) | (params: { starting: boolean; waiting: boolean; error: boolean; }) => React.ReactNode | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## SwipeAction
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/swipe-action.md
|
|
|
|
|
+
|
|
|
|
|
+# SwipeAction
|
|
|
|
|
+
|
|
|
|
|
+iOS-style swipeout buttons that appear from behind a component.
|
|
|
|
|
+
|
|
|
|
|
+### Definition
|
|
|
|
|
+
|
|
|
|
|
+Call out operations from one side of screen with gesture.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+1. Only one row can be swiped at a time.
|
|
|
|
|
+2. Can hide operations by clicking outside of buttons or swiping the list backforwards.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List, SwipeAction } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicSwipeActionExample extends React.Component<any, any> {
|
|
|
|
|
+ asyncFunction = () => {
|
|
|
|
|
+ return new Promise((resolve) => {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ console.log('asd')
|
|
|
|
|
+ resolve(123)
|
|
|
|
|
+ }, 1500)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const right = [
|
|
|
|
|
+ {
|
|
|
|
|
+ text: 'More',
|
|
|
|
|
+ onPress: async () => {
|
|
|
|
|
+ await this.asyncFunction()
|
|
|
|
|
+ },
|
|
|
|
|
+ backgroundColor: 'orange',
|
|
|
|
|
+ color: 'white',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ text: 'Delete',
|
|
|
|
|
+ onPress: () => console.log('delete'),
|
|
|
|
|
+ backgroundColor: 'red',
|
|
|
|
|
+ color: 'white',
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ const left = [
|
|
|
|
|
+ {
|
|
|
|
|
+ text: 'Read',
|
|
|
|
|
+ onPress: () => console.log('read'),
|
|
|
|
|
+ backgroundColor: 'blue',
|
|
|
|
|
+ color: 'white',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ text: 'Reply',
|
|
|
|
|
+ onPress: () => console.log('reply'),
|
|
|
|
|
+ backgroundColor: 'green',
|
|
|
|
|
+ color: 'white',
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ paddingTop: 30 }}>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <SwipeAction
|
|
|
|
|
+ right={right}
|
|
|
|
|
+ left={left}
|
|
|
|
|
+ closeOnAction
|
|
|
|
|
+ closeOnTouchOutside>
|
|
|
|
|
+ <List.Item extra="extra content">
|
|
|
|
|
+ Simple example: left and right buttons
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </SwipeAction>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <SwipeAction
|
|
|
|
|
+ right={right}
|
|
|
|
|
+ left={left}
|
|
|
|
|
+ closeOnAction={false}
|
|
|
|
|
+ closeOnTouchOutside
|
|
|
|
|
+ onSwipeableOpen={() => console.log('open')}
|
|
|
|
|
+ onSwipeableClose={() => console.log('close')}>
|
|
|
|
|
+ <List.Item extra="extra content">
|
|
|
|
|
+ Simple example: left and right buttons
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </SwipeAction>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### SwipeAction
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+|-----|-----|------|-------|------|
|
|
|
|
|
+| closeOnAction | Whether to return to the position automatically when the operation button is clicked | `boolean` | `true` | `5.2.1` |
|
|
|
|
|
+| closeOnTouchOutside | Whether to return to the position automatically when other areas is clicked | `boolean` | `false` | `5.2.1` |
|
|
|
|
|
+| left | List of operation buttons on the left | [SwipeoutButtonProps](/components/swipe-action#swipeoutbuttonprops)[] | `[]` | |
|
|
|
|
|
+| right | List of operation buttons on the right | [SwipeoutButtonProps](/components/swipe-action#swipeoutbuttonprops)[] | `[]` | |
|
|
|
|
|
+| styles | Semantic DOM style | [SwipeActionStyle](/components/swipe-action#swipeactionstyle-interface) | - | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+The rest of the props of `SwipeAction` are exactly the same as [react-native-gesture-handler/Swipeable](https://docs.swmansion.com/react-native-gesture-handler/docs/components/swipeable/),
|
|
|
|
|
+
|
|
|
|
|
+**eg: `onSwipeableOpen` , `onSwipeableClose` , `renderLeftActions` , `renderRightActions`**
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+When you set `renderLeftActions` prop, it will override `left` prop; <br/>
|
|
|
|
|
+when you set `renderRightActions` prop, it will override `right` prop.
|
|
|
|
|
+
|
|
|
|
|
+### SwipeoutButtonProps
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Default | Version |
|
|
|
|
|
+|-----|------|------|------|------|
|
|
|
|
|
+| backgroundColor | background color | `string` | - | |
|
|
|
|
|
+| color | font color | `string` | - | |
|
|
|
|
|
+| disabled | Whether disabled | `boolean` | - | |
|
|
|
|
|
+| onPress | Trigger when clicked | `() => void | Promise<any>` | - | `5.2.1` support async |
|
|
|
|
|
+| style | Aaction button style, effective when `text` is `string` | `StyleProp<TextStyle>` | - | |
|
|
|
|
|
+| text | Text | `string | ReactNode` | - | |
|
|
|
|
|
+| actionButtonProps | Rest props | [RectButtonProps](https://docs.swmansion.com/react-native-gesture-handler/docs/components/buttons/#rectbutton) | - | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+### SwipeActionStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+export interface SwipeActionStyle {
|
|
|
|
|
+ actionButton: ViewStyle
|
|
|
|
|
+ actionText: TextStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Ref
|
|
|
|
|
+
|
|
|
|
|
+New in `5.2.1`. Ref to Swipeable[#Ref](https://docs.swmansion.com/react-native-gesture-handler/docs/components/swipeable/#methods)
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type|
|
|
|
|
|
+|-----|------|------|
|
|
|
|
|
+| close | method that closes component | `() => void` |
|
|
|
|
|
+| openLeft | method that opens component on left side. | `() => void` |
|
|
|
|
|
+| openRight | method that opens component on right side. | `() => void` |
|
|
|
|
|
+| reset | method that resets the swiping states of this `Swipeable` component.<br/>Unlike method `close`, this method does not trigger any animation. | `() => void` |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Switch
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/switch.md
|
|
|
|
|
+
|
|
|
|
|
+# Switch
|
|
|
|
|
+
|
|
|
|
|
+Select between two status, e.g. Select On or Off.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- This is a **controlled component** that requires an `onChange` callback that updates the `checked` prop in order for the component to reflect user actions.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, Icon, List, Switch, WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class SwitchExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ disabled: true,
|
|
|
|
|
+ checked: false,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ toggle = () => {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ disabled: !this.state.disabled,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sleep1s = () => {
|
|
|
|
|
+ return new Promise((resolve) => {
|
|
|
|
|
+ setTimeout(resolve, 1000)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChangeAsync = async (val: boolean) => {
|
|
|
|
|
+ await this.sleep1s()
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ checked: val,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List renderHeader="基本">
|
|
|
|
|
+ <List.Item extra={<Switch />}>最简单的用法</List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="不可用">
|
|
|
|
|
+ <List.Item extra={<Switch disabled={this.state.disabled} />}>
|
|
|
|
|
+ Switch 失效状态
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <Button type="primary" onPress={this.toggle}>
|
|
|
|
|
+ Toggle disabled
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="文字和图标">
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checkedChildren="开"
|
|
|
|
|
+ unCheckedChildren="关"
|
|
|
|
|
+ defaultChecked
|
|
|
|
|
+ />
|
|
|
|
|
+ }
|
|
|
|
|
+ />
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={<Switch checkedChildren="1" unCheckedChildren="0" />}
|
|
|
|
|
+ />
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checkedChildren={<Icon name="check" color="white" />}
|
|
|
|
|
+ unCheckedChildren={<Icon name="close" color="white" />}
|
|
|
|
|
+ defaultChecked
|
|
|
|
|
+ />
|
|
|
|
|
+ }
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="加载中">
|
|
|
|
|
+ <List.Item extra={<Switch checked loading />}>
|
|
|
|
|
+ 标识开关操作仍在执行中
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item extra={<Switch loading />} />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="颜色">
|
|
|
|
|
+ <List.Item extra={<Switch checked color="red" />}>
|
|
|
|
|
+ color="red"
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="异步">
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checked={this.state.checked}
|
|
|
|
|
+ onChange={this.onChangeAsync}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ onChange 返回 Promise
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| checked | Whether is checked by default | Boolean | false |
|
|
|
|
|
+| defaultChecked | Whether to open initially | Boolean | false |
|
|
|
|
|
+| disabled | whether is disabled | Boolean | false |
|
|
|
|
|
+| loading | Loading status | Boolean | false |
|
|
|
|
|
+| onChange | The callback function when changing, when the Promise is returned, the loading status will be displayed automatically | `(val: boolean) => void \| Promise<void>` | - |
|
|
|
|
|
+| color | Background color when the switch is turned on. | String | #4dd865 |
|
|
|
|
|
+| checkedChildren | Selected content | ReactNode | - |
|
|
|
|
|
+| unCheckedChildren | Non-selected content | ReactNode | - |
|
|
|
|
|
+| styles | Semantic DOM style | [SwitchStyle](#switchstyle-interface) | - |
|
|
|
|
|
+
|
|
|
|
|
+### SwitchStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface SwitchStyle {
|
|
|
|
|
+ switch: ViewStyle
|
|
|
|
|
+ switch_inner: ViewStyle
|
|
|
|
|
+ switch_handle: ViewStyle
|
|
|
|
|
+ switch_checked: ViewStyle
|
|
|
|
|
+ switch_unchecked: ViewStyle
|
|
|
|
|
+ switch_inner_checked: ViewStyle
|
|
|
|
|
+ switch_inner_unchecked: ViewStyle
|
|
|
|
|
+ switch_handle_checked: ViewStyle
|
|
|
|
|
+ switch_handle_unchecked: ViewStyle
|
|
|
|
|
+ switch_checked_disabled: ViewStyle
|
|
|
|
|
+ switch_unchecked_disabled: ViewStyle
|
|
|
|
|
+ switch_handle_disabled: ViewStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## TabBar
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/tab-bar.md
|
|
|
|
|
+
|
|
|
|
|
+# TabBar
|
|
|
|
|
+
|
|
|
|
|
+Located at the bottom of the APP, to facilitate users to quickly switch between different functional modules。
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- Used as a class of APP classification, the number of tab between 3-5 is better。
|
|
|
|
|
+- Even if a Tab is not available, do not disable or remove the Tab。
|
|
|
|
|
+- Use Badge make a hint,stay can also know that there is content update。
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Icon, SearchBar, TabBar } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicTabBarExample extends React.Component<any, any> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ selectedTab: 'redTab',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ renderContent(pageText: any) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ flex: 1, alignItems: 'center', backgroundColor: 'white' }}>
|
|
|
|
|
+ <SearchBar placeholder="Search" showCancelButton />
|
|
|
|
|
+ <Text style={{ margin: 50 }}>{pageText}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChangeTab(tabName: any) {
|
|
|
|
|
+ this.setState({
|
|
|
|
|
+ selectedTab: tabName,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <TabBar
|
|
|
|
|
+ unselectedTintColor="#949494"
|
|
|
|
|
+ tintColor="#33A3F4"
|
|
|
|
|
+ barTintColor="#f5f5f5">
|
|
|
|
|
+ <TabBar.Item
|
|
|
|
|
+ title="Life"
|
|
|
|
|
+ icon={<Icon name="home" />}
|
|
|
|
|
+ selected={this.state.selectedTab === 'blueTab'}
|
|
|
|
|
+ onPress={() => this.onChangeTab('blueTab')}>
|
|
|
|
|
+ {this.renderContent('Life Tab')}
|
|
|
|
|
+ </TabBar.Item>
|
|
|
|
|
+ <TabBar.Item
|
|
|
|
|
+ icon={<Icon name="ordered-list" />}
|
|
|
|
|
+ title="Koubei"
|
|
|
|
|
+ badge={2}
|
|
|
|
|
+ selected={this.state.selectedTab === 'redTab'}
|
|
|
|
|
+ onPress={() => this.onChangeTab('redTab')}>
|
|
|
|
|
+ {this.renderContent('Koubei Tab')}
|
|
|
|
|
+ </TabBar.Item>
|
|
|
|
|
+ <TabBar.Item
|
|
|
|
|
+ icon={<Icon name="like" />}
|
|
|
|
|
+ title="Friend"
|
|
|
|
|
+ selected={this.state.selectedTab === 'greenTab'}
|
|
|
|
|
+ onPress={() => this.onChangeTab('greenTab')}>
|
|
|
|
|
+ {this.renderContent('Friend Tab')}
|
|
|
|
|
+ </TabBar.Item>
|
|
|
|
|
+ <TabBar.Item
|
|
|
|
|
+ icon={<Icon name="user" />}
|
|
|
|
|
+ title="My"
|
|
|
|
|
+ selected={this.state.selectedTab === 'yellowTab'}
|
|
|
|
|
+ onPress={() => this.onChangeTab('yellowTab')}>
|
|
|
|
|
+ {this.renderContent('My Tab')}
|
|
|
|
|
+ </TabBar.Item>
|
|
|
|
|
+ </TabBar>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### TabBar
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| barTintColor | tabbar's background color | String | `white` |
|
|
|
|
|
+| tintColor | selected's font color | String | `#108ee9` |
|
|
|
|
|
+| unselectedTintColor | unselected's font color | String | '#888' |
|
|
|
|
|
+| hidden | whether it is hidden | Boolean | false |
|
|
|
|
|
+
|
|
|
|
|
+### TabBar.Item
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| badge | badge number | Number \ String | 无 |
|
|
|
|
|
+| onPress | on press the bar, need change component by yourself. state & selecte={true} | Function | `(){}` |
|
|
|
|
|
+| selected | whether it is selected | Boolean | false |
|
|
|
|
|
+| icon | the default icon | `Image Source | React.ReactNode` | |
|
|
|
|
|
+| selectedIcon | the icon of selected | `Image Source | React.ReactNode` | |
|
|
|
|
|
+| title | title | String | |
|
|
|
|
|
+| key | unique identification | String | 无 |
|
|
|
|
|
+| iconStyle | icon style | String | { width: 28, height: 28 } |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Tabs
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/tabs.md
|
|
|
|
|
+
|
|
|
|
|
+# Tabs
|
|
|
|
|
+
|
|
|
|
|
+A `Tabs` is used to allow users to switch between different views.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+
|
|
|
|
|
+- Generally a `Tabs` should have 2-4 tab pane, the title of each tab pane should be concise,normally has 2-4 words..
|
|
|
|
|
+- In the secondary page of iOS, it is not recommended to use left and right swipe to switch tab, which conflicts with back swipe gestrue in iOS. eg: tabs in details page.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView, Text, TouchableOpacity, View } from 'react-native'
|
|
|
|
|
+import Tabs from '..'
|
|
|
|
|
+
|
|
|
|
|
+const renderContent = (tab: any, index: any) => {
|
|
|
|
|
+ const style = {
|
|
|
|
|
+ paddingVertical: 40,
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ margin: 10,
|
|
|
|
|
+ backgroundColor: '#ddd',
|
|
|
|
|
+ } as any
|
|
|
|
|
+ const content = [1, 2, 3, 4, 5, 6, 7, 8].map((i) => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View key={`${index}_${i}`} style={style}>
|
|
|
|
|
+ <Text>
|
|
|
|
|
+ {tab.title} - {i}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ })
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView key={index} style={{ backgroundColor: '#fff' }}>
|
|
|
|
|
+ {content}
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicTabsExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ const tabs = [
|
|
|
|
|
+ { title: 'First Tab' },
|
|
|
|
|
+ { title: 'Second Tab' },
|
|
|
|
|
+ { title: 'Third Tab' },
|
|
|
|
|
+ ]
|
|
|
|
|
+ const tabs2 = [
|
|
|
|
|
+ { title: '1st Tab' },
|
|
|
|
|
+ { title: '2nd Tab' },
|
|
|
|
|
+ { title: '3rd Tab' },
|
|
|
|
|
+ { title: '4th Tab' },
|
|
|
|
|
+ { title: '5th Tab' },
|
|
|
|
|
+ { title: '6th Tab' },
|
|
|
|
|
+ { title: '7th Tab' },
|
|
|
|
|
+ { title: '8th Tab' },
|
|
|
|
|
+ { title: '9th Tab' },
|
|
|
|
|
+ ]
|
|
|
|
|
+ const style = {
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ height: 150,
|
|
|
|
|
+ backgroundColor: '#fff',
|
|
|
|
|
+ } as any
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ flex: 1 }}>
|
|
|
|
|
+ <Tabs tabs={tabs}>
|
|
|
|
|
+ <View style={style}>
|
|
|
|
|
+ <Text>Content of First Tab</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={style}>
|
|
|
|
|
+ <Text>Content of Second Tab</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={style}>
|
|
|
|
|
+ <Text>Content of Third Tab</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Tabs>
|
|
|
|
|
+ <Text style={{ margin: 16 }}>Custom RenderTabBar</Text>
|
|
|
|
|
+ <Tabs
|
|
|
|
|
+ tabs={tabs}
|
|
|
|
|
+ renderTabBar={(tabProps) => (
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ paddingHorizontal: 16,
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'space-evenly',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ {tabProps.tabs.map((tab, i) => (
|
|
|
|
|
+ // change the style to fit your needs
|
|
|
|
|
+ <TouchableOpacity
|
|
|
|
|
+ activeOpacity={0.9}
|
|
|
|
|
+ key={tab.key || i}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ // width: '30%',
|
|
|
|
|
+ padding: 6,
|
|
|
|
|
+ }}
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ const { goToTab, onTabClick } = tabProps
|
|
|
|
|
+ // tslint:disable-next-line:no-unused-expression
|
|
|
|
|
+ onTabClick && onTabClick(tabs[i], i)
|
|
|
|
|
+ // tslint:disable-next-line:no-unused-expression
|
|
|
|
|
+ goToTab && goToTab(i)
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <Text
|
|
|
|
|
+ style={{
|
|
|
|
|
+ color: tabProps.activeTab === i ? 'green' : '#333333',
|
|
|
|
|
+ }}>
|
|
|
|
|
+ {tab.title}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )}>
|
|
|
|
|
+ <View style={style}>
|
|
|
|
|
+ <Text>Content of First Tab</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={style}>
|
|
|
|
|
+ <Text>Content of Second Tab</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View style={style}>
|
|
|
|
|
+ <Text>Content of Third Tab</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Tabs>
|
|
|
|
|
+ <View style={{ flex: 2 }}>
|
|
|
|
|
+ <Tabs tabs={tabs2} initialPage={1} tabBarPosition="top">
|
|
|
|
|
+ {tabs2.map((tab, index) => renderContent(tab, index))}
|
|
|
|
|
+ </Tabs>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export const title = 'Tabs'
|
|
|
|
|
+export const description = 'Tabs example'
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Tabs
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Required
|
|
|
|
|
+-----------|------------|------|--------|--------
|
|
|
|
|
+tabs | tabs data | Models.TabData[] | | true
|
|
|
|
|
+tabBarPosition | TabBar's position | 'top' \| 'bottom' | top | false
|
|
|
|
|
+renderTabBar | replace the TabBar | ((props: TabBarPropsType) => React.ReactNode) \| false | | false
|
|
|
|
|
+initialPage | the tab when inital, index or key | number \| string | | false
|
|
|
|
|
+page | current tab, index or key | number \| string | | false
|
|
|
|
|
+swipeable | Whether to switch tabs with swipe gestrue in the content | boolean | true | false
|
|
|
|
|
+useOnPan | use hand scroll | boolean | true | false
|
|
|
|
|
+prerenderingSiblingsNumber | pre-render nearby # sibling, Infinity: render all the siblings, 0: render current page. | number | 1 | false
|
|
|
|
|
+animated | Whether to change tabs with animation | boolean | true | false
|
|
|
|
|
+onChange | Callback when tab is switched | (tab: Models.TabData, index: number) => void | | false
|
|
|
|
|
+onTabClick | on tab click | (tab: Models.TabData, index: number) => void | | false
|
|
|
|
|
+destroyInactiveTab | destroy inactive tab | boolean | false | false
|
|
|
|
|
+distanceToChangeTab | distance to change tab, width ratio | number | 0.3 | false
|
|
|
|
|
+usePaged | use paged | boolean | true | false
|
|
|
|
|
+tabBarUnderlineStyle | style of the default tab bar's underline | React.CSSProperties \| any | | false
|
|
|
|
|
+tabBarBackgroundColor | color of the default tab bar's background | string | | false
|
|
|
|
|
+tabBarActiveTextColor | color of the default tab bar's text when active | string | | false
|
|
|
|
|
+tabBarInactiveTextColor | color of the default tab bar's text when inactive | string | | false
|
|
|
|
|
+tabBarTextStyle | tional styles to the tab bar's text | React.CSSProperties \| any | | false
|
|
|
|
|
+renderTab | render for replace the tab of tabbar | (tab: Models.TabData) => React.ReactNode | | false
|
|
|
|
|
+renderUnderline | renderUnderline | (style: any) => React.ReactNode | | false
|
|
|
|
|
+
|
|
|
|
|
+### Tabs.DefaultTabBar
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default | Required
|
|
|
|
|
+-----------|------------|------|--------|--------
|
|
|
|
|
+goToTab | call this function to switch Tab | (index: number) => boolean | | true
|
|
|
|
|
+tabs | tabs data | Models.TabData[] | | true
|
|
|
|
|
+activeTab | current tab | number | | true
|
|
|
|
|
+animated | Whether to change tabs with animation | boolean | | true
|
|
|
|
|
+renderTab | render for replace the tab of tabbar | (tab: Models.TabData) => React.ReactNode | | false
|
|
|
|
|
+page | the size for the tab of tabbar | number | 5 | false
|
|
|
|
|
+onTabClick | on tab click | (tab: Models.TabData, index: number) => void | | false
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Tag
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/tag.md
|
|
|
|
|
+
|
|
|
|
|
+# Tag
|
|
|
|
|
+
|
|
|
|
|
+Tag for categorizing or markuping, can be used to make classification or mark the attributes and dimensions of objects.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- The content should be displayed completely.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Tag, WhiteSpace } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+function onChange(selected: any) {
|
|
|
|
|
+ console.log(`tag selected: ${selected}`)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicTagExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View style={{ padding: 10 }}>
|
|
|
|
|
+ <Tag>Basic</Tag>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Tag selected>Selected</Tag>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Tag disabled>Disabled</Tag>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Tag onChange={onChange}>Callback</Tag>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Tag
|
|
|
|
|
+ closable
|
|
|
|
|
+ onClose={() => {
|
|
|
|
|
+ console.log('onClose')
|
|
|
|
|
+ }}
|
|
|
|
|
+ afterClose={() => {
|
|
|
|
|
+ console.log('afterClose')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ Closable
|
|
|
|
|
+ </Tag>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Tag small>Small and Readonly</Tag>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <Tag
|
|
|
|
|
+ onLongPress={() => {
|
|
|
|
|
+ console.log('onLongPress')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ LongPress
|
|
|
|
|
+ </Tag>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| small | Whether to show a smaller size | Boolean | `false` |
|
|
|
|
|
+| disabled | Whether is disabled | Boolean | `false` |
|
|
|
|
|
+| closable | Whether can be closed(invalid in `small` or `disabled` mode) | Boolean | `false` |
|
|
|
|
|
+| selected | Whether is selected by default | Boolean | `false` |
|
|
|
|
|
+| onChange | The callback function that is triggered when the selected state changes. | (selected: bool): void | - |
|
|
|
|
|
+| onClose | The callback function that is triggered when the tag is closed. | (): void | - |
|
|
|
|
|
+| afterClose | The callback function that is triggered after close. | (): void | - |
|
|
|
|
|
+| onLongPress | The callback function that is triggered when the tag is long pressed. | (): void | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## TextareaItem
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/textarea-item.md
|
|
|
|
|
+
|
|
|
|
|
+# TextareaItem
|
|
|
|
|
+
|
|
|
|
|
+> This package has been deprecated in `5.2.1`, recommend [components/Input.TextArea](/components/input#inputtextarea)
|
|
|
|
|
+
|
|
|
|
|
+A foundational component for inputting multi-line text into the app via a keyboard.
|
|
|
|
|
+
|
|
|
|
|
+### Rule
|
|
|
|
|
+- Support text input via keyboard or clipboard.
|
|
|
|
|
+- The cursor can be moved horizontally.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { List, TextareaItem, Toast } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+export default class BasicTextAreaItemExample extends React.Component<
|
|
|
|
|
+ any,
|
|
|
|
|
+ any
|
|
|
|
|
+> {
|
|
|
|
|
+ constructor(props: any) {
|
|
|
|
|
+ super(props)
|
|
|
|
|
+ this.state = {
|
|
|
|
|
+ val: '默认带value',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onChange = (val: any) => {
|
|
|
|
|
+ // console.log(val);
|
|
|
|
|
+ this.setState({ val })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ style={{ flex: 1 }}
|
|
|
|
|
+ automaticallyAdjustContentInsets={false}
|
|
|
|
|
+ showsHorizontalScrollIndicator={false}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}>
|
|
|
|
|
+ <List renderHeader={'基本'}>
|
|
|
|
|
+ <TextareaItem rows={4} placeholder="固定行数" />
|
|
|
|
|
+
|
|
|
|
|
+ <TextareaItem rows={4} placeholder="多行带计数" count={100} />
|
|
|
|
|
+
|
|
|
|
|
+ <TextareaItem
|
|
|
|
|
+ rows={4}
|
|
|
|
|
+ placeholder="高度自适应"
|
|
|
|
|
+ autoHeight
|
|
|
|
|
+ style={{ paddingVertical: 5 }}
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <TextareaItem value={this.state.val} onChange={this.onChange} />
|
|
|
|
|
+
|
|
|
|
|
+ <TextareaItem value="不可编辑 editable = {false}" editable={false} />
|
|
|
|
|
+
|
|
|
|
|
+ <TextareaItem clear={false} placeholder="不显示清除按钮" />
|
|
|
|
|
+
|
|
|
|
|
+ <TextareaItem
|
|
|
|
|
+ error
|
|
|
|
|
+ defaultValue="报错样式 error={true}"
|
|
|
|
|
+ onErrorClick={() => Toast.fail('Error message')}
|
|
|
|
|
+ />
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| value | the value to show for the textarea (see [react doc](https://facebook.github.io/react/docs/forms.html) for more information about controlled component) | String | |
|
|
|
|
|
+| defaultValue | provides an initial value that will change when the user starts typing. | String | - |
|
|
|
|
|
+| placeholder | the string that will be rendered before text input has been entered. | String | '' |
|
|
|
|
|
+| editable | whether is editable | bool | true |
|
|
|
|
|
+| disabled | whether is disabled | bool | false |
|
|
|
|
|
+| clear | whether to display the clear icon (it takes effect only if `editable` is `true` and `disabled` is `false`) | bool | false |
|
|
|
|
|
+| rows | sets the number of lines for a textarea | number | 1 |
|
|
|
|
|
+| count | it is used for word count and maxlength, the default is 0 which indicates that word count is turned off. | number | - |
|
|
|
|
|
+| onChange | callback that is called when the textarea's text changes. | (val: string): void | - |
|
|
|
|
|
+| error | whether to display error | bool | false |
|
|
|
|
|
+| onErrorClick | callback that is called when the error icon is clicked | (): void | |
|
|
|
|
|
+| autoHeight | auto adjust height (only use one of `autoHeight` and `rows` properties) | bool | false |
|
|
|
|
|
+| labelNumber | number of label text, valid value is 2 to 7 | number | `5` |
|
|
|
|
|
+| last | If it is the last item, the `borderBottom` will be removed, the default has `borderBottom` | bool | false |
|
|
|
|
|
+
|
|
|
|
|
+> More available react-native `TextareaItem` API can be found at [react-native TextInput](http://facebook.github.io/react-native/docs/textinput.html)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Toast
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/toast.md
|
|
|
|
|
+
|
|
|
|
|
+# Toast
|
|
|
|
|
+
|
|
|
|
|
+A lightweight feedback or tips, used to display content that does not interrupt user operations. Suitable for page transitions, data interaction and other scenes.
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+- Toast with Icon, 4-6 words is recommended; Toast without Icon, the number of words should not exceed 14.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { Button, List, Provider, Switch, Toast } from '@ant-design/react-native'
|
|
|
|
|
+import React, { useEffect, useRef, useState } from 'react'
|
|
|
|
|
+import { ActivityIndicator, ScrollView, Text } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const ToastExample = () => {
|
|
|
|
|
+ const handler = useRef<number>()
|
|
|
|
|
+ const [enableMask, setEnableMask] = useState(Toast.getConfig().mask)
|
|
|
|
|
+ const [enableStack, setEnableStack] = useState(Toast.getConfig().stackable)
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <ScrollView>
|
|
|
|
|
+ <List>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checked={enableMask}
|
|
|
|
|
+ onChange={(mask) => {
|
|
|
|
|
+ Toast.config({ mask })
|
|
|
|
|
+ setEnableMask(Toast.getConfig().mask)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ Enable mask
|
|
|
|
|
+ <List.Item.Brief>是否显示透明蒙层,防止触摸穿透</List.Item.Brief>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ <List.Item
|
|
|
|
|
+ extra={
|
|
|
|
|
+ <Switch
|
|
|
|
|
+ checked={enableStack}
|
|
|
|
|
+ onChange={(stackable) => {
|
|
|
|
|
+ Toast.config({ stackable })
|
|
|
|
|
+ setEnableStack(Toast.getConfig().stackable)
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ }>
|
|
|
|
|
+ Enable stackable
|
|
|
|
|
+ <List.Item.Brief>是否允许叠加显示</List.Item.Brief>
|
|
|
|
|
+ </List.Item>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="图标">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.success('Success')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 成功
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.fail('Fail')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 失败
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.offline('Network connection failed !!!')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 网络失败
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.loading('loading...')
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 加载中
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.show({
|
|
|
|
|
+ content: '上传中',
|
|
|
|
|
+ icon: <ActivityIndicator />,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 自定义图标
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="更多功能">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.show({
|
|
|
|
|
+ content: 'Hello World',
|
|
|
|
|
+ position: 'top',
|
|
|
|
|
+ })
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 顶部提示
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.show({
|
|
|
|
|
+ content: 'Hello World',
|
|
|
|
|
+ position: 'bottom',
|
|
|
|
|
+ })
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 底部提示
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.show({
|
|
|
|
|
+ icon: 'loading',
|
|
|
|
|
+ content: <CountDownText />,
|
|
|
|
|
+ duration: 5,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 动态内容
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="手动清除">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ handler.current = Toast.show({
|
|
|
|
|
+ content: '这条提示不会自动消失',
|
|
|
|
|
+ duration: 0,
|
|
|
|
|
+ position: 'top',
|
|
|
|
|
+ mask: false,
|
|
|
|
|
+ })
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 显示
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ handler.current && Toast.remove(handler.current)
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 清除
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ Toast.removeAll()
|
|
|
|
|
+ }}>
|
|
|
|
|
+ 关闭所有
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export default ToastExample
|
|
|
|
|
+
|
|
|
|
|
+const CountDownText = () => {
|
|
|
|
|
+ const [count, setCount] = useState(5)
|
|
|
|
|
+ const interval = useRef<any>()
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ interval.current = setInterval(() => {
|
|
|
|
|
+ setCount((x) => {
|
|
|
|
|
+ if (x > 1) {
|
|
|
|
|
+ return x - 1
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return x
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }, 1000)
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ interval.current && clearInterval(interval.current)
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [])
|
|
|
|
|
+ return <Text style={{ color: '#ffffff' }}>还剩 {count} 秒</Text>
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+`Toast` only supports Imperative calls. The argument type is `string | ToastProps`.
|
|
|
|
|
+
|
|
|
|
|
+- `Toast.show(props)` - New in `5.2.1`
|
|
|
|
|
+- `Toast.success(props)`
|
|
|
|
|
+- `Toast.fail(props)`
|
|
|
|
|
+- `Toast.info(props)`
|
|
|
|
|
+- `Toast.loading(props)`
|
|
|
|
|
+- `Toast.offline(props)`
|
|
|
|
|
+
|
|
|
|
|
+`Toast.show(string)`'s default config is `{duration:1.5, mask: false}`. Another method is to specify a shortcut to the `icon`.
|
|
|
|
|
+
|
|
|
|
|
+ToastProps has these fields:
|
|
|
|
|
+
|
|
|
|
|
+| Properties | Descrition | Type | Required | Default | Version |
|
|
|
|
|
+| ---------- | ---------- | -----| -----------| --------|---------|
|
|
|
|
|
+| content | Toast content | `String | React.ReactNode` | Yes | - | |
|
|
|
|
|
+| duration | Delay time to close, which units is second | number | No | 3 | |
|
|
|
|
|
+| icon | Toast icon | `'success' | 'fail' | 'offline' | 'loading' | React.ReactNode` | No | - | `5.2.1` |
|
|
|
|
|
+| mask | Whether to show a transparent mask, which will prevent touch event of the whole page | Boolean | No | true | |
|
|
|
|
|
+| onClose | A callback function Triggered when the Toast is closed | Function | No | - | |
|
|
|
|
|
+| position | Vertical display position | `'top' | 'bottom' | 'center'` | No | `'center'` | `5.2.1` |
|
|
|
|
|
+| stackable | Whether to allow toast overlay | Boolean | No | true | |
|
|
|
|
|
+| styles | Semantic DOM style | [ToastStyle](#toaststyle-interface) | No | - | `5.2.1` |
|
|
|
|
|
+
|
|
|
|
|
+> **Notice:** OnClose is invalid and Toast does not hide, If set duration = 0, toast will not auto hide, you have to manually do it.
|
|
|
|
|
+
|
|
|
|
|
+```js
|
|
|
|
|
+import { Toast } from '@ant-design/react-native';
|
|
|
|
|
+
|
|
|
|
|
+const key = Toast.loading('message');
|
|
|
|
|
+Toast.remove(key);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Toast.removeAll
|
|
|
|
|
+
|
|
|
|
|
+Turn off `Toast` in all displays.
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+Toast.removeAll()
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Toast.config
|
|
|
|
|
+
|
|
|
|
|
+Methods for global configuration. Support `duration`、`mask`、`onClose`、`position`、`stackable` and `style`. The configuration method is as follows:
|
|
|
|
|
+
|
|
|
|
|
+```ts
|
|
|
|
|
+Toast.config({ duration: 1, position: 'top' })
|
|
|
|
|
+
|
|
|
|
|
+// get current config
|
|
|
|
|
+Toast.getConfig()
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Toast.useToast()
|
|
|
|
|
+
|
|
|
|
|
+New in `5.3.0`. antd-mobile-rn will inserted into the root node of `<Provider>` through `Portal.add` when call toast methods. Whose context is different with origin code located context.
|
|
|
|
|
+<br/>
|
|
|
|
|
+When you need context info (like **Modal** context), you can use `toast.useToast` to get `toastApi` instance and `contextHolder` node. And put it in your children:
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+import { Modal } from 'react-native'
|
|
|
|
|
+import { Toast } from '@ant-design/react-native'
|
|
|
|
|
+
|
|
|
|
|
+const [toastApi, contextHolder] = Toast.useToast();
|
|
|
|
|
+
|
|
|
|
|
+const showLoading = () => {
|
|
|
|
|
+ toastApi.loading(
|
|
|
|
|
+ // ...
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+return (
|
|
|
|
|
+ <Modal>
|
|
|
|
|
+ {contextHolder}
|
|
|
|
|
+ <View>
|
|
|
|
|
+ ...
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </Modal>
|
|
|
|
|
+);
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### InputStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface ToastStyle {
|
|
|
|
|
+ container: ViewStyle
|
|
|
|
|
+ innerContainer: ViewStyle
|
|
|
|
|
+ innerWrap: ViewStyle
|
|
|
|
|
+ iconToast: ViewStyle
|
|
|
|
|
+ textToast: ViewStyle
|
|
|
|
|
+ content: TextStyle
|
|
|
|
|
+ image: TextStyle
|
|
|
|
|
+ centering: ViewStyle
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Tooltip
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/tooltip.md
|
|
|
|
|
+
|
|
|
|
|
+# Tooltip
|
|
|
|
|
+
|
|
|
|
|
+After clicking on a control or an area, a Tooltip menu appears for doing more.
|
|
|
|
|
+If set mask prop, it is recommended to exit by clicking on any of the mask layers.
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import {
|
|
|
|
|
+ Button,
|
|
|
|
|
+ Icon,
|
|
|
|
|
+ List,
|
|
|
|
|
+ Provider,
|
|
|
|
|
+ Toast,
|
|
|
|
|
+ Tooltip,
|
|
|
|
|
+} from '@ant-design/react-native'
|
|
|
|
|
+import React, { useEffect, useState } from 'react'
|
|
|
|
|
+import { ScrollView, Text, View } from 'react-native'
|
|
|
|
|
+import { Action, TooltipProps } from '../PropsType'
|
|
|
|
|
+
|
|
|
|
|
+const actions: Action[] = [
|
|
|
|
|
+ { key: 'scan', icon: <Icon name="scan" />, text: '扫一扫' },
|
|
|
|
|
+ { key: 'payment', icon: <Icon name="pay-circle" />, text: '付钱/收钱' },
|
|
|
|
|
+ { key: 'bus', icon: <Icon name="qrcode" />, text: '乘车码' },
|
|
|
|
|
+ { key: 'assistant', icon: <Icon name="ant-design" />, text: '智能助理' },
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+export default function TooltipExample() {
|
|
|
|
|
+ const [placement, setPlacement] =
|
|
|
|
|
+ useState<TooltipProps['placement']>('top-start')
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ let current = 0
|
|
|
|
|
+
|
|
|
|
|
+ const timer = setInterval(() => {
|
|
|
|
|
+ if (current >= directionList.length - 1) {
|
|
|
|
|
+ current = 0
|
|
|
|
|
+ } else {
|
|
|
|
|
+ current += 1
|
|
|
|
|
+ }
|
|
|
|
|
+ setPlacement(directionList[current])
|
|
|
|
|
+ }, 2000)
|
|
|
|
|
+
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ clearInterval(timer)
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [])
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <Provider>
|
|
|
|
|
+ <ScrollView {...Tooltip.scrollProps}>
|
|
|
|
|
+ <List renderHeader="基本用法">
|
|
|
|
|
+ <Tooltip
|
|
|
|
|
+ content="Hello World"
|
|
|
|
|
+ trigger="onPress"
|
|
|
|
|
+ placement="right"
|
|
|
|
|
+ defaultVisible>
|
|
|
|
|
+ <Button style={{ alignSelf: 'flex-start', margin: 10 }}>
|
|
|
|
|
+ 点我
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="深色气泡">
|
|
|
|
|
+ <Tooltip content="Hello World" placement="bottom" mode="dark" visible>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ style={{ alignSelf: 'flex-start', margin: 10, marginBottom: 30 }}>
|
|
|
|
|
+ 点我
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="气泡位置">
|
|
|
|
|
+ <Tooltip
|
|
|
|
|
+ visible
|
|
|
|
|
+ content={
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <Text>Popover</Text>
|
|
|
|
|
+ <Text>Content</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ }
|
|
|
|
|
+ styles={{ arrow: { borderTopColor: 'yellow' } }}
|
|
|
|
|
+ placement={placement}>
|
|
|
|
|
+ <Button style={{ alignSelf: 'center', margin: 10 }}>
|
|
|
|
|
+ {placement}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="浅色气泡菜单">
|
|
|
|
|
+ <Tooltip.Menu
|
|
|
|
|
+ actions={actions}
|
|
|
|
|
+ placement="bottom-start"
|
|
|
|
|
+ onAction={(node) => Toast.show(`选择了 ${node.text}`)}
|
|
|
|
|
+ trigger="onPress">
|
|
|
|
|
+ <Button style={{ alignSelf: 'flex-start', margin: 10 }}>
|
|
|
|
|
+ 点我
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Tooltip.Menu>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="深色气泡菜单">
|
|
|
|
|
+ <Tooltip.Menu
|
|
|
|
|
+ mode="dark"
|
|
|
|
|
+ actions={actions}
|
|
|
|
|
+ placement="bottom-start"
|
|
|
|
|
+ onAction={(node) => Toast.show(`选择了 ${node.text}`)}
|
|
|
|
|
+ trigger="onPress">
|
|
|
|
|
+ <Button style={{ alignSelf: 'flex-start', margin: 10 }}>
|
|
|
|
|
+ 点我
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Tooltip.Menu>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ <List renderHeader="超过最大数量,隐藏滚动">
|
|
|
|
|
+ <Tooltip.Menu
|
|
|
|
|
+ actions={actions}
|
|
|
|
|
+ maxCount={2}
|
|
|
|
|
+ onAction={(node) => Toast.show(`选择了 ${node.text}`)}
|
|
|
|
|
+ placement="bottom-start"
|
|
|
|
|
+ trigger="onPress">
|
|
|
|
|
+ <Button style={{ alignSelf: 'flex-start', margin: 10 }}>
|
|
|
|
|
+ 点我
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Tooltip.Menu>
|
|
|
|
|
+ </List>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </Provider>
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const directionList = [
|
|
|
|
|
+ 'top-start',
|
|
|
|
|
+ 'top',
|
|
|
|
|
+ 'top-end',
|
|
|
|
|
+ 'right-start',
|
|
|
|
|
+ 'right',
|
|
|
|
|
+ 'right-end',
|
|
|
|
|
+ 'bottom-end',
|
|
|
|
|
+ 'bottom',
|
|
|
|
|
+ 'bottom-start',
|
|
|
|
|
+ 'left-end',
|
|
|
|
|
+ 'left',
|
|
|
|
|
+ 'left-start',
|
|
|
|
|
+] as const
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+### Tooltip
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| children | The element that triggered the Tooltip | `React.ReactElement` | - |
|
|
|
|
|
+| content | The content of the Tooltip | `React.ReactNode` | - |
|
|
|
|
|
+| defaultVisible | Whether to show or hide by default | `boolean` | `false` |
|
|
|
|
|
+| mode | Set bright color mode or black mode | `'light' | 'dark'` | `'light'` |
|
|
|
|
|
+| crossOffset | Set the offset of the pop-up window position; Top: Additional offset applied along the main axis between the element and its triggering element. Left: Additional offset applied along the horizontal axis between the element and its triggering element. | `{ top: number, left: number }` | `'{ top: StatusBar.currentHeight, left: 0 } '` |
|
|
|
|
|
+| onVisibleChange | Callback when the visible prop is changed | `(visible: boolean) => void` | - |
|
|
|
|
|
+| placement | The position of the Tooltip | `'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end'` | `'top'` |
|
|
|
|
|
+| styles | Semantic DOM style | [TooltipStyle](#tooltipstyle-interface) | - |
|
|
|
|
|
+| trigger | Event to trigger | `'onPress'` | - |
|
|
|
|
|
+| visible | Whether to display pop-up content in controlled mode | `boolean` | - |
|
|
|
|
|
+
|
|
|
|
|
+### Ref
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type |
|
|
|
|
|
+| ------- | -------------------------------- | ------------ |
|
|
|
|
|
+| hide | Hide the Tooltip | `() => void` |
|
|
|
|
|
+| show | Show the Tooltip | `() => void` |
|
|
|
|
|
+| visible | Whether the Tooltip is diplaying | `boolean` |
|
|
|
|
|
+
|
|
|
|
|
+## Tooltip.scrollProps
|
|
|
|
|
+
|
|
|
|
|
+While `Tooltip` is inside a `<ScrollView />`, please pread `Tooltip.scrollProps` to the ScrollView,
|
|
|
|
|
+<br/>
|
|
|
|
|
+otherwise it will not follow the scroll
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+import { ScrollView } from 'react-native'
|
|
|
|
|
+import { Tooltip } from '@ant-design/react-native'
|
|
|
|
|
+
|
|
|
|
|
+<ScrollView {...Tooltip.scrollProps}>
|
|
|
|
|
+ <Tooltip>...</Tooltip>
|
|
|
|
|
+<ScrollView>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Tooltip.Menu
|
|
|
|
|
+
|
|
|
|
|
+### Props
|
|
|
|
|
+
|
|
|
|
|
+Except for `content`, all other attributes are inherited from `Tooltip`, the unique attributes are as follows:
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| actions | Menu list, used when the pop-up content is a standard menu | `Action[]` | - |
|
|
|
|
|
+| maxCount | Maximum number of menu lists, if exceeded, hide for scrolling | `number` | - |
|
|
|
|
|
+| onAction | Callback of the selected menum, when the menu list is used | `(item: Action) => void` | - |
|
|
|
|
|
+
|
|
|
|
|
+### Action
|
|
|
|
|
+
|
|
|
|
|
+| Name | Description | Type | Default |
|
|
|
|
|
+| --- | --- | --- | --- |
|
|
|
|
|
+| disabled | Whether disabled | `boolean` | `false` |
|
|
|
|
|
+| icon | The icon of the menu item | `ReactNode` | `null` |
|
|
|
|
|
+| key | The unique identifier of the menu, the default is `index` | `string | number` | `actions` array's `index` |
|
|
|
|
|
+| onPress | Triggered on click | `() => void` | - |
|
|
|
|
|
+| text | Menu list, used when the pop-up content is a standard menu | `ReactNode` | - |
|
|
|
|
|
+
|
|
|
|
|
+### TooltipStyle interface
|
|
|
|
|
+
|
|
|
|
|
+```typescript
|
|
|
|
|
+interface TooltipStyle extends ListItemStyle {
|
|
|
|
|
+ tooltip: ViewStyle
|
|
|
|
|
+ tooltipText: TextStyle
|
|
|
|
|
+ arrow: ViewStyle // `borderTopColor` sets the arrow bg color
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Ref
|
|
|
|
|
+
|
|
|
|
|
+Same as Tooltip.
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### Why can't some children components wrapped by Tooltip be opened onPress?
|
|
|
|
|
+
|
|
|
|
|
+First, Tooltip's children must be `React.ReactElement`, which is a JSX Element rather than a variable.
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+const element = <Button>press</Button>
|
|
|
|
|
+
|
|
|
|
|
+<Tooltip
|
|
|
|
|
+ content="Hello World"
|
|
|
|
|
+ defaultVisible>
|
|
|
|
|
+ {element} // ❌ DO NOT USE
|
|
|
|
|
+ <Button>press</Button> // ✅ YES
|
|
|
|
|
+</Tooltip>
|
|
|
|
|
+```
|
|
|
|
|
+Secondly, the positioning of Tooltip is calculated based on `View.onLayout`, so the children component must support the [onLayout](https://reactnative.dev/docs/view#onlayout) event.
|
|
|
|
|
+
|
|
|
|
|
+```jsx
|
|
|
|
|
+const CustomButton = (props: {
|
|
|
|
|
+ onLayout: (event: LayoutChangeEvent) => void
|
|
|
|
|
+ }) => (
|
|
|
|
|
+ <View onLayout={props.onLayout}>
|
|
|
|
|
+ ...
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+<Tooltip
|
|
|
|
|
+ content="Hello World"
|
|
|
|
|
+ defaultVisible>
|
|
|
|
|
+ <CustomButton>press<CustomButton>
|
|
|
|
|
+</Tooltip>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## View
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/view.md
|
|
|
|
|
+
|
|
|
|
|
+# View
|
|
|
|
|
+
|
|
|
|
|
+Safe View
|
|
|
|
|
+
|
|
|
|
|
+### Rules
|
|
|
|
|
+
|
|
|
|
|
+- Support `string`/`number` ReactNode
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { View } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+
|
|
|
|
|
+export default class SafeViewExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
|
+ height: 100,
|
|
|
|
|
+ padding: 20,
|
|
|
|
|
+ }}>
|
|
|
|
|
+ <View style={{ backgroundColor: 'blue', flex: 0.3 }} />
|
|
|
|
|
+ <View style={{ backgroundColor: 'red', flex: 0.5 }} />
|
|
|
|
|
+ <View>Hello World!</View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| children | child component | `React.ReactNode` \| `React.ReactText` | - |
|
|
|
|
|
+| style | style | `StyleProp<ViewStyle>` \| `StyleProp<TextStyle>` | - |
|
|
|
|
|
+
|
|
|
|
|
+> More available react-native `View` API can be found at [react-native View](http://facebook.github.io/react-native/docs/view.html)
|
|
|
|
|
+
|
|
|
|
|
+## FAQ
|
|
|
|
|
+
|
|
|
|
|
+### What difference between it and React Native's built-in components View and Text?
|
|
|
|
|
+
|
|
|
|
|
+React Native's View does not support `children` of type `string` / `number`.
|
|
|
|
|
+
|
|
|
|
|
+Misinformation will cause crash and no Code Line Numbers
|
|
|
|
|
+
|
|
|
|
|
+**This component can be used to evacuate errors once, giving priority to ensuring that the device does not crash.**
|
|
|
|
|
+
|
|
|
|
|
+Common mistakes:
|
|
|
|
|
+```jsx
|
|
|
|
|
+const length = arr.length;
|
|
|
|
|
+
|
|
|
|
|
+<View>
|
|
|
|
|
+ {length && <Component />}
|
|
|
|
|
+</View>
|
|
|
|
|
+
|
|
|
|
|
+// when length=0, actually render:
|
|
|
|
|
+<View>
|
|
|
|
|
+ 0
|
|
|
|
|
+</View>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Attention, only one layer of protection can be achieved, even `<React.Fragment>` children maked worng type:
|
|
|
|
|
+```jsx
|
|
|
|
|
+import {View} from '@ant-design/react-native'
|
|
|
|
|
+
|
|
|
|
|
+<View>
|
|
|
|
|
+ {/* still crash */}
|
|
|
|
|
+ <React.Fragment>
|
|
|
|
|
+ 0
|
|
|
|
|
+ </React.Fragment>
|
|
|
|
|
+
|
|
|
|
|
+ {/* still crash */}
|
|
|
|
|
+ <>''</>
|
|
|
|
|
+</View>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## WhiteSpace
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/white-space.md
|
|
|
|
|
+
|
|
|
|
|
+# WhiteSpace
|
|
|
|
|
+
|
|
|
|
|
+Layout controls
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { WhiteSpace } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const PlaceHolder = (props: any) => (
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: '#fff',
|
|
|
|
|
+ height: 30,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ }}
|
|
|
|
|
+ {...props}>
|
|
|
|
|
+ <Text style={{ color: '#bbb' }}>Block</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+export default class WhiteSpaceExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WhiteSpace size="xs" />
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="sm" />
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="xl" />
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| size | up and down margins, optional values:`xs`,`sm`,`md`,`lg`,`xl` | string | `md` |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## WingBlank
|
|
|
|
|
+
|
|
|
|
|
+Source: https://rn.mobile.ant.design/components/wing-blank.md
|
|
|
|
|
+
|
|
|
|
|
+# WingBlank
|
|
|
|
|
+
|
|
|
|
|
+Layout controls
|
|
|
|
|
+
|
|
|
|
|
+## Examples
|
|
|
|
|
+
|
|
|
|
|
+```tsx
|
|
|
|
|
+import { WhiteSpace, WingBlank } from '@ant-design/react-native'
|
|
|
|
|
+import React from 'react'
|
|
|
|
|
+import { Text, View } from 'react-native'
|
|
|
|
|
+
|
|
|
|
|
+const PlaceHolder = (props: any) => (
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: '#fff',
|
|
|
|
|
+ height: 30,
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
|
+ }}
|
|
|
|
|
+ {...props}>
|
|
|
|
|
+ <Text style={{ color: '#bbb' }}>Block</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+export default class WingBlankExample extends React.Component<any, any> {
|
|
|
|
|
+ render() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View>
|
|
|
|
|
+ <WhiteSpace />
|
|
|
|
|
+ <WingBlank>
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <WingBlank size="md">
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+
|
|
|
|
|
+ <WhiteSpace size="lg" />
|
|
|
|
|
+ <WingBlank size="sm">
|
|
|
|
|
+ <PlaceHolder />
|
|
|
|
|
+ </WingBlank>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## API
|
|
|
|
|
+
|
|
|
|
|
+Properties | Descrition | Type | Default
|
|
|
|
|
+-----------|------------|------|--------
|
|
|
|
|
+| size | left and right blank space, optional values:`sm`,`md`,`lg` | string | `lg` |
|
|
|
|
|
+
|
|
|
|
|
+---
|