Я бы не использовал зависимость вместо того, чтобы управлять ею сам.
- Создайте компонент с именем
DropDown
, который покрывает весь экран с абсолютной позицией (чтобы он не влиял на положение других элементов на экране).Этот компонент невидим, когда неактивен. - Когда кнопка нажата, ее положение измеряется в представлении, а затем передается компоненту
DropDown
. - С обновленными реквизитами компонент
DropDown
выполняет рендеринг и маленькое меню отображается в непосредственной близости от исходной кнопки, которая была нажата. - Нажатие на элемент в меню вызывает возврат к основному компоненту и изменяет видимость DropDown на то, что он становится невидимым.
- Нажатие на фон также вызывает возврат к основному компоненту,и изменяет видимость DropDown обратно на невидимость.
Вот код, но я также положил его в закуску, чтобы вы могли поиграть с https://snack.expo.io/@andypandy/dropdownmenu
ТамЕсть много возможностей, которые вы могли бы сделать с этим.Вы можете передать детей в качестве реквизита, вы можете подключить его к редуксу и установить его в корне вашего приложения, чтобы его можно было использовать где угодно.Стили могут быть легко изменены.Это действительно довольно гибко в том, что вы можете сделать с нимЯ использовал это во многих приложениях, которые в настоящее время живут в обоих магазинах приложений.
App.js
import React from 'react';
import {
Text,
View,
StyleSheet,
UIManager,
findNodeHandle,
TouchableOpacity
} from 'react-native';
// import components
import DropDown from './DropDown';
import MyButton from './MyButton';
export default class App extends React.Component {
state = {
show: false,
position: {}
}
// handle showing the dropdown
showDropDown = () => {
if (this.button) {
// use the uimanager to measure the button's position in the window
UIManager.measure(findNodeHandle(this.button), (x, y, width, height, pageX, pageY) => {
const position = { left: pageX, top: pageY, width: width, height: height };
// setState, which updates the props that are passed to the DropDown component
this.setState({show: true, position: { x: pageX + (width / 2), y: pageY + (2 * height / 3) }})
});
}
}
// hide the dropdown
hideDropDown = (item) => {
alert(item)
this.setState({show: false, position: {}})
}
render() {
return (
<View style={styles.container}>
<View style={{height: 100, width: 300, backgroundColor: 'yellow', alignItems: 'center', justifyContent: 'center'}}>
<MyButton
ref={ref => {this.button = ref}}
onPress={this.showDropDown}
title={'Menu'}
/>
</View>
{/* Anything to be rendered below the DropDown should appear before the DropDown. So for best performance all components should go here. */}
<DropDown show={this.state.show} position={this.state.position} hide={this.hideDropDown}/>
{/* If you place a component here, it will appear above the DropDown and may interfere with how the DropDown works. You should not put anything here. */}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
}
});
DropDown.js
import React from 'react';
import { Text, View, StyleSheet, TouchableWithoutFeedback, TouchableOpacity} from 'react-native';
export default class DropDown extends React.Component {
render() {
if (this.props.show) {
const { y: top, x: left } = this.props.position;
const width = 100;
return (
<TouchableWithoutFeedback onPress={() => this.props.hide('background pressed')}>
<View style={styles.container}>
<View style={[styles.menu, { top, left: left - width/2, width}]}>
<TouchableOpacity style={{width, alignItems: 'center', paddingTop: 5}} onPress={() => this.props.hide('Item 1')}>
<Text>Item 1</Text>
</TouchableOpacity>
<TouchableOpacity style={{width, alignItems: 'center', paddingTop: 5}} onPress={() => this.props.hide('Item 2')}>
<Text>Item 2</Text>
</TouchableOpacity>
<TouchableOpacity style={{width, alignItems: 'center', paddingTop: 5}} onPress={() => this.props.hide('Item 3')}>
<Text>Item 3</Text>
</TouchableOpacity>
<TouchableOpacity style={{width, alignItems: 'center', paddingVertical: 5}} onPress={() => this.props.hide('Item 4')}>
<Text>Item 4</Text>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
);
} else {
return null
}
}
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0
},
menu: {
position: 'absolute',
backgroundColor: 'white',
alignItems: 'center',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 5,
},
shadowOpacity: 0.36,
shadowRadius: 6.68,
elevation: 11,
}
});
MyButton.js
import React from 'react';
import {
Text,
View,
StyleSheet,
TouchableOpacity
} from 'react-native';
export default class App extends React.Component {
render() {
return (
<TouchableOpacity onPress={this.props.onPress}>
<View style={styles.button}>
<Text style={{color: 'white'}}>{this.props.title}</Text>
</View>
</TouchableOpacity>
)
}
}
const styles = StyleSheet.create({
button: {
backgroundColor: '#336699',
padding: 10,
borderRadius: 5
}
});