-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
530 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React from 'react'; | ||
import {ImageHeader, Icon, Flex, Text} from '@uiw/react-native'; | ||
import {ComProps} from '../../routes'; | ||
import Layout, {Container} from '../../Layout'; | ||
|
||
export interface ImageHeaderProps extends ComProps {} | ||
|
||
export default class ImageHeaderView extends React.Component<ImageHeaderProps> { | ||
render() { | ||
return ( | ||
<ImageHeader | ||
headerBackgroundImg={{uri: 'https://c-ssl.duitang.com/uploads/blog/201411/18/20141118232436_zkQVV.jpeg'}} | ||
headerHeight={161} | ||
headerLeftColor="#FFF" | ||
headerLeft="返回" | ||
headerRight={<Icon name="delete" size={20} color={'##FFF'} />} | ||
statusBarColor="blue" | ||
statusBarStyle="dark-content"> | ||
<Flex justify="center" style={{backgroundColor: 'white', height: 100, marginHorizontal: 20}}> | ||
<Text>111</Text> | ||
</Flex> | ||
</ImageHeader> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import React, { ReactNode } from 'react'; | ||
import { TextStyle, TouchableOpacity, Text } from 'react-native'; | ||
import Animated, { Extrapolate, interpolate, interpolateColor, useAnimatedStyle } from 'react-native-reanimated'; | ||
import { useSafeAreaInsets } from 'react-native-safe-area-context'; | ||
import { Theme } from '../theme'; | ||
import { useTheme } from '@shopify/restyle'; | ||
|
||
import Box from '../Typography/Box'; | ||
import Flex from '../Flex'; | ||
import helpers from './helpers'; | ||
import Icon from '../Icon'; | ||
|
||
const { px, ONE_PIXEL, deviceWidth } = helpers; | ||
const HEADER_HEIGHT = px(44); | ||
export interface AnimateHeaderProps { | ||
/** 头部文字 */ | ||
headerTitle: string; | ||
/** 头部文字样式 */ | ||
headerTitleStyle?: TextStyle; | ||
/** 滚动距离 */ | ||
scrollY: Animated.SharedValue<number>; | ||
/** 纵向滚动到哪个值时显示ImageHeader */ | ||
scrollHeight?: number; | ||
/** 头部右侧内容 */ | ||
headerRight?: ReactNode; | ||
/** 左侧返回键和字体颜色 */ | ||
headerLeftColor?: string; | ||
/** 头部左侧内容 */ | ||
headerLeft?: ReactNode; | ||
/** 头部底色,默认为透明 */ | ||
headerBackgroundColor?: string; | ||
/** 左侧点击事件 */ | ||
onPress?: () => void; | ||
/** 是否显示左侧图标 */ | ||
showLeft?: boolean; | ||
} | ||
|
||
const AnimateHeader: React.FC<AnimateHeaderProps> = (props) => { | ||
const theme = useTheme<Theme>(); | ||
const insets = useSafeAreaInsets(); | ||
|
||
const { | ||
scrollY, | ||
headerTitle, | ||
headerTitleStyle, | ||
scrollHeight = 300, | ||
onPress, | ||
showLeft = true, | ||
headerRight, | ||
headerLeftColor = theme.colors.gray500, | ||
headerLeft, | ||
headerBackgroundColor = theme.colors.background, | ||
} = props; | ||
|
||
const inputRange = [0, scrollHeight]; | ||
const style = useAnimatedStyle(() => { | ||
const opacity = interpolate(scrollY.value, inputRange, [0, 1], Extrapolate.CLAMP); | ||
const borderBottomWidth = interpolate(scrollY.value, inputRange, [0, ONE_PIXEL], Extrapolate.CLAMP); | ||
const backgroundColor = interpolateColor(scrollY.value, inputRange, ['transparent', headerBackgroundColor]); | ||
|
||
return { | ||
borderBottomWidth, | ||
backgroundColor, | ||
opacity, | ||
}; | ||
}); | ||
|
||
return ( | ||
<Animated.View | ||
style={[ | ||
{ | ||
width: deviceWidth, | ||
position: 'absolute', | ||
top: 0, | ||
zIndex: 99, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
borderBottomColor: theme.colors.border, | ||
paddingTop: insets.top, | ||
height: HEADER_HEIGHT + insets.top, | ||
}, | ||
style, | ||
]} | ||
> | ||
<Flex style={{ flex: 1 }}> | ||
{showLeft ? ( | ||
<TouchableOpacity activeOpacity={0.5} onPress={onPress} style={{ flex: 1 }}> | ||
<Flex> | ||
<Icon name="left" size={px(24)} color={headerLeftColor} /> | ||
{typeof headerLeft === 'string' ? ( | ||
<Text style={{ color: headerLeftColor }}>{headerLeft}</Text> | ||
) : ( | ||
headerLeft | ||
)} | ||
</Flex> | ||
</TouchableOpacity> | ||
) : ( | ||
<Box flex={1} /> | ||
)} | ||
<Animated.View style={{ flex: 5, alignItems: 'center' }}> | ||
<Text numberOfLines={1} style={[{ color: '#333333' }, headerTitleStyle]}> | ||
{headerTitle} | ||
</Text> | ||
</Animated.View> | ||
<Box flex={1} alignItems="flex-end"> | ||
{headerRight} | ||
</Box> | ||
</Flex> | ||
</Animated.View> | ||
); | ||
}; | ||
AnimateHeader.displayName = 'AnimateHeader'; | ||
|
||
export default AnimateHeader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
--- | ||
title: ImageHeader - 图片头部组件 | ||
nav: | ||
title: RN组件 | ||
path: /react-native | ||
group: | ||
title: Display | ||
path: /display | ||
--- | ||
|
||
# ImageHeader 图片头部组件 | ||
|
||
## 效果演示 | ||
|
||
### 1. 普通 ImageHeader | ||
|
||
```tsx | pure | ||
<ImageHeader headerBackgroundImg={require('../../assets/images/bg_rank.png')} headerHeight={px(161)} {...props}> | ||
<Flex justifyContent="center" backgroundColor="white" height={100}> | ||
<Text>111</Text> | ||
</Flex> | ||
</ImageHeader> | ||
``` | ||
|
||
<center> | ||
<figure> | ||
<img | ||
alt="header-ios1.png" | ||
src="https://td-dev-public.oss-cn-hangzhou.aliyuncs.com/maoyes-app/1609999430064140139.png" | ||
style="width: 375px; margin-right: 10px; border: 1px solid #ddd;" | ||
/> | ||
</figure> | ||
</center> | ||
|
||
### 2. ImageHeader 配置 left、right 和 headerLeftColor | ||
|
||
```tsx | pure | ||
<ImageHeader | ||
headerBackgroundImg={require('../../assets/images/bg_rank.png')} | ||
headerHeight={px(161)} | ||
headerLeftColor={theme.colors.white} | ||
headerLeft="返回" | ||
headerRight={<Icon name="delete" size={px(20)} color={theme.colors.white} />} | ||
{...props} | ||
> | ||
<Flex justifyContent="center" backgroundColor="white" height={100}> | ||
<Text>111</Text> | ||
</Flex> | ||
</ImageHeader> | ||
``` | ||
|
||
<center> | ||
<figure> | ||
<img | ||
alt="header-ios2.png" | ||
src="https://td-dev-public.oss-cn-hangzhou.aliyuncs.com/maoyes-app/1609999550703021067.png" | ||
style="width: 375px; margin-right: 10px; border: 1px solid #ddd;" | ||
/> | ||
</figure> | ||
</center> | ||
|
||
### 3. ImageHeader 配置 headerBackgroundColor | ||
|
||
```tsx | pure | ||
<ImageHeader | ||
headerBackgroundImg={require('../../assets/images/bg_rank.png')} | ||
headerHeight={px(161)} | ||
headerBackgroundColor={theme.colors.white} | ||
headerLeft="返回" | ||
headerRight={<Icon name="delete" size={px(20)} color={theme.colors.white} />} | ||
{...props} | ||
> | ||
<Flex justifyContent="center" height={100}> | ||
<Text>111</Text> | ||
</Flex> | ||
</ImageHeader> | ||
``` | ||
|
||
<center> | ||
<figure> | ||
<img | ||
alt="header-ios3.png" | ||
src="https://td-dev-public.oss-cn-hangzhou.aliyuncs.com/maoyes-app/1610000705310241428.png" | ||
style="width: 375px; margin-right: 10px; border: 1px solid #ddd;" | ||
/> | ||
</figure> | ||
</center> | ||
|
||
### 4. AnimatedHeader | ||
|
||
```tsx | pure | ||
import { useScrollHandler } from 'react-native-redash'; | ||
import Animated from 'react-native-reanimated'; | ||
|
||
export default () => { | ||
const { scrollHandler, y } = useScrollHandler(); | ||
|
||
return ( | ||
<AnimateHeader | ||
scrollY={y} | ||
scrollHeight={200} | ||
headerTitle="测试啊啊啊啊啊" | ||
headerLeft="返回" | ||
headerBackgroundColor={theme.colors.white} | ||
{...props} | ||
headerRight={ | ||
<TouchableOpacity activeOpacity={0.5} onPress={() => props.navigation.goBack()}> | ||
<Icon name="delete" size={px(20)} color={theme.colors.primaryColor} /> | ||
</TouchableOpacity> | ||
} | ||
/> | ||
<Animated.ScrollView {...scrollHandler}> | ||
<ImageHeader | ||
headerBackgroundImg={require('../../assets/images/bg_rank.png')} | ||
headerHeight={px(161)} | ||
headerLeftColor={theme.colors.white} | ||
headerRight={ | ||
<TouchableOpacity activeOpacity={0.5} onPress={() => props.navigation.goBack()}> | ||
<Icon name="delete" size={px(20)} color={theme.colors.primaryColor} /> | ||
</TouchableOpacity> | ||
} | ||
{...props} | ||
> | ||
<Flex justifyContent="center" height={100}> | ||
<Text>111</Text> | ||
</Flex> | ||
</ImageHeader> | ||
<Box width={200} height={900} /> | ||
</Animated.ScrollView> | ||
) | ||
} | ||
``` | ||
|
||
<center> | ||
<figure> | ||
<img | ||
alt="header-ios4.gif" | ||
src="https://td-dev-public.oss-cn-hangzhou.aliyuncs.com/maoyes-app/1608877076955547998.gif" | ||
style="width: 375px; margin-right: 10px; border: 1px solid #ddd;" | ||
/> | ||
</figure> | ||
</center> | ||
|
||
## ImageHeader 组件 API | ||
|
||
| 属性 | 必填 | 说明 | 类型 | 默认值 | | ||
| --------------------- | ------- | -------------------- | --------------------- | --------------------------- | | ||
| headerTitle | `false` | 头部文字 | `ReactNode` | | | ||
| headerRight | `false` | 头部右侧内容 | `ReactNode` | | | ||
| headerLeft | `false` | 头部左侧内容 | `ReactNode` | | | ||
| headerLeftColor | `false` | 左侧返回键和字体颜色 | `string` | `theme.colors.primaryColor` | | ||
| headerBackgroundColor | `false` | 头部背景颜色 | `string` | `transparent` | | ||
| headerBackgroundImg | `true` | 头部背景图片 | `ImageSourcePropType` | | | ||
| headerHeight | `false` | 头部高度 | `number` | | | ||
| onPress | `false` | 左边图标点击事件 | `() => void` | | | ||
| showLeft | `false` | 是否显示左边图标 | `boolean` | `true` | | ||
|
||
## AnimateHeader 组件 API | ||
|
||
| 属性 | 必填 | 说明 | 类型 | 默认值 | | ||
| --- | --- | --- | --- | --- | | ||
| headerTitle | `true` | 头部文字 | `string` | | | ||
| headerTitleStyle | `false` | 头部文字样式 | `TextStyle` | | | ||
| scrollY | `false` | 滚动距离 | `Animated.SharedValue<number>` | `0` | | ||
| scrollHeight | `false` | 纵向滚动到哪个值时显示 `ImageHeader` | `number` | `300` | | ||
| headerHeight | `true` | 头部高度 | `number` | | | ||
| headerRight | `false` | 头部右侧内容 | `ReactNode` | | | ||
| headerLeft | `false` | 头部左侧内容 | `ReactNode` | | | ||
| headerLeftColor | `false` | 左侧返回键和字体颜色 | `string` | `theme.colors.primaryColor` | | ||
| headerBackgroundColor | `false` | 头部背景颜色 | `string` | `transparent` | | ||
| onPress | `false` | 左边按钮点击事件 | `() => void` | | | ||
| showLeft | `false` | 是否显示左边图标 | `boolean` | `true` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Platform, StyleProp } from 'react-native'; | ||
|
||
import { deviceHeight, deviceWidth, ONE_PIXEL, px } from './normalize'; | ||
// import rddNode from './rddNode'; | ||
|
||
/** | ||
* 判断是否是IOS系统 | ||
*/ | ||
const isIOS = Platform.OS === 'ios'; | ||
|
||
/** | ||
* 根据条件决定样式是否生效 | ||
* @param condition | ||
* @param style | ||
*/ | ||
const conditionalStyle = (condition: boolean, style: StyleProp<any>) => (condition ? style : {}); | ||
|
||
function hexToRgba(hex: string, alpha = 1) { | ||
let c: any; | ||
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) { | ||
let arr = hex.substring(1).split(''); | ||
if (arr.length == 3) { | ||
arr = [arr[0], arr[0], arr[1], arr[1], arr[2], arr[2]]; | ||
} | ||
c = '0x' + arr.join(''); | ||
return 'rgba(' + [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',') + `,${alpha})`; | ||
} | ||
throw new Error('Bad Hex'); | ||
} | ||
|
||
export default { | ||
// rddNode, | ||
px, | ||
deviceWidth, | ||
deviceHeight, | ||
ONE_PIXEL, | ||
isIOS, | ||
conditionalStyle, | ||
hexToRgba, | ||
}; |
Oops, something went wrong.