lottie-react-native动画库github以及官网
可以用于页面加载时的动画
import React, {FC} from "react";
import {SafeAreaView, ScrollView, Text} from "react-native";
import Lottie from 'lottie-react-native';
interface Props {
}
const LottieReactNative: FC<Props> = () => {
const animationRef = React.useRef<Lottie | null>(null);
React.useEffect(() => {
}, []);
return <SafeAreaView>
<ScrollView>
<Lottie source={require('./animation.json')} autoPlay loop style={{width: 100}}/>
</ScrollView>
</SafeAreaView>;
};
export default LottieReactNative;
react-icomoon轻量图标
import React from "react";
import {SafeAreaView, ScrollView} from "react-native";
import IcoMoon, {iconList} from "react-icomoon";
const iconSet = require('./selection.json');
import { Svg, Path } from 'react-native-svg';
const ReactIcoMoon = () => {
React.useEffect(() => {
}, []);
return <SafeAreaView>
<ScrollView>
<IcoMoon
native
iconSet={iconSet}
SvgComponent={Svg}
PathComponent={Path}
icon="heart"
size={30}
style={{ margin: 50, color: '#f40' }}
/>
</ScrollView>
</SafeAreaView>;
};
export default ReactIcoMoon;
react-native-calendars日历
import React from "react";
import {SafeAreaView, ScrollView} from "react-native";
import {Calendar, LocaleConfig} from 'react-native-calendars';
LocaleConfig['locales'][''] = {
monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
dayNames: ['周一', '周二', '周三', '周四', '周五', '周六', '周天'],
dayNamesShort: ['周一', '周二', '周三', '周四', '周五', '周六', '周天'],
amDesignator: '上午',
pmDesignator: '下午'
}
const ReactNativeCalendars = () => {
const [selected, setSelected] = React.useState('');
React.useEffect(() => {
}, []);
return <SafeAreaView>
<ScrollView>
<Calendar
onDayPress={(day) => {
setSelected(day.dateString);
}}
style={{height: 350}}
markedDates={{
[selected]: {selected: true, disableTouchEvent: true, selectedDotColor: 'orange'}
}}
/>
</ScrollView>
</SafeAreaView>;
};
export default ReactNativeCalendars;
react-native-drawer抽屉
<Drawer
type="displace"
ref={drawerRef}
acceptDoubleTap={true}
captureGestures={false}
tweenDuration={100}
panThreshold={0.08}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
openDrawerOffset={() => 90}
panOpenMask={0.2}
open={open}
negotiatePan={true}
content={<ScrollView style={styles.container}>
<ReactNativeCalendars onSelect={(date) => {
drawerRef.current!.close();
setDate(date);
}}/>
</ScrollView>}
styles={{drawer: styles.drawer, main: styles.main}}
tweenHandler={(ratio) => ({
main: {opacity: (2 - ratio) / 2}
})}
>
<ScrollView style={[styles.container, {backgroundColor: '#FFF',}]}>
<Text onPress={() => drawerRef.current!.open()}>{date || '选择日期'}</Text>
</ScrollView>
</Drawer>
react-native-textinput-effects漂亮的输入框
import React from "react";
import {SafeAreaView, ScrollView} from "react-native";
import {Fumi} from 'react-native-textinput-effects';
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
const ReactNativeTextInputEffects = () => {
const [value, setValue] = React.useState('');
React.useEffect(() => {
}, []);
return <SafeAreaView>
<ScrollView>
<Fumi
style={{backgroundColor: '#f9f5ed'}}
label="账号"
iconClass={FontAwesomeIcon}
iconName="university"
iconColor="#f95a25"
iconSize={20}
iconWidth={40}
inputPadding={16}
onChangeText={setValue}
value={value}
keyboardType="number-pad"
blurOnSubmit={true}
/>
</ScrollView>
</SafeAreaView>;
};
export default ReactNativeTextInputEffects;
react-native-lightbox查看图片(这个库有点老复制下来重写)
import React, {FC} from "react";
import {
View,
ViewStyle,
Animated,
Easing,
Dimensions,
Platform,
StyleSheet,
StatusBar,
Modal,
TouchableOpacity,
Text, TouchableWithoutFeedback, Image
} from "react-native";
const WINDOW_HEIGHT = Dimensions.get('window').height;
const WINDOW_WIDTH = Dimensions.get('window').width;
const isIOS = Platform.OS === 'ios';
export interface ImageLightBoxProps {
style?: ViewStyle;
uri: string;
}
const styles = StyleSheet.create({
background: {
position: 'absolute',
top: 0,
left: 0,
width: WINDOW_WIDTH,
height: WINDOW_HEIGHT,
backgroundColor: '#000'
},
open: {
position: 'absolute',
flex: 1,
justifyContent: 'center',
backgroundColor: 'transparent',
},
header: {
position: 'absolute',
top: 0,
left: 0,
width: WINDOW_WIDTH,
backgroundColor: 'transparent',
},
closeButton: {
fontSize: 35,
color: 'white',
lineHeight: 40,
width: 40,
textAlign: 'center',
shadowOffset: {
width: 0,
height: 0,
},
shadowRadius: 1.5,
shadowColor: 'black',
shadowOpacity: 0.8,
},
});
const springConfig = {
tension: 1,
friction: 100,
useNativeDriver: false
}
const ImageLightBox: FC<ImageLightBoxProps> = (props) => {
const rootRef = React.useRef<Image>();
const animatedLayoutOpacity = React.useRef(new Animated.Value(1));
const animatedOpenValue = React.useRef(new Animated.Value(0));
const [origin, setOrigin] = React.useState({x: 0, y: 0, width: 0, height: 0});
const [isOpen, setIsOpen] = React.useState(false);
const [target, setTarget] = React.useState({x: 0, y: 0, opacity: 1});
const [imageStyle, setImageStyle] = React.useState<{ height?: number | string; width?: number | string }>({});
React.useEffect(() => {
Image.getSize(props.uri, (w, h) => {
if (props.style) {
const {height, width} = props.style;
if (height && !width) {
setImageStyle({width: height * w / h, height});
} else if (!height && width) {
setImageStyle({width, height: width * h / w});
} else if (height && width) {
setImageStyle({width, height});
} else {
setImageStyle({height: h, width: w})
}
}
});
}, [props.uri]);
const open = () => {
rootRef.current!.measure((ox, oy, width, height, px, py) => {
if (isIOS) {
StatusBar.setHidden(true, 'fade');
}
setIsOpen(true);
setTarget({x: 0, y: 0, opacity: 1});
// 获取图片的位置并隐身
setOrigin({width, height, x: px, y: py});
Animated.parallel([
setOpacity(0),
setOpenValue(1)
]).start();
});
}
const close = () => {
if (isIOS) {
StatusBar.setHidden(false, 'fade');
}
setOpenValue(0).start(() => {
setOpacity(1).start(() => {
setIsOpen(false);
});
});
}
const setOpenValue = (value) => {
return Animated.spring(animatedOpenValue.current, {
toValue: value,
...springConfig
});
}
const setOpacity = (value: number) => {
return Animated.timing(animatedLayoutOpacity.current, {
useNativeDriver: true,
easing: Easing.linear,
duration: 100,
toValue: value
});
}
const opacityStyle = {
opacity: animatedOpenValue.current.interpolate({inputRange: [0, 1], outputRange: [0, target.opacity]})
}
const openStyle = [styles.open, {
left: animatedOpenValue.current.interpolate({
inputRange: [0, 1],
outputRange: [origin.x || 0, target.x || 0],
}),
top: animatedOpenValue.current.interpolate({
inputRange: [0, 1],
outputRange: [origin.y || 0, target.y || 0],
}),
width: animatedOpenValue.current.interpolate({
inputRange: [0, 1],
outputRange: [origin.width || 0, WINDOW_WIDTH],
}),
height: animatedOpenValue.current.interpolate({
inputRange: [0, 1],
outputRange: [origin.height || 0, WINDOW_HEIGHT],
})
}];
return <React.Fragment>
<TouchableWithoutFeedback onPress={open}>
<View ref={rootRef} style={imageStyle}>
<Animated.Image
style={[props.style, imageStyle, {opacity: animatedLayoutOpacity.current}]}
resizeMode="contain"
source={{uri: props.uri}}
/>
</View>
</TouchableWithoutFeedback>
<Modal visible={isOpen} transparent={true} onRequestClose={close}>
<Animated.View style={[styles.background, opacityStyle]}/>
<Animated.View style={[openStyle]}>
<Image
source={{uri: props.uri}}
resizeMode="contain"
style={{flex: 1}}
/>
</Animated.View>
<Animated.View style={[styles.header, opacityStyle]}>
<TouchableOpacity onPress={close}>
<Text style={styles.closeButton}>×</Text>
</TouchableOpacity>
</Animated.View>
</Modal>
</React.Fragment>;
};
export default ImageLightBox;
import React from "react";
import {SafeAreaView, ScrollView, View} from "react-native";
import ImageLightBox from "../../components/ImageLightBox";
const ReactNativeLightBox = () => {
React.useEffect(() => {
}, []);
return <SafeAreaView>
<ScrollView style={{paddingTop: 100}}>
<View style={{flexDirection: "row", justifyContent: "space-between"}}>
<ImageLightBox
uri="https://xxx.jpeg"
style={{height: 40}}
/>
<ImageLightBox
uri="https://xxx.jpeg"
style={{height: 100}}
/>
<ImageLightBox
uri="https://xxx.jpeg"
style={{height: 200}}
/>
</View>
</ScrollView>
</SafeAreaView>;
};
export default ReactNativeLightBox;
react-native-action-button浮动折叠菜单
import React from "react";
import {SafeAreaView, ScrollView, StyleSheet} from "react-native";
import ActionButton from 'react-native-action-button';
import Icon from 'react-native-vector-icons/Ionicons';
const ReactNativeActionButton = () => {
React.useEffect(() => {
}, []);
return <SafeAreaView style={{flex: 1, backgroundColor: '#f3f3f3'}}>
<ScrollView>
</ScrollView>
<ActionButton buttonColor="rgba(231,76,60,1)">
<ActionButton.Item buttonColor='#9b59b6' title="新任务" onPress={() => {}}>
<Icon name="md-create" style={styles.actionButtonIcon} />
</ActionButton.Item>
<ActionButton.Item buttonColor='#3498db' title="新消息" onPress={() => {}}>
<Icon name="md-notifications-off" style={styles.actionButtonIcon} />
</ActionButton.Item>
<ActionButton.Item buttonColor='#1abc9c' title="新问题" onPress={() => {}}>
<Icon name="md-done-all" style={styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
</SafeAreaView>;
};
const styles = StyleSheet.create({
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white',
},
});
export default ReactNativeActionButton;
react-native-masonry砖块格子类似小红书
这个库的里的ListView不能用了,需要替换成deprecated-react-native-listview,顺便把查看图片也加了进去,建议用最新的FlatList去重写
import React from "react";
import {SafeAreaView} from "react-native";
import Masonry from "../../components/Masonry";
const ReactNativeMasonry = () => {
React.useEffect(() => {
}, []);
return <SafeAreaView style={{flex: 1}}>
<Masonry
columns={2}
bricks={[
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
{uri: 'https://xxx'},
]}
/>
</SafeAreaView>;
};
export default ReactNativeMasonry;
react-native-looped-carousel反复的轮播(图片)
和react-native-swiper和react-native-carousel差不多。
图片浏览的轮播用react-native-image-carousel可以放大缩小
react-native-fading-slides轮播幻灯片没什么用
import React, {FC} from "react";
import {View, Image} from "react-native";
import Carousel from 'react-native-looped-carousel';
interface Props {
images?: { uri: string }[];
currentPage?: number;
onAnimateNextPage?: (page: number) => void;
}
const Images: FC<Props> = (props) => {
const [size, setSize] = React.useState<{ width?: number, height?: number }>({});
React.useEffect(() => {
}, []);
return <View style={{width: '100%', height: '100%'}} onLayout={(e) => {
const layout = e['nativeEvent'].layout;
setSize({width: layout.width, height: layout.height});
}}>
<Carousel
currentPage={props.currentPage}
pageInfo={true}
style={{...size}}
autoplay={false}
pageInfoBackgroundColor="rgba(255,255,255,0.5)"
onAnimateNextPage={props.onAnimateNextPage}>
{props.images!.map((i, index) => {
return <View style={[size]} key={index}>
<Image
source={{uri: i.uri}}
resizeMode="contain"
style={{flex: 1, }}
/>
</View>
})}
</Carousel>
</View>;
};
Images.defaultProps = {
images: [],
currentPage: 0,
}
export default Images;
react-native-svg-charts图表
import React from "react";
import {SafeAreaView, ScrollView, View} from "react-native";
import {
AreaChart,
Grid,
StackedAreaChart,
BarChart,
LineChart,
PieChart,
ProgressCircle,
YAxis,
XAxis
} from 'react-native-svg-charts';
import * as shape from 'd3-shape'
const ReactNativeSvgCharts = () => {
React.useEffect(() => {
}, []);
return <SafeAreaView style={{flex: 1}}>
<ScrollView>
<AreaChart
style={{height: 200}}
data={[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]}
contentInset={{top: 30, bottom: 30}}
curve={shape.curveNatural}
svg={{fill: 'rgba(134, 65, 244, 0.8)'}}
>
<Grid/>
</AreaChart>
<StackedAreaChart
style={{height: 200, paddingVertical: 16}}
data={[
{
month: new Date(2015, 0, 1),
apples: 3840,
bananas: 1920,
cherries: 960,
dates: 400,
},
{
month: new Date(2015, 1, 1),
apples: 1600,
bananas: 1440,
cherries: 960,
dates: 400,
},
{
month: new Date(2015, 2, 1),
apples: 640,
bananas: 960,
cherries: 3640,
dates: 400,
},
{
month: new Date(2015, 3, 1),
apples: 3320,
bananas: 480,
cherries: 640,
dates: 400,
},
]}
keys={['apples', 'bananas', 'cherries', 'dates']}
colors={['#8800cc', '#aa00ff', '#cc66ff', '#eeccff']}
curve={shape.curveNatural}
showGrid={false}
svgs={[
{onPress: () => console.log('apples')},
{onPress: () => console.log('bananas')},
{onPress: () => console.log('cherries')},
{onPress: () => console.log('dates')},
]}
/>
<BarChart
style={{height: 200}}
data={[50, 10, 40, 95, -4, -24, null, 85, undefined, 0, 35, 53, -53, 24, 50, -20, -80]}
svg={{fill: 'rgb(134, 65, 244)'}}
contentInset={{top: 30, bottom: 30}}
>
<Grid/>
</BarChart>
<LineChart
style={{height: 200}}
data={[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]}
svg={{stroke: 'rgb(134, 65, 244)'}}
contentInset={{top: 20, bottom: 20}}
>
<Grid/>
</LineChart>
<PieChart
style={{height: 200}}
data={
[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80].filter((value) => value > 0)
.map((value, index) => ({
value,
svg: {
fill: ('#' + ((Math.random() * 0xffffff) << 0).toString(16) + '000000').slice(0, 7),
onPress: () => console.log('press', index),
},
key: `pie-${index}`,
}))
}
/>
<ProgressCircle
style={{height: 200}}
progress={0.7}
progressColor={'rgb(134, 65, 244)'}
/>
<View style={{height: 200, flexDirection: 'row'}}>
<YAxis
data={[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]}
contentInset={{top: 20, bottom: 20}}
svg={{
fill: 'grey',
fontSize: 10,
}}
numberOfTicks={10}
formatLabel={(value) => `${value}ºC`}
/>
<LineChart
style={{flex: 1, marginLeft: 16}}
data={[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]}
svg={{stroke: 'rgb(134, 65, 244)'}}
contentInset={{top: 20, bottom: 20}}
>
<Grid/>
</LineChart>
</View>
<View style={{height: 200, padding: 20}}>
<LineChart
style={{flex: 1}}
data={[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]}
gridMin={0}
contentInset={{top: 10, bottom: 10}}
svg={{stroke: 'rgb(134, 65, 244)'}}
>
<Grid/>
</LineChart>
<XAxis
style={{marginHorizontal: -10}}
data={[50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]}
formatLabel={(value, index) => index}
contentInset={{left: 10, right: 10}}
svg={{fontSize: 10, fill: 'black'}}
/>
</View>
</ScrollView>
</SafeAreaView>;
};
export default ReactNativeSvgCharts;
react-native-progress-bar进度条
import React, {FC} from "react";
import {StyleSheet, Animated, Easing, View, ViewStyle} from "react-native";
interface Props {
initialProgress?: number;
progress: number;
easing?: (value: number) => number;
easingDuration?: number;
backgroundStyle?: ViewStyle;
style?: ViewStyle;
fillStyle?: ViewStyle;
}
const ProgressBar: FC<Props> = (props) => {
const progressRef = React.useRef(new Animated.Value(props.initialProgress || 0));
React.useEffect(() => {
update();
}, [props.progress]);
const update = () => {
Animated.timing(progressRef.current, {
useNativeDriver: false,
easing: props.easing!,
duration: props.easingDuration!,
toValue: props.progress
}).start();
};
React.useEffect(() => {
}, []);
return <View style={[styles.background, props.backgroundStyle, props.style]}>
<Animated.View style={[styles.fill, props.fillStyle, {
width: progressRef.current.interpolate({
inputRange: [0, 1],
outputRange: [0, 1 * (props.style!.width || 0)],
})
}]}/>
</View>;
};
const styles = StyleSheet.create({
background: {
backgroundColor: '#bbbbbb',
height: 5,
overflow: 'hidden'
},
fill: {
backgroundColor: '#3b5998',
height: 5
}
});
ProgressBar.defaultProps = {
initialProgress: 0,
easingDuration: 500,
easing: Easing.inOut(Easing.ease),
backgroundStyle: {},
style: {},
fillStyle: {}
}
export default ProgressBar;
<ProgressBar
fillStyle={{}}
backgroundStyle={{backgroundColor: '#cccccc', borderRadius: 2}}
style={{marginTop: 10, width: 300}}
progress={progress}
/>
react-native-gesture-password手势密码
import React from "react";
import {SafeAreaView, ScrollView} from "react-native";
import GesturePassword from "react-native-gesture-password";
const ReactNativeGesturePassword = () => {
const [status, setStatus] = React.useState('normal');
const [message, setMessage] = React.useState('请输入密码');
const refPassword = React.useRef<GesturePassword>();
React.useEffect(() => {
}, []);
const onStart = () => {
}
const onEnd = (password: string) => {
refPassword.current!.resetActive();
}
return <SafeAreaView>
<GesturePassword
ref={(e) => refPassword.current = e}
status={status}
message={message}
onStart={() => onStart()}
onEnd={(password) => onEnd(password)}
innerCircle={true}
outerCircle={true}
/>
</SafeAreaView>;
};
export default ReactNativeGesturePassword;
持续更新...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。