我一直在尝试调整样式和元素的渲染顺序,以使Android和iOS的行为相同。做了大量研究,当前的答案似乎无法解决问题。
问题是此确切的代码可在iOS上使用,而不能在Android设备上。
class Dropdown extends React.Component {
constructor() {
super()
this.state = {
open: false,
selected: undefined,
}
}
handleSelectPress = () => {
this.setState({open: !this.state.open});
}
handleOptionPress = (item) => {
this.setState({selected: item, open: !this.state.open});
this.props.onSelectOption(item);
}
render () {
const { selected = {}, open } = this.state
const { placeholder = '', options = [] } = this.props
return (
<Select
onPress={this.handleSelectPress}
value={selected.name || placeholder}
open={open}
options={options}
onOptionPress={this.handleOptionPress} />
)
}
}
const shadowStyles = {
ios: {
shadowOpacity: 0.3,
shadowRadius: 3,
shadowOffset: {
height: 1,
width: 1,
},
},
android: {
elevation: 5,
},
}
class Select extends React.PureComponent {
render () {
const { value, open, options, onOptionPress } = this.props
const shadowStyle = shadowStyles[Platform.OS]
return (
<View style={[shadowStyle, styles.wrap]}>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.selectContainer}>
<Text>{value}</Text>
</View>
</TouchableWithoutFeedback>
{open && <View style={styles.menu}>
{ options.map( (item, idx) => <Option value={item} key={idx} onPress={onOptionPress} />)}
</View>}
</View>
)
}
}
class Option extends React.PureComponent {
handlePress = () => {
this.props.onPress(this.props.value)
}
render () {
const { value } = this.props
return (
<TouchableOpacity onPress={this.handlePress}>
<View style={styles.optionContainer}>
<Text>{value.name}</Text>
</View>
</TouchableOpacity>
)
}
}
class App extends React.Component {
render() {
return (
<View style={styles.root}>
<Dropdown
placeholder="--- SELECT ---"
options={
[
{ name: "Press me!", id: "1" },
{ name: "No Me!", id: "2" },
{ name: "Cmon guys, here!", id: "3" },
]
}
onSelectOption={ (item) => console.log(`item pressed! ${item}`)}
/>
</View>
)
}
}
const styles = StyleSheet.create({
root: {
width: 360,
height: 640,
backgroundColor: '#292c2e'
},
wrap: {
position: 'relative',
zIndex: 10,
backgroundColor: 'rgb(73,75,77)'
},
selectContainer: {
padding: 16,
},
menu: {
backgroundColor: 'rgb(73,75,77)',
position: 'absolute',
top: '100%',
left: 0,
right: 0,
maxHeight: 300
},
optionContainer: {
padding: 16
}
});
反应本机版本-0.59.3
几件事要注意:
zIndex
,以便将菜单元素呈现在其他元素之上(在下拉组件之后呈现)。 TouchableHighlight
,TouchableOpacity
,TouchableWithoutFeedback
,并且仅适用于Android TouchableNativeFeedback
View
和ScrollView
之间更改“菜单”元素(最初是滚动)Select
上切换open
标志的触摸在Android和iOS上均正常工作,因此,我很确定它的范围缩小到了绝对定位的父级。答案 0 :(得分:2)
String errorMsg;
StreamBuilder(
stream: myStream,
builder: (BuildContext context, snapshot) {
if (snapshot.hasError) {
errorMsg = snapshot.error.toString();
}
if (errorMsg != null) {
return Text(errorMsg);
}
return new Text(
snapshot.data.toString(),
);
},
)
中的样式存在问题,而不是zIndex。
您已给styles.menu
和position:'absolute'
。
这意味着您的子视图相对于父视图处于绝对位置,并且由于top:'100%'
,您的子视图将在父视图完成后立即开始。
结论:您的选项在父项之外显示。是的,它们可见,因为下面没有其他组件,并且zIndex更高。并且您不能触摸任何不在父级范围内的东西。
在top: '100%'
中,更改以下内容:
styles.menu
您还可以删除zIndex:也可以删除1000和1005:)
答案 1 :(得分:1)
您必须为Select
而不是Option
设置职位
这是小吃:https://snack.expo.io/HkDHHo6YV
更改wrap
和menu
的样式,如下所示:
wrap: {
position: 'absolute',
zIndex: 10,
width: "100%",
backgroundColor: 'rgb(73,75,77)',
},
menu: {
backgroundColor: 'rgb(73,75,77)',
maxHeight: 300,
},
缺少的部分是要考虑下拉菜单下的空间,因为它是完全绝对定位的。我不得不更改Select
组件以呈现“ padding”元素以说明空间。
class Select extends React.PureComponent {
render() {
const { value, open, options, onOptionPress } = this.props;
const shadowStyle = shadowStyles[Platform.OS];
return (
<>
<View style={{height: 60}}></View>
<View style={[shadowStyle, styles.wrap]}>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.selectContainer}>
<Text>{value}</Text>
</View>
</TouchableWithoutFeedback>
{open && (
<View style={styles.menu}>
{options.map((item, idx) => (
<Option value={item} key={idx} onPress={onOptionPress} />
))}
</View>
)}
</View>
</>
);
}
}
然后将styles.selectContainer
的高度调整为相同的高度60
selectContainer: {
padding: 16,
height: 60
},
import * as React from 'react';
import {
Text,
Button,
View,
StyleSheet,
Platform,
TouchableWithoutFeedback,
TouchableOpacity,
} from 'react-native';
class Dropdown extends React.Component {
constructor() {
super();
this.state = {
open: false,
selected: undefined,
};
}
handleSelectPress = () => {
this.setState({ open: !this.state.open });
};
handleOptionPress = item => {
this.setState({ selected: item, open: !this.state.open });
this.props.onSelectOption(item);
};
render() {
const { selected = {}, open } = this.state;
const { placeholder = '', options = [] } = this.props;
return (
<Select
onPress={this.handleSelectPress}
value={selected.name || placeholder}
open={open}
options={options}
onOptionPress={this.handleOptionPress}
/>
);
}
}
const shadowStyles = {
ios: {
shadowOpacity: 0.3,
shadowRadius: 3,
shadowOffset: {
height: 1,
width: 1,
},
},
android: {
elevation: 5,
},
};
class Select extends React.PureComponent {
render() {
const { value, open, options, onOptionPress } = this.props;
const shadowStyle = shadowStyles[Platform.OS];
return (
<>
<View style={{height: 60}}></View>
<View style={[shadowStyle, styles.wrap]}>
<TouchableWithoutFeedback onPress={this.props.onPress}>
<View style={styles.selectContainer}>
<Text>{value}</Text>
</View>
</TouchableWithoutFeedback>
{open && (
<View style={styles.menu}>
{options.map((item, idx) => (
<Option value={item} key={idx} onPress={onOptionPress} />
))}
</View>
)}
</View>
</>
);
}
}
class Option extends React.PureComponent {
handlePress = () => {
this.props.onPress(this.props.value);
};
render() {
const { value } = this.props;
return (
<TouchableOpacity onPress={this.handlePress}>
<View style={styles.optionContainer}>
<Text>{value.name}</Text>
</View>
</TouchableOpacity>
);
}
}
export default class App extends React.Component {
render() {
return (
<View style={styles.root}>
<Dropdown
placeholder="--- SELECT ---"
options={[
{ name: 'Press me!', id: '1' },
{ name: 'No Me!', id: '2' },
{ name: 'Cmon guys, here!', id: '3' },
]}
onSelectOption={item => console.log(`item pressed! ${item}`)}
/>
<Text>hellof</Text>
<View style={{backgroundColor: "red", height: 250}} />
</View>
);
}
}
const styles = StyleSheet.create({
root: {
width: 360,
height: 640,
backgroundColor: '#292c2e',
marginTop: 100
},
wrap: {
position: 'absolute',
zIndex: 10,
width: "100%",
backgroundColor: 'rgb(73,75,77)',
},
selectContainer: {
padding: 16,
height: 60
},
menu: {
backgroundColor: 'rgb(73,75,77)',
maxHeight: 300,
},
optionContainer: {
padding: 16,
height: 60
},
});