|
|
import React, { useState } from 'react'; |
|
|
import { ScrollView, StyleSheet, View } from 'react-native'; |
|
|
import { |
|
|
Button, |
|
|
Card, |
|
|
Chip, |
|
|
FAB, |
|
|
IconButton, |
|
|
List, |
|
|
ProgressBar, |
|
|
Searchbar, |
|
|
SegmentedButtons, |
|
|
Snackbar, |
|
|
Switch, |
|
|
Text, |
|
|
TextInput, |
|
|
useTheme, |
|
|
} from 'react-native-paper'; |
|
|
|
|
|
export default function PaperDemo() { |
|
|
const theme = useTheme(); |
|
|
const [searchQuery, setSearchQuery] = useState(''); |
|
|
const [text, setText] = useState(''); |
|
|
const [switchValue, setSwitchValue] = useState(false); |
|
|
const [snackbarVisible, setSnackbarVisible] = useState(false); |
|
|
const [segmentedValue, setSegmentedValue] = useState('walk'); |
|
|
const [expanded, setExpanded] = useState(true); |
|
|
|
|
|
return ( |
|
|
<View style={styles.container}> |
|
|
<ScrollView style={styles.scrollView} contentContainerStyle={styles.content}> |
|
|
{/* 标题 */} |
|
|
<Text variant="headlineLarge" style={styles.title}> |
|
|
React Native Paper |
|
|
</Text> |
|
|
<Text variant="bodyMedium" style={styles.subtitle}> |
|
|
Material Design 组件库示例 |
|
|
</Text> |
|
|
|
|
|
{/* 搜索框 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
🔍 搜索框 |
|
|
</Text> |
|
|
<Searchbar |
|
|
placeholder="搜索..." |
|
|
onChangeText={setSearchQuery} |
|
|
value={searchQuery} |
|
|
style={styles.searchbar} |
|
|
/> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 输入框 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
✏️ 输入框 |
|
|
</Text> |
|
|
<TextInput |
|
|
label="标准输入框" |
|
|
value={text} |
|
|
onChangeText={setText} |
|
|
mode="outlined" |
|
|
style={styles.input} |
|
|
/> |
|
|
<TextInput |
|
|
label="扁平输入框" |
|
|
value={text} |
|
|
onChangeText={setText} |
|
|
mode="flat" |
|
|
style={styles.input} |
|
|
/> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 按钮 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
🔘 按钮 |
|
|
</Text> |
|
|
<View style={styles.buttonRow}> |
|
|
<Button mode="contained" onPress={() => setSnackbarVisible(true)}> |
|
|
Contained |
|
|
</Button> |
|
|
<Button mode="outlined" onPress={() => setSnackbarVisible(true)}> |
|
|
Outlined |
|
|
</Button> |
|
|
</View> |
|
|
<View style={styles.buttonRow}> |
|
|
<Button mode="text" onPress={() => setSnackbarVisible(true)}> |
|
|
Text |
|
|
</Button> |
|
|
<Button |
|
|
mode="elevated" |
|
|
onPress={() => setSnackbarVisible(true)} |
|
|
icon="camera" |
|
|
> |
|
|
With Icon |
|
|
</Button> |
|
|
</View> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 分段按钮 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
📊 分段按钮 |
|
|
</Text> |
|
|
<SegmentedButtons |
|
|
value={segmentedValue} |
|
|
onValueChange={setSegmentedValue} |
|
|
buttons={[ |
|
|
{ |
|
|
value: 'walk', |
|
|
label: '步行', |
|
|
icon: 'walk', |
|
|
}, |
|
|
{ |
|
|
value: 'train', |
|
|
label: '火车', |
|
|
icon: 'train', |
|
|
}, |
|
|
{ value: 'drive', label: '驾车', icon: 'car' }, |
|
|
]} |
|
|
/> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 开关和芯片 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
🎛️ 开关和芯片 |
|
|
</Text> |
|
|
<View style={styles.row}> |
|
|
<Text variant="bodyLarge">启用通知</Text> |
|
|
<Switch value={switchValue} onValueChange={setSwitchValue} /> |
|
|
</View> |
|
|
<View style={styles.chipContainer}> |
|
|
<Chip icon="star" onPress={() => {}}> |
|
|
收藏 |
|
|
</Chip> |
|
|
<Chip icon="heart" mode="outlined" onPress={() => {}}> |
|
|
喜欢 |
|
|
</Chip> |
|
|
<Chip |
|
|
icon="close" |
|
|
onPress={() => {}} |
|
|
onClose={() => {}} |
|
|
closeIcon="close-circle" |
|
|
> |
|
|
可关闭 |
|
|
</Chip> |
|
|
</View> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 进度条 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
📈 进度条 |
|
|
</Text> |
|
|
<ProgressBar progress={0.7} style={styles.progressBar} /> |
|
|
<ProgressBar progress={0.5} color={theme.colors.secondary} /> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 列表 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Content> |
|
|
<Text variant="titleMedium" style={styles.sectionTitle}> |
|
|
📋 列表 |
|
|
</Text> |
|
|
<List.Section> |
|
|
<List.Accordion |
|
|
title="可展开列表" |
|
|
left={(props) => <List.Icon {...props} icon="folder" />} |
|
|
expanded={expanded} |
|
|
onPress={() => setExpanded(!expanded)} |
|
|
> |
|
|
<List.Item title="第一项" left={(props) => <List.Icon {...props} icon="file" />} /> |
|
|
<List.Item title="第二项" left={(props) => <List.Icon {...props} icon="file" />} /> |
|
|
</List.Accordion> |
|
|
</List.Section> |
|
|
<List.Item |
|
|
title="带描述的列表项" |
|
|
description="这是一个描述文本" |
|
|
left={(props) => <List.Icon {...props} icon="account" />} |
|
|
right={(props) => <List.Icon {...props} icon="chevron-right" />} |
|
|
/> |
|
|
</Card.Content> |
|
|
</Card> |
|
|
|
|
|
{/* 卡片示例 */} |
|
|
<Card style={styles.card}> |
|
|
<Card.Cover source={{ uri: 'https://picsum.photos/700' }} /> |
|
|
<Card.Title |
|
|
title="卡片标题" |
|
|
subtitle="卡片副标题" |
|
|
left={(props) => <IconButton {...props} icon="image" />} |
|
|
right={(props) => <IconButton {...props} icon="dots-vertical" />} |
|
|
/> |
|
|
<Card.Content> |
|
|
<Text variant="bodyMedium"> |
|
|
这是一个完整的卡片示例,包含封面图片、标题、内容和操作按钮。 |
|
|
</Text> |
|
|
</Card.Content> |
|
|
<Card.Actions> |
|
|
<Button>取消</Button> |
|
|
<Button>确定</Button> |
|
|
</Card.Actions> |
|
|
</Card> |
|
|
|
|
|
{/* 底部留白 */} |
|
|
<View style={styles.bottomSpace} /> |
|
|
</ScrollView> |
|
|
|
|
|
{/* 浮动操作按钮 */} |
|
|
<FAB |
|
|
icon="plus" |
|
|
style={styles.fab} |
|
|
onPress={() => setSnackbarVisible(true)} |
|
|
label="添加" |
|
|
/> |
|
|
|
|
|
{/* 提示条 */} |
|
|
<Snackbar |
|
|
visible={snackbarVisible} |
|
|
onDismiss={() => setSnackbarVisible(false)} |
|
|
duration={3000} |
|
|
action={{ |
|
|
label: '撤销', |
|
|
onPress: () => { |
|
|
// 撤销操作 |
|
|
}, |
|
|
}} |
|
|
> |
|
|
操作成功! |
|
|
</Snackbar> |
|
|
</View> |
|
|
); |
|
|
} |
|
|
|
|
|
const styles = StyleSheet.create({ |
|
|
container: { |
|
|
flex: 1, |
|
|
}, |
|
|
scrollView: { |
|
|
flex: 1, |
|
|
}, |
|
|
content: { |
|
|
padding: 16, |
|
|
}, |
|
|
title: { |
|
|
marginBottom: 8, |
|
|
fontWeight: 'bold', |
|
|
}, |
|
|
subtitle: { |
|
|
marginBottom: 24, |
|
|
opacity: 0.7, |
|
|
}, |
|
|
card: { |
|
|
marginBottom: 16, |
|
|
}, |
|
|
sectionTitle: { |
|
|
marginBottom: 12, |
|
|
fontWeight: '600', |
|
|
}, |
|
|
searchbar: { |
|
|
marginTop: 8, |
|
|
}, |
|
|
input: { |
|
|
marginBottom: 12, |
|
|
}, |
|
|
buttonRow: { |
|
|
flexDirection: 'row', |
|
|
gap: 8, |
|
|
marginBottom: 8, |
|
|
}, |
|
|
row: { |
|
|
flexDirection: 'row', |
|
|
justifyContent: 'space-between', |
|
|
alignItems: 'center', |
|
|
marginBottom: 16, |
|
|
}, |
|
|
chipContainer: { |
|
|
flexDirection: 'row', |
|
|
flexWrap: 'wrap', |
|
|
gap: 8, |
|
|
}, |
|
|
progressBar: { |
|
|
marginBottom: 12, |
|
|
}, |
|
|
bottomSpace: { |
|
|
height: 80, |
|
|
}, |
|
|
fab: { |
|
|
position: 'absolute', |
|
|
margin: 16, |
|
|
right: 0, |
|
|
bottom: 0, |
|
|
}, |
|
|
}); |
|
|
|
|
|
|