React Native Overflow Touchable在Android中不起作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Native Overflow Touchable在Android中不起作用相关的知识,希望对你有一定的参考价值。

请看看我的Expo Snack

下拉项目在ios中可触摸,但在android中不可触摸。固定容器的高度(灰色框)会导致此问题,但我需要保持工具栏的固定高度。

我尝试过使用react-native-view-overflow包但没有运气。它需要react-native link,同时我无法弹出我的项目,因为我正在使用一些世博会套餐,如果我弹出将被打破。

有任何建议让Android中的下拉项目可触摸吗?

enter image description here

答案

我改变了你的代码,检查一下:Snack link

这可以解决您的问题,但您可以更新您的react-native版本以包含此commit,它在React Native for Android上添加了对overflow样式属性的支持。

另一答案

看起来当下拉展开时,它会在视图之外流动,因为您已经给出了固定的高度。

因此,对于解决方法,您可以使用minHeight属性而不是height

这将确保至少你获得最小高度,如果需要,它可以使用更多高度,就像你扩展下拉菜单时一样。

修正如下,

dropdownContainer: {
    width:340,
    minHeight:115,// changed this from height:115
    ...
    ...
  },
另一答案

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

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

以上是关于React Native Overflow Touchable在Android中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

React-Native踩坑记录二

React Native 溢出 Touchable 在 Android 中不起作用

react-native持续踩坑总结

Tips——RN canvas缩放处理

react-插槽(Portals)

react-native init 指定 react 版本和 react-native 版本