React Native Overflow Touchable is Not Working in Android

前端 未结 3 1083
[愿得一人]
[愿得一人] 2021-01-20 21:18

Please have a look at my Expo Snack.

Dropdown items are touchable in iOS but not in Android. Fixed container\'s height (grey box) causes this issue but I need to kee

3条回答
  •  悲哀的现实
    2021-01-20 22:00

    I wouldn't use a dependency instead I would manage it myself.

    1. Create a component called DropDown that covers the whole screen with an absolute position (so that it doesn't affect the position of other elements on the screen). This component is invisible when inactive.
    2. When the button is pressed its position is measured in the view and this is then passed to the DropDown component.
    3. With its props updated the DropDown component re-renders and a small menu is displayed in close proximity to the original button that was pressed.
    4. Tapping on an item in the menu calls back to the main component, and changes the visibility of the DropDown back to being invisible.
    5. Tapping on the background also calls back to the main component, and changes the visibility of the DropDown back to being invisible.

    Here is the code, but I have also put it in a snack for you to play with https://snack.expo.io/@andypandy/dropdownmenu

    There are lots of possibilities that you could do with this. You could pass in children as props, you could hook it in to redux and set it at the root of your app so that it can be used anywhere. The styles can easily be changed. It really is quite flexible in what you can do with it. I have used this in many applications that are currently live in both app stores.

    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 (
          
            
               {this.button = ref}}
                onPress={this.showDropDown}
                title={'Menu'}
              />
            
              {/* Anything to be rendered below the DropDown should appear before the DropDown. So for best performance all components should go here. */}
            
              {/* 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. */}
          
        )
      }
    }
    
    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 (
             this.props.hide('background pressed')}>
              
                  
    
                   this.props.hide('Item 1')}>
                    Item 1
                  
    
                   this.props.hide('Item 2')}>
                    Item 2
                  
    
                   this.props.hide('Item 3')}>
                    Item 3
                  
    
                   this.props.hide('Item 4')}>
                    Item 4
                  
                  
              
            
          );
        } 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 (
          
            
              {this.props.title}
            
          
        )
      }
    }
    
    const styles = StyleSheet.create({
      button: {
        backgroundColor: '#336699', 
        padding: 10, 
        borderRadius: 5
      }
    });
    

提交回复
热议问题