簡體   English   中英

React Native:Touchable Opacity 元素在 iOS 上可點擊,但在 Android 上不可點擊

[英]React Native: Touchable Opacity element is clickable on iOS but not Android

我正在開發帶有 typeahead 組件的 React Native 應用程序。 typeahead 顯示覆蓋路線上其他內容的選項(見下圖)。 當用戶單擊這些選項之一時,onPress 偵聽器會運行一個函數:

在此處輸入圖片說明

這一切在 iOS 上都運行良好。 但在 Android 上,永遠不會收到 onPress 事件。 更奇怪的是,當我嘗試單擊列表下方的選項(如波士頓,馬薩諸塞州,美國)時,按下選項(Djerba)下方的卡片收到 onPress 事件。

有誰知道什么可能導致這種行為? 對於其他人可以就此查詢提供的任何見解,我將不勝感激。

下面是 Explore 視圖和 typeahead 組件的代碼。

探索.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)

預先輸入.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 上 - 最新的視圖遮蔽了之前的所有視圖(我不確定,但我認為您必須嘗試使用​​它才能發現下一個問題)。

您還應該從除一個組件之外的所有組件中刪除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)

預先輸入.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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM