React Native Overflow Touchable在Android中不起作用

时间:2019-02-04 09:48:03

标签: android facebook react-native expo

请看看我的Expo Snack

下拉菜单在iOS中是可触摸的,但在Android中不可触摸。固定容器的高度(灰色框)会导致此问题,但我需要为工具栏保持固定高度。

我尝试使用react-native-view-overflow软件包,但没有运气。它需要react-native link,同时我无法退出项目,因为我正在使用一些Expo软件包,如果退出,这些软件包会被破坏。

有没有建议让下拉菜单在Android中可触摸?

enter image description here

3 个答案:

答案 0 :(得分:0)

我更改了您的代码,请检查:Snack link

这可以解决您的问题,但是您可以更新您的react-native版本,使其包含此commit,从而增加对Android React Native上function removeSpecialCharacters(metadata) { const result = metadata.map(datum => { const cleanId = datum.id.replace(/\W+/g, '') return { ...datum, id: cleanId } }) return result } const data = [{id: "someth+in%g#", apple: "dfgdf efd"}, {id: 'some%@%"<>+#', apple: "dfgdf efd"}]; console.log(removeSpecialCharacters(data));样式属性的支持。

答案 1 :(得分:0)

我不会使用依赖项,而是由我自己管理。

  1. 创建一个名为DropDown的组件,该组件以绝对位置覆盖整个屏幕(这样就不会影响屏幕上其他元素的位置)。处于非活动状态时,此组件不可见。
  2. 按下按钮时,将在视图中测量其位置,然后将其传递到DropDown组件。
  3. 更新道具后,DropDown组件会重新显示,并且会在与按下的原始按钮非常接近的位置显示小菜单
  4. 在菜单中的某个项目上点击可调用主要组件,并将DropDown的可见性更改为不可见。
  5. 在后台点击还会回调主组件,并将DropDown的可见性更改为不可见。

这里是代码,但我也把它放进了小吃中,让您可以https://snack.expo.io/@andypandy/dropdownmenu

您可以使用此方法进行多种操作。您可以传入儿童作为道具,也可以将其挂接到redux并将其设置在应用程序的根目录,以便可以在任何地方使用。样式可以轻松更改。在使用它时,它确实非常灵活。我已经在两个应用程序商店中目前都存在的许多应用程序中使用了此功能。

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
  }
});

答案 2 :(得分:0)

当下拉列表扩展时,由于您已设置了固定高度,因此它似乎不可见。

因此,要解决此问题,可以使用minHeight属性而不是height

这将确保至少获得最小高度,并且在需要时可以使用更大的高度,例如在展开下拉菜单时。

更正如下,

dropdownContainer: {
    width:340,
    minHeight:115,// changed this from height:115
    ...
    ...
  },