|
|
|
|
|
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,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|