问题
I'm using a react-native router with Flexbox. I would like to show FlatList taking the full screen and sticky footer in the end. I tried to specify flexGrow: 1
for FlatList, and flexShrink: 0
for View footer, but it doesn't work. I'm building the app in Expo and check result on iPhone.
import React, {Component} from 'react';
import {
Text,
View,
FlatList,
} from 'react-native'
import {Provider} from 'react-redux'
import {NativeRouter, Route, Link} from 'react-router-native'
export default class App extends Component {
render() {
return <NativeRouter>
<View style={{
display: "flex",
flexDirection: "column",
padding: 10,
}}>
<View style={{
display: "flex",
flexDirection: 'row',
justifyContent: 'space-around'
}}>
<Link
to="/lobby"
underlayColor='#f0f4f7'
style={{
flex: 8,
alignItems: 'center',
padding: 10,
}}>
<Text>Lobby</Text>
</Link>
<Link
to="/"
underlayColor='#f0f4f7'
style={{
flex: 2,
alignItems: 'center',
padding: 10,
}}>
<Text>Home</Text>
</Link>
</View>
<Route exact path="/" component={Home}/>
<Route path="/lobby" component={Lobby}/>
</View>
</NativeRouter>
}
}
const Home = () => (
<Text>
Home
</Text>
);
class Lobby extends Component {
render() {
return <View style={{
flexGrow: 1,
flexDirection: "column",
// justifyContent: "space-between"
}}>
<FlatList
style={{
flexGrow: 1,
}}
data={[
{key: 'Spring Game'},
{key: 'Summer Game'},
{key: 'Fall Game'},
{key: 'Winter Game'},
]}
renderItem={({item}) => <Text style={{
display: "flex",
flex: 1,
padding: 10,
fontSize: 18,
height: 44,
alignContent: "center"
}}>{item.key}</Text>}
/>
<View style={{
display: "flex",
flexDirection: "row",
backgroundColor: "#848441",
flexShrink: 0,
}}>
<Text style={{
flex: 6,
alignSelf: "flex-end"
}}>Footer</Text>
</View>
</View>
}
}
回答1:
First of all, good luck :) If your "stickyness logic" isn't as simple as "just stay always to the bottom" you're going to have to start listening to scrolls and resizes...
Anyway, I needed a Sticky component for my react app, and this is how it worked for me. It's react-dom so a bit different but as far as CSS is concerned it should be fine.
First, set its parent element to have position: "relative"
, which will allow its children to be position absolutely based on the parent.
This parent element should wrap around all of your available area.
So you parent View component's style is almost ok, just add flexBasis: 0
if it's not already occupying all of the available area, and position: "relative"
.
Set Sticky component itself (child View) to display: "block"
, have position: "absolute"
, and overflow
to anything but visible. And techincally, it's sticky already.
Then add bottom: 0
to your sticky, and your component should already be sticking to the bottom - now you just have to manage its width and horizontal position, with any property or tool you like.
I tried to solve this with flexbox rules only, but it seems like the best way to approach this is position="relative"
and position="absolute"
You should also note that after this, the really fun part of Sticky boxes starts, because based on the actual location of your sticky you may have to add some js to handle special cases. Example: now the sticky box will cover your content, I think. Additional white space should be added to the bottom of the page so that you can actually scroll down enough to see the bottom of your content.
Additional note: I know if you combine display: "flex"
and position: "relative"
, it's handled in a peculiar way. Not sure what exactly is different, but block and flex behave a bit differently when assigned position="relative". If you see weirdness in your layout, try adding a wrapper between your flex view and block sticky, a block/relative wrapper, to normalize behaviour.
My classes simplified, this was for a sticky sidebar:
.StickyBox {
overflow: auto;
position: absolute;
height: inherit;
}
.sidebarWrapper {
flex: 1;
position: relative;
}
来源:https://stackoverflow.com/questions/50387589/how-to-make-sticky-footer-with-flexbox-and-react