@react-navigation/stack#useHeaderHeight TypeScript Examples
The following examples show how to use
@react-navigation/stack#useHeaderHeight.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: JoinScreen.tsx From lets-fork-native with MIT License | 6 votes |
JoinScreen = React.memo((props: Props): React.ReactElement => {
const { navigation, ws } = props
const [value, setValue] = React.useState('')
const headerHeight = useHeaderHeight()
// joins an existing party
const handleJoin = (): void => {
if (value) {
ws.send(JSON.stringify({ type: 'join', payload: { party_id: value } }))
navigation.navigate('Party')
Keyboard.dismiss()
}
}
return (
<KeyboardAvoidingView
behavior="height"
style={{
...styles.container,
height: height - headerHeight,
}}
>
<Text style={styles.text}>Please enter the party code</Text>
<Input value={value} handleChange={setValue} keyboardType="phone-pad" />
<Button size="sm" color="purple" onPress={(): void => handleJoin()}>
JOIN
</Button>
</KeyboardAvoidingView>
)
})
Example #2
Source File: ImageTransformerTest.tsx From react-native-gallery-toolkit with MIT License | 6 votes |
export default function StandaloneGalleryBasicScreen() {
const headerHeight = useHeaderHeight();
return (
<ImageTransformer
windowDimensions={{
height: height - headerHeight,
width,
}}
width={image.width}
height={image.height}
source={image.uri}
/>
);
}
Example #3
Source File: Map.tsx From react-native-gallery-toolkit with MIT License | 6 votes |
export default function StandaloneMap() {
const initialIndex = 1;
const headerHeight = useHeaderHeight();
const totalCount = 3;
function handleIndexChange(i: number) {
'worklet';
console.log(i);
// you can fetch more items and store it to the map here
}
return (
<SimpleGallery
initialIndex={initialIndex}
onIndexChange={handleIndexChange}
height={height - headerHeight}
renderPage={(props, i) => <Page {...props} index={i} />}
getItem={(data, i) => data.get(i)}
items={images}
getTotalCount={() => totalCount}
/>
);
}
Example #4
Source File: ShelfTabs.tsx From krmanga with MIT License | 5 votes |
function ShelfTabs() {
const tabHeight = useHeaderHeight() - getStatusBarHeight();
return (
<Tab.Navigator
lazy
tabBar={(props) => <TopBar {...props} />}
pager={props => <ViewPagerAdapter {...props} />}
tabBarOptions={{
scrollEnabled: true,
tabStyle: {
width: 50,
height: tabHeight,
padding: 0,
margin: 0
},
labelStyle: {
fontSize: 15,
fontWeight: "bold",
color: Color.white
},
indicatorStyle: {
height: 3,
width: 16,
marginLeft: 17,
marginBottom: 5,
borderRadius: 2,
backgroundColor: Color.white
},
allowFontScaling: true,
activeTintColor: Color.dark_title,
inactiveTintColor: Color.black
}}>
<Tab.Screen
key={"shelf-tab-1"}
name="收藏"
component={Shelf}
/>
<Tab.Screen
key={"shelf-tab-2"}
name={"历史"}
component={History}
/>
<Tab.Screen
key={"shelf-tab-3"}
name={"下载"}
component={Download}
/>
</Tab.Navigator>
);
}
Example #5
Source File: TopBarWrapper.tsx From krmanga with MIT License | 5 votes |
function TopBarWrapper({navigation, topBarColor}: IProps) {
const headerHeight = useHeaderHeight()
const goSearch = () => {
navigation.navigate('Search');
}
const goGuess = (headerTitle: string) => {
navigation.navigate('Guess', {
headerTitle
});
}
return (
<Animated.View style={[styles.container, {
height: headerHeight
}]}>
<Animated.View style={{
...StyleSheet.absoluteFillObject,
backgroundColor: Color.theme,
opacity: topBarColor
}}/>
<View style={styles.header}>
<View style={styles.headerLeft}>
<Touchable style={styles.headerLeftView} onPress={() => goGuess("榜单")}>
<Icon name="icon-paihangbang" size={25}/>
<Text style={styles.headerText}>榜单</Text>
</Touchable>
<Touchable style={styles.headerLeftView} onPress={() => goGuess("更新")}>
<Icon name="icon-shizhong" size={25}/>
<Text style={styles.headerText}>更新</Text>
</Touchable>
<Touchable style={styles.headerLeftView} onPress={() => goGuess("书单")}>
<Icon name="icon-history" size={25}/>
<Text style={styles.headerText}>书单</Text>
</Touchable>
<Touchable style={styles.headerLeftView} onPress={() => goGuess("VIP")}>
<Icon name="icon-VIP" size={25}/>
<Text style={styles.headerText}>VIP</Text>
</Touchable>
</View>
<Touchable onPress={goSearch}>
<View style={styles.headerRight}>
<Icon name="icon-search" size={25}/>
</View>
</Touchable>
</View>
</Animated.View>
)
}
Example #6
Source File: index.tsx From lets-fork-native with MIT License | 5 votes |
// Initially shown while waiting for users to join party
// But can also be accessed through Menu for additional
// users to join after party has started
export default function Share(props: Props): React.ReactElement {
const [loading, setLoading] = React.useState(false)
const { party, ws } = props
const headerHeight = useHeaderHeight()
const viewHeight = env.ADS ? height - headerHeight - 50 : height - headerHeight
const handlePress = (): void => {
Alert.alert(
'',
'No matches will be shown until another user joins your party',
[
{
text: 'OK',
onPress: (): void => {
if (ws) {
ws.send(JSON.stringify({ type: 'start-swiping' }))
setLoading(true)
}
},
},
],
{ cancelable: true },
)
}
if (loading) {
return (
<View
style={{
...styles.container,
height: viewHeight,
}}
>
<ActivityIndicator size="large" />
</View>
)
}
return (
<View
style={{
...styles.container,
height: viewHeight,
}}
>
<Text style={styles.text}>Share this code with friends to have them join your party.</Text>
<Text style={styles.code}>{party.id}</Text>
<QRCode
size={200}
// value={`http://192.168.178.76:8003/party/${party.id}`}
value={`https://letsfork.app/party/${party.id}`}
/>
{
party.status === 'waiting'
&& <Button color="purple" size="lg" onPress={(): void => handlePress()}>START SWIPING</Button>
}
<TouchableOpacity
accessibilityRole="button"
onPress={(): Promise<ShareAction> => RNShare.share(
{ message: `Join my party on Let's Fork by clicking this link:\nhttps://letsfork.app/party/${party.id}\n\nor by opening the app and entering the code ${party.id}` },
)}
>
{Platform.OS === 'ios' ? (
<Ionicons name="ios-share-outline" size={32} />
) : (
<MaterialIcons name="share" size={32} />
)}
</TouchableOpacity>
</View>
)
}
Example #7
Source File: MatchScreen.tsx From lets-fork-native with MIT License | 5 votes |
MatchScreen = React.memo((props: Props) => {
const { navigation, party } = props
const headerHeight = useHeaderHeight()
if (!party?.matches) {
return (
<View
style={{
...styles.container,
height: height - headerHeight - 108,
}}
>
<Text style={styles.text}>No matches yet</Text>
<Text style={styles.text}>Keep swiping!</Text>
</View>
)
}
return (
<ScrollView contentContainerStyle={styles.scrollView}>
{party?.matches.map((restaurant) => (
<TouchableOpacity
key={restaurant.id}
onPress={(): void => navigation.navigate('Restaurant', {
restaurant,
})}
>
<View style={styles.card}>
<View style={styles.overlay}>
<View>
<Text style={styles.name}>{restaurant.name}</Text>
</View>
</View>
<Image style={styles.image} source={{ uri: restaurant.image_url }} />
</View>
</TouchableOpacity>
))}
</ScrollView>
)
})
Example #8
Source File: Basic.tsx From react-native-gallery-toolkit with MIT License | 5 votes |
export default function StandaloneGalleryBasicScreen() {
const headerHeight = useHeaderHeight();
return (
<SimpleGallery height={height - headerHeight} items={images} />
);
}
Example #9
Source File: CategoryTabs.tsx From krmanga with MIT License | 4 votes |
function CategoryTabs({ hideHeader, statusList, myCategoryList }: IProps) {
const translateY = useRef(new Animated.Value(0)).current;
const headerHeight = useHeaderHeight();
const navigationHeight = headerHeight - getStatusBarHeight();
const getTopOpacity = () => {
return translateY.interpolate({
inputRange: [-navigationHeight, 0],
outputRange: [0, 1],
extrapolate: "clamp"
});
};
const showTopBar = () => {
Animated.timing(translateY, {
toValue: 0,
useNativeDriver: true
}).start();
};
const hideTopBar = () => {
Animated.timing(translateY, {
toValue: -navigationHeight,
useNativeDriver: true
}).start();
};
const addModel = useCallback((id: number) => {
statusList.map(item => {
createCategoryModel(`tab-category-${id}-status-${item.id}`);
});
}, []);
const renderScreen = (item: ICategory) => {
addModel(item.id);
return (
<Tab.Screen
key={`item-${item.id}`}
name={item.name}
component={Category}
initialParams={{
namespace: `tab-category-${item.id}`,
category_id: item.id
}}
options={{
tabBarLabel: item.name
}}
/>
);
};
if (hideHeader) {
hideTopBar();
} else {
showTopBar();
}
return (
<View style={styles.container}>
<View style={[styles.statusBar, {
...StyleSheet.absoluteFillObject,
backgroundColor: Color.page_bg
}]} />
<Animated.View style={[styles.statusBar, {
backgroundColor: Color.theme,
opacity: getTopOpacity()
}
]} />
<Animated.View style={[styles.tabBarView, {
height: navigationHeight,
backgroundColor: Color.theme,
opacity: getTopOpacity(),
transform: [{ translateY: translateY }]
}]}>
<Animated.Text style={[styles.title]}>漫画分类</Animated.Text>
</Animated.View>
<Animated.View style={{
height: viewportHeight - getStatusBarHeight(),
transform: [{ translateY: translateY }]
}}>
<Tab.Navigator
lazy
tabBar={(props) => <TopBar {...props} />}
pager={(props) => <ViewPagerAdapter {...props} />}
tabBarOptions={{
scrollEnabled: true,
tabStyle: {
width: 50,
height: 45,
padding: 0,
margin: 0
},
labelStyle: {
fontSize: 13
},
indicatorStyle: {
height: 3,
width: 16,
marginLeft: 17,
marginBottom: 5,
borderRadius: 2,
backgroundColor: Color.theme
},
allowFontScaling: true,
activeTintColor: Color.theme,
inactiveTintColor: Color.black
}}>
{myCategoryList.map(item => renderScreen(item))}
</Tab.Navigator>
</Animated.View>
</View>
);
}
Example #10
Source File: index.tsx From krmanga with MIT License | 4 votes |
function Home({ dispatch, commendList, refreshing, navigation, loading, hasMore }: IProps) {
const headerHeight = useHeaderHeight();
const scrollY: Animated.Value = useRef(new Animated.Value(0)).current;
const [endReached, setEndReached] = useState<boolean>(false);
useEffect(() => {
SplashScreen.hide();//关闭启动屏
dispatch({
type: "home/setState",
payload: {
headerHeight
}
});
syncImmediate();
loadCarouselList();
loadCommendList(true);
}, []);
const syncImmediate = () => {
if (Platform.OS === "android") {
codePush.checkForUpdate().then((update) => {
if (update) {
navigation.navigate("AppUpdate");
}
});
}
};
const loadCarouselList = () => {
dispatch({
type: "home/fetchCarouselList"
});
};
const loadCommendList = (refreshing: boolean, callback?: () => void) => {
dispatch({
type: "home/fetchCommendList",
payload: {
refreshing
},
callback
});
};
const renderSectionHeader = ({ section: { title } }: any) => {
return (
<View style={styles.sectionHeader}>
<View style={styles.cell} />
<Text style={styles.classifyName}>{title}</Text>
</View>
);
};
const onRefresh = () => {
loadCarouselList();
loadCommendList(true);
};
const onEndReached = () => {
if (!hasMore || loading) {
return;
}
setEndReached(true);
loadCommendList(false, () => {
setEndReached(false);
});
};
const renderFooter = () => {
if (endReached) {
return <More />;
}
if (!hasMore) {
return <End />;
}
return null;
};
const goBrief = useCallback((data: IBook) => {
navigation.navigate("Brief", {
id: data.id
});
}, []);
const renderItem = ({ item }: SectionListRenderItemInfo<IBook[]>) => {
return (
<View style={styles.contentContainer}>
{item.map(data => {
return (
<BookCover data={data} goBrief={goBrief} key={data.id} />
);
})}
</View>
);
};
const getTopBarColor = useCallback(() => {
return scrollY.interpolate({
inputRange: [0, maxScroll],
outputRange: [0, 1],
extrapolate: "clamp"
});
}, []);
const TopBarColor = getTopBarColor();
return (
(loading && refreshing) ? <HomePlaceholder /> :
<View style={{ flex: 1 }}>
<CarouselBlurBackground />
<TopBarWrapper navigation={navigation} topBarColor={TopBarColor} />
<SectionList
keyExtractor={(item, index) => `item-${item["id"]}-key-${index}`}
ListHeaderComponent={() => <Carousel />}
renderSectionHeader={renderSectionHeader}
onRefresh={onRefresh}
refreshing={refreshing}
sections={commendList}
stickySectionHeadersEnabled={true}
scrollEventThrottle={1}
onScroll={Animated.event(
[{
nativeEvent: { contentOffset: { y: scrollY } }
}],
{
useNativeDriver: false
}
)}
onEndReached={onEndReached}
onEndReachedThreshold={0.1}
renderItem={renderItem}
extraData={endReached}
ListFooterComponent={renderFooter}
/>
</View>
);
}
Example #11
Source File: SearchBar.tsx From krmanga with MIT License | 4 votes |
function SearchBar({ navigation, dispatch, searchTitle }: IProps) {
const headerHeight = useHeaderHeight();
const onSubmitEditing = () => {
if (searchTitle.length > 0) {
dispatch({
type: "search/setState",
payload: {
showBookView: true
}
});
dispatch({
type: "search/fetchBookList",
payload: {
title: searchTitle,
refreshing: true
},
addSearch: (isAdd: boolean) => {
if (isAdd) {
dispatch({
type: "search/addSearch",
payload: {
title: searchTitle
}
});
}
}
});
}
};
const debounce = (cb: any, wait: number) => {
let timeout = tempTimeout;
if (timeout !== null) {
clearTimeout(timeout);
}
tempTimeout = setTimeout(() => {
tempTimeout = null;
cb && cb();
}, wait);
};
const onChangeText = (title: string) => {
dispatch({
type: "search/setState",
payload: {
searchTitle: title
}
});
if (title && title.length > 0) {
debounce(() => loadData(title), 500);
} else {
dispatch({
type: "search/setState",
payload: {
showSimpleView: false,
showBookView: false
}
});
if (tempTimeout !== null) {
clearTimeout(tempTimeout);
}
}
};
const cleanTitle = useCallback(() => {
dispatch({
type: "search/setState",
payload: {
searchTitle: "",
showSimpleView: false,
showBookView: false
}
});
}, []);
const loadData = (title: string) => {
dispatch({
type: "search/fetchSimpleList",
payload: {
searchTitle: title
}
});
};
return (
<View style={[styles.wrapper, { height: headerHeight + 15 }]}>
<View style={styles.container}>
<View style={styles.leftView}>
<Icon name="icon-search" style={styles.searchIcon} size={18} />
<TextInput style={styles.searchInput}
onSubmitEditing={onSubmitEditing}
maxLength={20}
placeholder={"搜索关键字..."}
onChangeText={(text) => {
onChangeText(text);
}}
value={searchTitle}
/>
<Touchable onPress={cleanTitle}>
<Icon name="icon-chacha" style={styles.cleanTitle} size={18} />
</Touchable>
</View>
<Touchable onPress={() => navigation.goBack()}>
<View style={styles.rightView}>
<Text>取消</Text>
</View>
</Touchable>
</View>
</View>
);
}
Example #12
Source File: index.tsx From lets-fork-native with MIT License | 4 votes |
export default function Details(props: Props): React.ReactElement {
const headerHeight = useHeaderHeight()
const { restaurant: defaultRestaurant, photos } = props
const [restaurant, setRestaurant] = React.useState(defaultRestaurant)
React.useEffect(() => {
const fetchData = async (): Promise<void> => {
// More details about the restaurant can be fetched from
// the server. This can be triggered off a feature flag in the future.
// For the time being this saves on api requests to yelp.
if (false) { // eslint-disable-line
try {
const rest = await getRestaurant(defaultRestaurant.id)
setRestaurant({
...rest,
...defaultRestaurant,
})
} catch (err) {
console.log(err)
}
} else {
setRestaurant(defaultRestaurant)
}
}
fetchData()
}, [defaultRestaurant])
const imageHeight = env.ADS
? height - headerHeight - 50
: height - headerHeight
const images = [(
<Image
key={restaurant.image_url}
style={{
...styles.image,
height: imageHeight,
}}
source={{ uri: restaurant.image_url, cache: 'force-cache' }}
/>
)]
if (restaurant.photos?.length) {
restaurant.photos.forEach((url) => {
if (url !== restaurant.image_url) {
images.push(
<Image
key={url}
style={{
...styles.image,
height: imageHeight,
}}
source={{ uri: url, cache: 'force-cache' }}
/>,
)
}
})
}
return (
<View
style={{
...styles.container,
minHeight: (height - headerHeight) * 0.8,
}}
>
{
photos ? (
<ScrollView
horizontal
alwaysBounceHorizontal={false}
showsHorizontalScrollIndicator
scrollEventThrottle={10}
pagingEnabled
onScroll={
Animated.event(
[{ nativeEvent: { contentOffset: { x: new Animated.Value(0) } } }],
{ useNativeDriver: true },
)
}
>
{images}
</ScrollView>
) : null
}
<View>
<Text style={[styles.text, styles.name]}>{restaurant.name}</Text>
<View style={styles.rating}>
<Rating rating={restaurant.rating} size="sm" />
<Text style={styles.text}>{`• ${restaurant.review_count} reviews`}</Text>
</View>
<Text
style={styles.text}
>
{
restaurant.price
? `${restaurant.price} • ${restaurant?.categories?.map((c) => c.title).join(', ')}`
: restaurant?.categories?.map((c) => c.title).join(', ')
}
</Text>
{ restaurant?.transactions?.length
? (
<Text style={styles.text}>
{restaurant.transactions.map((tran) => `${tran[0].toUpperCase()}${tran.replace('_', ' ').substring(1)}`).join(' • ')}
</Text>
) : null}
</View>
<View style={styles.section}>
<TouchableOpacity onPress={(): void => call(restaurant.display_phone)}>
<MaterialIcons name="phone" size={32} />
</TouchableOpacity>
<TouchableOpacity onPress={(): Promise<any> => Linking.openURL(restaurant.url)}>
<FontAwesome name="yelp" size={32} color={colors.yelpRed} />
</TouchableOpacity>
</View>
{
restaurant?.coordinates?.latitude && restaurant?.coordinates?.longitude
? (
<View style={styles.mapContainer}>
<MapView
region={{
latitude: restaurant.coordinates.latitude,
longitude: restaurant.coordinates.longitude,
latitudeDelta: 0.005,
longitudeDelta: 0.05,
}}
style={styles.map}
rotateEnabled={false}
scrollEnabled={false}
zoomEnabled={false}
>
<Marker
coordinate={{
latitude: restaurant.coordinates.latitude,
longitude: restaurant.coordinates.longitude,
}}
title={restaurant.name}
/>
</MapView>
</View>
) : null
}
<TouchableOpacity
style={styles.section}
onPress={(): void => {
const url = Platform.select({
ios: `maps:0,0?q=${restaurant.coordinates.latitude},${restaurant.coordinates.longitude}`,
android: `geo:0,0?q=${restaurant.coordinates.latitude},${restaurant.coordinates.longitude}`,
})
if (url) {
Linking.openURL(url)
}
}}
>
<Text style={styles.directionText}>Get Directions</Text>
<MaterialIcons name="directions" size={32} />
</TouchableOpacity>
{
restaurant.hours
? <Hours hours={restaurant.hours} />
: null
}
</View>
)
}
Example #13
Source File: PartyScreen.tsx From lets-fork-native with MIT License | 4 votes |
PartyScreen = React.memo((props: Props) => {
const {
navigation, party, route, setParty, ws,
} = props
const [snapIndex, setSnapIndex] = React.useState(2)
const [finished, setFinished] = React.useState<boolean>(false)
const [restaurants, setRestaurants] = React.useState<Restaurant[]>()
const headerHeight = useHeaderHeight()
const viewHeight = env.ADS ? height - headerHeight - 50 : height - headerHeight
if (party?.error) {
Alert.alert(
'Yike! Something went wrong',
party.error,
[
{
text: 'OK',
onPress: (): void => {
navigation.navigate('Home')
setParty({} as Party)
},
},
],
{ cancelable: false },
)
}
// Request more cards with 3 remaining to prevent
// having to show loader
React.useEffect(() => {
if (restaurants && restaurants?.length === 3) {
ws.send(JSON.stringify({ type: 'request-more' }))
}
}, [restaurants, restaurants?.length, ws])
// Deep linking will open the app to the party screen
// but the party still needs to be joined
React.useEffect(() => {
if (route?.params?.id) {
ws.send(JSON.stringify({ type: 'join', payload: { party_id: route?.params?.id } }))
}
}, [route?.params?.id, ws])
// When anyone requests more cards, they are set in current
// and this useEffect loads the new cards into the restaurants array
const prevState = usePrevious(party || {} as Party)
React.useEffect(() => {
if (JSON.stringify(prevState.current) !== JSON.stringify(party?.current)) {
if (party?.current?.length && restaurants) {
const res = [...restaurants, ...party?.current]
setRestaurants(res)
}
}
}, [party, prevState, restaurants])
// Custom android back button
useFocusEffect( // eslint-disable-line
React.useCallback(() => {
const onBackPress = (): boolean => {
Alert.alert(
'Are you sure you want to exit?',
'Exiting will make you lose all data in this party',
[
{ text: 'Cancel' },
{
text: 'OK',
onPress: (): void => {
ws.send(JSON.stringify({ type: 'quit' }))
navigation.navigate('Home')
setParty({} as Party)
},
},
],
{ cancelable: true },
)
return true
}
BackHandler.addEventListener('hardwareBackPress', onBackPress)
return (): void => BackHandler.removeEventListener('hardwareBackPress', onBackPress)
}, [navigation, setParty, ws]),
)
const handleSwipeRight = (id: string): void => {
ws.send(JSON.stringify({ type: 'swipe-right', payload: { restaurant_id: id } }))
}
if (party?.status === 'waiting') {
return <Share party={party} ws={ws} />
}
if (finished || party?.total === 0) {
return (
<View
style={{
...styles.waiting,
height: viewHeight,
}}
>
<Text style={styles.text}>
No more restaurants.
Go through the list again or try expanding your search range.
</Text>
<Button
size="sm"
color="purple"
onPress={(): void => {
setFinished(false)
setRestaurants(party?.restaurants)
}}
>
START OVER
</Button>
</View>
)
}
if (!party || !party.restaurants) {
return (
<View
style={{
...styles.waiting,
height: viewHeight,
}}
>
<ActivityIndicator size="large" />
</View>
)
}
const current = restaurants?.length
? restaurants[0] : party.restaurants[0]
return (
<SafeAreaView style={styles.container}>
<View
// disable swiping while BottomSheet is open
pointerEvents={snapIndex !== 2 ? 'none' : 'auto'}
style={{ height: viewHeight, zIndex: 0 }}
>
<SwipeWindow
handleSwipeRight={handleSwipeRight}
restaurants={restaurants || party.restaurants}
setFinished={setFinished}
setRestaurants={setRestaurants}
/>
</View>
<ScrollBottomSheet
componentType="ScrollView"
contentContainerStyle={styles.scrollBottomSheet}
snapPoints={[100, 100, viewHeight - BOTTOM_BAR_HEIGHT]}
initialSnapIndex={2}
onSettle={setSnapIndex}
renderHandle={(): React.ReactElement => <Handle />}
animationConfig={{
duration: 100,
}}
>
<Details restaurant={current} />
</ScrollBottomSheet>
</SafeAreaView>
)
})