javascript - react native : Touchable Opacity element is clickable on iOS but not Android

标签 javascript android reactjs react-native expo

我正在开发一个带有 typeahead 组件的 React Native 应用程序。预先输入会显示覆盖路线上其他内容的选项(请参见下右图)。当用户单击这些选项之一时,onPress 监听器将运行一个函数:

enter image description here

这一切在 iOS 上运行得很好。但在 Android 上,永远不会收到 onPress 事件。更奇怪的是,当我尝试单击列表中较低的选项(例如美国马萨诸塞州波士顿)时,按下选项下方的卡片(杰尔巴岛)会收到 onPress 事件。 p>

有谁知道什么可能会导致这种行为?对于其他人可以就此查询提供的任何见解,我将非常感激。

以下是“浏览” View 和预输入组件的代码。

探索.js

import React from 'react'
import { connect } from 'react-redux'
import { Text, View, ScrollView, TouchableOpacity } from 'react-native'
import { gradients, sizing } from '../../style'
import { LinearGradient } from 'expo-linear-gradient'
import { MountainHero } from '../Heros'
import { CardRow } from '../Card'
import Loading from '../Loading'
import { setExploreSearch, onExploreTypeaheadClick } from '../../actions/locations'
import { Typeahead } from '../Typeahead'

const styles = {
  container: {
    flex: 1,
    flexDirection: 'column',
  },
  scrollView: {
    paddingBottom: sizing.margin,
  },
  loadingContainer: {
    position: 'absolute',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 100,
    elevation: 100,
    top: 53,
    width: '100%',
  },
  typeahead: {
    margin: sizing.margin,
    marginBottom: 0,
    width: sizing.screen.width - (2*sizing.margin),
    zIndex: 100,
    elevation: 100,
  }
}

const Explore = props => {
  const { authenticated: a, spotlight, loading } = props;
  let r = (a.recommendedLocations || []);
  if (!r || !spotlight) return null;
  // remove spotlight locations from the recommended locations
  const ids = spotlight.map(i => i.guid);
  const recommended = r.filter(i => ids.indexOf(i.guid) == -1);
  return (
    <LinearGradient style={styles.container} colors={gradients.teal}>
      <ScrollView contentContainerStyle={styles.scrollView}>
        {loading && (
          <View style={styles.loadingContainer}>
            <Loading />
          </View>
        )}
        <MountainHero text='Explore' />
        <Typeahead
          style={styles.typeahead}
          placeholder='Search Cities'
          value={props.exploreSearch}
          onChange={props.setExploreSearch}
          vals={props.exploreTypeahead}
          valKey={'place_id'}
          onTypeaheadClick={props.onExploreTypeaheadClick}
        />
        <CardRow
          text='Explore Places'
          cards={recommended}
          type='location' />
        <CardRow
          text='In the Spotlight'
          cards={spotlight}
          type='location' />
      </ScrollView>
    </LinearGradient>
  )
}

const mapStateToProps = state => ({
  authenticated: state.users.authenticated,
  spotlight: state.locations.spotlight,
  exploreSearch: state.locations.exploreSearch,
  exploreTypeahead: state.locations.exploreTypeahead,
  loading: state.locations.loading,
})

const mapDispatchToProps = dispatch => ({
  setExploreSearch: s => dispatch(setExploreSearch(s)),
  onExploreTypeaheadClick: val => dispatch(onExploreTypeaheadClick(val)),
})

export default connect(mapStateToProps, mapDispatchToProps)(Explore)

Typeahead.js

import React from 'react'
import { Text, View, TouchableOpacity } from 'react-native'
import { sizing, GradientInput } from '../style'

const styles = {
  container: {
    position: 'absolute',
    zIndex: 100,
    elevation: 100,
    height: 400,
    width: '100%',
  },
  input: {
    width: '100%',
    borderRadius: 0,
  },
  typeaheadContainer: {
    position: 'absolute',
    zIndex: 100,
    elevation: 100,
    top: 55,
    width: '100%',
  },
  typeaheadRow: {
    padding: 10,
    paddingTop: 12,
    paddingBottom: 12,
    borderWidth: 1,
    borderColor: '#eeeeee',
    backgroundColor: '#ffffff',
    marginBottom: -1,
  },
  typeaheadRowText: {
    fontSize: 15,
    fontFamily: 'open-sans',
    lineHeight: 20,
    backgroundColor: '#ffffff',
  },
}

export const Typeahead = props => {
  return (
    <View style={[props.container, props.style]}>
      <GradientInput style={styles.input}
        placeholder={props.placeholder}
        value={props.value}
        onChange={props.onChange} />
      <TypeaheadList vals={props.vals}
        valKey={props.valKey}
        onTypeaheadClick={props.onTypeaheadClick} />
    </View>
  )
}

export const TypeaheadList = props => {
  if (!props.vals) return null;
  return (
    <View style={styles.typeaheadContainer}>
      {props.vals.map(i => {
        let text = i.text;
        if (text.length > 31) text = text.substring(0,31) + '...';
        return (
          <TouchableOpacity activeOpacity={0.5} key={i[props.valKey]}
            style={styles.typeaheadRow}
            onPress={() => props.onTypeaheadClick(i[props.valKey])}>
            <Text numberOfLines={1} style={styles.typeaheadRowText}>{text}</Text>
          </TouchableOpacity>
        )
      })}
    </View>
  )
}

export default Typeahead

最佳答案

尝试将 Typeahead 组件移动到所有 CardRow 组件下​​方,并为 Typeahead 设置position:absolute。可能在 Android 上 - 最新的 View 隐藏了之前的所有 View (我不确定,但我认为你必须尝试一下才能发现下一个问题)。

您还应该从除一个组件之外的所有组件中删除 position:absolute。工作代码:

探索.js

import React from 'react'
import { connect } from 'react-redux'
import { Text, View, ScrollView, TouchableOpacity } from 'react-native'
import { gradients, sizing } from '../../style'
import { LinearGradient } from 'expo-linear-gradient'
import { MountainHero } from '../Heros'
import { CardRow } from '../Card'
import Loading from '../Loading'
import { setExploreSearch, onExploreTypeaheadClick } from '../../actions/locations'
import { Typeahead } from '../Typeahead'
const styles = {
  container: {
    flex: 1,
    flexDirection: 'column',
  },
  scrollView: {
    paddingBottom: sizing.margin,
  },
  loadingContainer: {
    position: 'absolute',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 1,
    elevation: 1,
    top: 53,
    width: '100%',
  },
  topCardRow: {
    paddingTop: sizing.margin + sizing.gradientInput.height,
  },
  typeahead: {
    margin: sizing.margin,
    marginBottom: 0,
    width: sizing.screen.width - (2*sizing.margin),
    zIndex: 1,
    elevation: 1,
    position: 'absolute',
    top: sizing.mountainHero.height,
    left: 0,
  }
}
const Explore = props => {
  const { authenticated: a, spotlight, loading } = props;
  let r = (a.recommendedLocations || []);
  if (!r || !spotlight) return null;
  // remove spotlight locations from the recommended locations
  const ids = spotlight.map(i => i.guid);
  const recommended = r.filter(i => ids.indexOf(i.guid) == -1);
  return (
    <LinearGradient style={styles.container} colors={gradients.teal}>
      <ScrollView contentContainerStyle={styles.scrollView}>
        {loading && (
          <View style={styles.loadingContainer}>
            <Loading />
          </View>
        )}
        <MountainHero text='Explore' />
        <CardRow
          style={styles.topCardRow}
          text='Explore Places'
          cards={recommended}
          type='location' />
        <CardRow
          text='In the Spotlight'
          cards={spotlight}
          type='location' />
        <Typeahead
          style={styles.typeahead}
          placeholder='Search Cities'
          value={props.exploreSearch}
          onChange={props.setExploreSearch}
          vals={props.exploreTypeahead}
          valKey={'place_id'}
          onTypeaheadClick={props.onExploreTypeaheadClick}
        />
      </ScrollView>
    </LinearGradient>
  )
}
const mapStateToProps = state => ({
  authenticated: state.users.authenticated,
  spotlight: state.locations.spotlight,
  exploreSearch: state.locations.exploreSearch,
  exploreTypeahead: state.locations.exploreTypeahead,
  loading: state.locations.loading,
})
const mapDispatchToProps = dispatch => ({
  setExploreSearch: s => dispatch(setExploreSearch(s)),
  onExploreTypeaheadClick: val => dispatch(onExploreTypeaheadClick(val)),
})
export default connect(mapStateToProps, mapDispatchToProps)(Explore)

Typeahead.js

import React from 'react'
import { Text, View, TouchableOpacity } from 'react-native'
import { sizing, GradientInput } from '../style'

const styles = {
  container: {
    zIndex: 1,
    elevation: 1,
    height: 400,
    width: '100%',
  },
  input: {
    width: '100%',
    borderRadius: 0,
  },
  typeaheadContainer: {
    zIndex: 1,
    elevation: 1,
    top: 0,
    width: '100%',
  },
  typeaheadRow: {
    padding: 10,
    paddingTop: 12,
    paddingBottom: 12,
    borderWidth: 1,
    borderColor: '#eeeeee',
    backgroundColor: '#ffffff',
    marginBottom: -1,
    zIndex: 1,
    elevation: 1,
  },
  typeaheadRowText: {
    fontSize: 15,
    fontFamily: 'open-sans',
    lineHeight: 20,
    backgroundColor: '#ffffff',
  },
}

export const Typeahead = props => {
  return (
    <View style={[props.container, props.style]}>
      <GradientInput style={styles.input}
        placeholder={props.placeholder}
        value={props.value}
        onChange={props.onChange} />
      <TypeaheadList vals={props.vals}
        valKey={props.valKey}
        onTypeaheadClick={props.onTypeaheadClick} />
    </View>
  )
}

export const TypeaheadList = props => {
  if (!props.vals) return null;
  return (
    <View style={styles.typeaheadContainer}>
      {props.vals.map(i => {
        let text = i.text;
        if (text.length > 31) text = text.substring(0,31) + '...';
        return (
          <TouchableOpacity activeOpacity={0.5} key={i[props.valKey]}
            style={styles.typeaheadRow}
            onPress={() => props.onTypeaheadClick(i[props.valKey])}>
            <Text numberOfLines={1} style={styles.typeaheadRowText}>{text}</Text>
          </TouchableOpacity>
        )
      })}
    </View>
  )
}

export default Typeahead

关于javascript - react native : Touchable Opacity element is clickable on iOS but not Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60252763/

相关文章:

javascript - 如何在单击按钮时更新 useEffect() Hook 的值

javascript - 如何使用 Javascript 在我的 HTML 页面中获取输出

android - 正确使用 fragment

javascript - handleClick 函数不适用于父组件?

javascript - React setState 改变子进程的 props

java - 如何在Android中实现持久队列

javascript - 如何在我的应用程序中组织 jQuery

javascript - 在函数内获取 post 变量

javascript - 如何从数组中为 div 提供随机背景颜色

java - Android Studio 解析 JSON 时出现问题