简体   繁体   English

反应原生触摸事件正在通过绝对视图

[英]React native Touch events are passing through absolute view

I'm using react-navigation and I have a view that I want to show when an icon is pressed in the toolbar, I already made it using another component and setting the component to be displayed as absolute, the thing is, all touchEvents are passing through the overlay view, I tried setting zIndex and elevation on both headerRightStyle, the view that is absolute, even in another children view.我正在使用 react-navigation 并且我想在工具栏中按下图标时显示一个视图,我已经使用另一个组件制作了它并将组件设置为绝对显示,问题是,所有 touchEvents 都是通过叠加视图,我尝试在 headerRightStyle 上设置 zIndex 和高程,即使在另一个子视图中也是绝对视图。 I also tried using a TouchableWithoutFeedback as a wrapper but that didn't fix the issue either.我还尝试使用 TouchableWithoutFeedback 作为包装器,但这也没有解决问题。

This is my component这是我的组件

import React, { Component } from 'react';
import {
  View,
  Text,
  UIManager,
  LayoutAnimation,
  Dimensions,
  TouchableWithoutFeedback,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';

const styles = {
  movieFilterListContainerStyle: {
    position: 'absolute',
    bottom: -300,
    right: -10,
    height: 300,
  },
};

class MovieFilter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showFilterList: false,
      filterListWidth: 0,
    };
    this.renderFilterList = this.renderFilterList.bind(this);
    this.onShowFilterList = this.onShowFilterList.bind(this);
    this.calculateFilterListWidth = this.calculateFilterListWidth.bind(this);
  }

  componentWillMount() {
    UIManager.setLayoutAnimationEnabledExperimental(true);
    this.calculateFilterListWidth();
    Dimensions.addEventListener('change', this.calculateFilterListWidth);
  }

  componentWillUpdate() {
    LayoutAnimation.spring();
  }

  componentWillUnmount() {
    Dimensions.removeEventListener('change', () => {});
  }

  onShowFilterList() {
    const { showFilterList } = this.state;
    this.setState({ showFilterList: !showFilterList });
  }

  calculateFilterListWidth() {
    this.setState({ filterListWidth: Dimensions.get('window').width });
  }

  renderFilterList() {
    const { showFilterList, filterListWidth } = this.state;
    const { movieFilterListContainerStyle } = styles;
    if (showFilterList === true) {
      return (
        <View
          style={[
            movieFilterListContainerStyle,
            {
              width: filterListWidth,
            },
          ]}
        >
          <TouchableWithoutFeedback onPress={() => {}}>
            <View
              style={{
                flex: 1,
                backgroundColor: '#FFFFFF',
                elevation: 10,
                zIndex: 999999,
                paddingRight: 10,
                paddingLeft: 10,
                paddingTop: 10,
                paddingBottom: 10,
              }}
            >
              <View
                style={{
                  flexDirection: 'row',
                  position: 'relative',
                  justifyContent: 'space-between',
                }}
              >
                <Text>Year</Text>
                <Text>Test</Text>
              </View>
              <View style={{ flexDirection: 'row', position: 'relative' }}>
                <Text>Rating</Text>
                <Text>Test</Text>
              </View>
              <View style={{ flexDirection: 'row', position: 'relative' }}>
                <Text>Categories</Text>
                <Text>Test</Text>
              </View>
            </View>
          </TouchableWithoutFeedback>
        </View>
      );
    }
    return null;
  }

  render() {
    return (
      <View style={{ flex: 1 }}>
        <Icon name="filter-list" size={30} onPress={this.onShowFilterList} />
        {this.renderFilterList()}
      </View>
    );
  }
}

export default MovieFilter;

This is my navigator:这是我的导航器:

const MoviesTab = createStackNavigator(
  {
    MovieList: MoviesScreen,
  },
  {
    navigationOptions: ({ navigation }) => ({
      headerRight: (
        <View
          style={{
            marginLeft: 10,
            marginRight: 10,
            flexDirection: 'row',
            flex: 1,
          }}
        >
          <Icon
            onPress={navigation.getParam('logout')}
            size={30}
            name="logout-variant"
            color="#000000"
          />
          <MovieFilter />
        </View>
      ),
      headerRightContainerStyle: {
        zIndex: 20,
        elevation: 20,
      },
      headerLeft: (
        <View style={{ flex: 1, flexDirection: 'row' }}>
          <SearchBar />
        </View>
      ),
    }),
  },
);

Add pointerEvents attribute.添加pointerEvents属性。 The documentation can be found here http://facebook.github.io/react-native/docs/0.50/view#pointerevents Add the pointerEvents to this view in renderFilterList method该文件可以在这里找到http://facebook.github.io/react-native/docs/0.50/view#pointerevents添加pointerEvents这一观点在renderFilterList方法

<View
  style={[
    movieFilterListContainerStyle,
    {
      width: filterListWidth,
    },
  ]}
  pointerEvents={'box-only'}
>

This turned out to be the issue/fix for our app (see first and final comments): move the absolute element to the last element in the top view结果证明这是我们应用程序的问题/修复(请参阅第一个和最后一个评论):将绝对元素移动到顶视图中的最后一个元素

zIndex / Touch issue on Android Android 上的 zIndex / Touch 问题

When wrapping with empty TouchableWithoutFeedback , click events are not able to propagate beyond that当用空的TouchableWithoutFeedback包装时,点击事件不能传播到此之外

import { TouchableWithoutFeedback } from "react-native";

<TouchableWithoutFeedback>
  // your component
</TouchableWithoutFeedback>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM