Quantcast
Channel: Active questions tagged react-native+android - Stack Overflow
Viewing all articles
Browse latest Browse all 29594

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

$
0
0

I'm working on a React Native app with a typeahead component. The typeahead displays options that overlay other content on the route (see right image below). When a user clicks one of those options, an onPress listener runs a function:

enter image description here

This all works just fine on iOS. On Android though, the onPress event is never received. Even more strangely, when I try to click on an option lower in the list (like Boston, MA, USA), the onPress event is received by the card below the pressed option (Djerba).

Does anyone know what might cause this behavior? I'd be super grateful for any insights others can offer on this query.

Here's the code for the Explore view and the typeahead components.

Explore.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

Viewing all articles
Browse latest Browse all 29594

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>