Vince Gonzales
Vince Gonzales

Reputation: 985

React Native Android - Why is absolute positioned view outside of parent component bounds cannot be interacted with?

I am trying to implement an autocomplete input that has a scrollview below the text input when the user starts typing which contains rows of suggestions that can be pressed. The problem only occurs on Android wherein the component below the text input which has an absolute positioning cannot be pressed or scrolled since it is outside the parent container. What is the best work around on this? I already tried changing zIndex of the parent container and also the scroll view, but it still doesn't work.

Here is a snack code url if you guys wanna test: snack.expo.io/HkLeBYV18

Here is a screenshot of what I am trying to implement, the one circled with red cannot be press or anything on Android: enter image description here

Upvotes: 4

Views: 3010

Answers (3)

You can use a portal to move autocomplete view to root component. To use portals on react native you need install react-native-portal package. I have modified your code on snack to include react-native-portal

Upvotes: 1

Vishal Dhanotiya
Vishal Dhanotiya

Reputation: 2638

I have resolved your issue of pressed or scrolled searching data inside Scrollview, by adding isHideScroll state into onPress listener. isHideScroll Flag is used to show and hide Scrollview conditionally. Please check following expo snack code:-

https://snack.expo.io/@vishal7008/scroll-and-press-issue

But it is not the best approach to doing search data from list

You need to add FlatList in place of ScrollView and search data using filter function. Please check the below added example code and expo snack link.

https://snack.expo.io/@vishal7008/searching-list

import * as React from 'react';
import {
  Text,
  View,
  FlatList,
  StyleSheet,
  TextInput,
  TouchableOpacity,
} from 'react-native';

// or any pure javascript modules available in npm

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isHideList: true,
      searchText: '',
      listData: [
        {name: 'Bread'},
        {name: 'Cookies'},
        {name: 'Biscuit'},
        {name: 'Chocolate'},
      ],
      localData: [
        {name: 'Bread'},
        {name: 'Cookies'},
        {name: 'Biscuit'},
        {name: 'Chocolate'},
      ],
    };
  }

  selectOnClick = () => {
    this.setState({isHideList:false})
  };
  _renderListView = ({item, index}) => {
    return (
      <View style={styles.listItemView}>
        <TouchableOpacity onPress={() => this.selectOnClick()}>
          <Text allowFontScaling={false} style={styles.listText}>
            {item.name}
          </Text>
        </TouchableOpacity>
      </View>
    );
  };
  _searchFoodItem = value => {
    const newData = this.state.localData.filter(function(item) {
      let itemData = item.name.toUpperCase();
      let textData = value.toUpperCase();
      return itemData.startsWith(textData);
    });
    if (value == '') {
      this.setState({
        isHideList: false,
      });
    } else {
      this.setState({
        isHideList: true,
      });
    }
    this.setState({
      listData: [...newData],
    });
  };

  render() {
    return (
      <View>
        <View style={styles.selectedTagsContainer}>
          <TextInput
            style={styles.searchInput}
            placeholderTextColor="#9B6B6B"
            placeholder="Select 3 tags"
            onChangeText={text => {
              this._searchFoodItem(text);
            }}
          />
        </View>
        {this.state.isHideList && (
          <View style={styles.listStyle}>
            <FlatList
              nestedScrollEnabled={true}
              data={this.state.listData}
              keyExtractor={(item, index) => index.toString()}
              renderItem={(item, index) =>
                this._renderListView(item, index)
              }
              bounces={false}
              keyboardShouldPersistTaps="handled"
              alwaysBounceVertical={false}
            />
          </View>
        )}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  listStyle: {
    flex: 1,
    flexDirection: 'row',
    backgroundColor: '#ffffff',
    borderRadius: 2,
    position: 'absolute',
    width: '60%',
    zIndex: 1,
    marginLeft: 25,
    marginTop: 104,
    maxHeight:150,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5,
  },
  selectedTagsContainer: {
    flexDirection: 'column',
    flexWrap: 'wrap',
    marginLeft: 20,
    marginRight: 20,
    marginTop: 50,
    backgroundColor: '#F3F3F3',
    borderRadius: 10,
    alignItems: 'center',
  },
  listText: {
    padding: 10,
    width: '100%',
    color: 'black',
    marginTop: 7,
  },
  listItemView: {
    flex: 1,
    paddingLeft: 10,
  },
  searchInput: {
    width: '100%',
    height: 50,
    paddingHorizontal: 20,
    color: '#6B6B6B',
    fontSize: 10,
  },
});

Upvotes: 0

Shing Ho Tan
Shing Ho Tan

Reputation: 951

Are you open to using the custom dropdowns like

https://github.com/sohobloo/react-native-modal-dropdown https://github.com/maxkordiyak/react-native-dropdown-autocomplete#readme

Please check these libraries if you can use.

Upvotes: 0

Related Questions