简体   繁体   English

Scrollview 不适用于 android,但在 React Native 中适用于 iOS

[英]Scrollview not working on android, but works on iOS in react native

I want to have a scroll in the list.我想在列表中滚动。
In ios its working fine but in android scroll is not working.在 ios 中它工作正常但在 android 中滚动不工作。 In the below code, if I give height to the green view its working, but I want to achieve it without giving height to the green view, because of my usecase, it should always overlap the white text.在下面的代码中,如果我为绿色视图提供高度,但我想在不为绿色视图提供高度的情况下实现它,因为我的用例,它应该始终与白色文本重叠。

Please see the below code -请看下面的代码 -

App.tsx应用程序.tsx

import {View, Text, Alert, StyleSheet} from 'react-native';
import React, {useState} from 'react';
import SearchableDropdown from './searchableDropdown';

var items = [
  {
    id: 1,
    name: 'JavaScript',
  },
  {
    id: 2,
    name: 'Java',
  },
  {
    id: 3,
    name: 'Ruby',
  },
  {
    id: 4,
    name: 'React Native',
  },
  {
    id: 5,
    name: 'PHP',
  },
  {
    id: 6,
    name: 'Python',
  },
  {
    id: 7,
    name: 'Go',
  },
  {
    id: 8,
    name: 'Swift',
  },
];

const App = () => {
  const [selectedItem, setSelectedItem] = useState<any>(null);

  return (
    <View style={{backgroundColor: 'blue', flex: 1}}>
      <SearchableDropdown
        onItemSelect={(item: any) => {
          console.log('on item selected :', item);
          setSelectedItem(item.name);
        }}
        containerStyle={{
          zIndex: 200,
          backgroundColor: 'green',
          padding: 5,
          width: 200,
          marginTop: 100,
        }}
        onRemoveItem={(item: any, index: number) => {
          setSelectedItem(null);
        }}
        itemStyle={styles.itemStyle}
        itemTextStyle={{color: '#222'}}
        itemsContainerStyle={{maxHeight: 140}}
        items={items}
        resetValue={false}
        textInputProps={{
          value: selectedItem,
          placeholder: 'Select Location',
          underlineColorAndroid: 'transparent',
          onTextChange: (text: string) => console.log('on text change :', text),
        }}
        listProps={{
          nestedScrollEnabled: true,
        }}
      />
      <Text>fjsdkfjka</Text>
      <Text>fjsdkfjka</Text>
      <Text>fjsdkfjka</Text>
      <Text>fjsdkfjka</Text>
      <Text>fjsdkfjka</Text>
      <Text>fjsdkfjka</Text>
    </View>
  );
};

export default App;

const styles = StyleSheet.create({
  itemStyle: {
    padding: 10,
    backgroundColor: '#ddd',
    borderColor: '#bbb',
    borderWidth: 1,
    borderRadius: 5,
  },
});

searchableDropdown.tsx searchableDropdown.tsx


import React, {Component, useEffect, useState} from 'react';
import {
  Text,
  FlatList,
  TextInput,
  View,
  TouchableOpacity,
  Keyboard,
} from 'react-native';
import Entypo from 'react-native-vector-icons/Entypo';

const defaultItemValue = {
  name: '',
  id: 0,
};

const SearchableDropdown = (props: any) => {
  const [item, setItem] = useState<any>({});
  const [listItems, setListItems] = useState<any>([]);
  const [focus, setFocus] = useState<any>(false);
  const [viewHeight, setViewHeight] = useState<any>(0);
  let input: any = null;

  const renderFlatList = () => {
    if (focus) {
      const flatListPorps = {...props.listProps};
      const oldSupport = [
        {key: 'keyboardShouldPersistTaps', val: 'always'},
        {key: 'nestedScrollEnabled', val: false},
        {key: 'style', val: {...props.itemsContainerStyle}},
        {key: 'data', val: listItems},
        {
          key: 'keyExtractor',
          val: (item: any, index: number) => index.toString(),
        },
        {
          key: 'renderItem',
          val: ({item, index}: any) => renderItems(item, index),
        },
        {
          key: 'contentContainerStyle',
          val: {...props.contentContainerStyle},
        },
      ];
      oldSupport.forEach(kv => {
        if (!Object.keys(flatListPorps).includes(kv.key)) {
          flatListPorps[kv.key] = kv.val;
        } else {
          if (kv.key === 'style') {
            flatListPorps['style'] = kv.val;
          }
        }
      });
      return (
        <View
          style={{
            position: 'absolute',
            backgroundColor: 'red',
            width: '100%',
            opacity: 1,
            zIndex: 1,
            marginTop: 60,
          }}>
          <FlatList {...flatListPorps} />
        </View>
      );
    }
  };

  useEffect(() => {
    const listItems = props.items;
    const defaultIndex = props.defaultIndex;
    if (defaultIndex && listItems.length > defaultIndex) {
      setItem(listItems[defaultIndex]);
      setListItems(listItems);
    } else {
      setListItems(listItems);
    }
  }, []);

  const searchedItems = (searchedText: string) => {
    let setSort = props.setSort;
    if (!setSort && typeof setSort !== 'function') {
      setSort = (item: any, searchedText: string) => {
        return item.name.toLowerCase().indexOf(searchedText.toLowerCase()) > -1;
      };
    }
    var ac = props.items.filter((item: any) => {
      return setSort(item, searchedText);
    });
    let item = {
      id: -1,
      name: searchedText,
    };
    setItem(item);
    setListItems(ac);
    const onTextChange =
      props.onTextChange ||
      props.textInputProps.onTextChange ||
      props.onChangeText ||
      props.textInputProps.onChangeText;
    if (onTextChange && typeof onTextChange === 'function') {
      setTimeout(() => {
        onTextChange(searchedText);
      }, 0);
    }
  };

  const renderItems = (item: any, index: number) => {
    if (props.multi && props.selectedItems && props.selectedItems.length > 0) {
      return props.selectedItems.find((sitem: any) => sitem.id === item.id) ? (
        <TouchableOpacity
          style={{...props.itemStyle, flex: 1, flexDirection: 'row'}}>
          <View
            style={{
              flex: 0.9,
              flexDirection: 'row',
              alignItems: 'flex-start',
            }}>
            <Text>{item.name}</Text>
          </View>
          <View
            style={{flex: 0.1, flexDirection: 'row', alignItems: 'flex-end'}}>
            <TouchableOpacity
              onPress={() =>
                setTimeout(() => {
                  props.onRemoveItem(item, index);
                }, 0)
              }
              style={{
                backgroundColor: '#f16d6b',
                alignItems: 'center',
                justifyContent: 'center',
                width: 25,
                height: 25,
                borderRadius: 100,
                marginLeft: 10,
              }}>
              <Text>X</Text>
            </TouchableOpacity>
          </View>
        </TouchableOpacity>
      ) : (
        <TouchableOpacity
          onPress={() => {
            setItem(item);
            setTimeout(() => {
              props.onItemSelect(item);
            }, 0);
          }}
          style={{...props.itemStyle, flex: 1, flexDirection: 'row'}}>
          <View
            style={{flex: 1, flexDirection: 'row', alignItems: 'flex-start'}}>
            <Text>{item.name}</Text>
          </View>
        </TouchableOpacity>
      );
    } else {
      return (
        <TouchableOpacity
          style={{...props.itemStyle}}
          onPress={() => {
            setFocus(false);
            setItem(item);
            Keyboard.dismiss();
            setTimeout(() => {
              props.onItemSelect(item);
              if (props.resetValue) {
                setFocus(true);
                setItem(defaultItemValue);
                input.focus();
              }
            }, 0);
          }}>
          {props.selectedItems &&
          props.selectedItems.length > 0 &&
          props.selectedItems.find((x: any) => x.id === item.id) ? (
            <Text style={{...props.itemTextStyle}}>{item.name}</Text>
          ) : (
            <Text style={{...props.itemTextStyle}}>{item.name}</Text>
          )}
        </TouchableOpacity>
      );
    }
  };

  const renderListType = () => {
    return renderFlatList();
  };

  const renderTextInput = () => {
    const textInputProps = {...props.textInputProps};
    const oldSupport = [
      {key: 'ref', val: (e: any) => (input = e)},
      {
        key: 'onTextChange',
        val: (text: string) => {
          searchedItems(text);
        },
      },
      {key: 'underlineColorAndroid', val: props.underlineColorAndroid},
      {
        key: 'onFocus',
        val: () => {
          props.onFocus && props.onFocus();
          setFocus(true);
          setItem(defaultItemValue);
          setListItems(props.items);
        },
      },
      {
        key: 'onBlur',
        val: () => {
          props.onBlur && props.onBlur(this);
          setFocus(false);
          setItem(props.selectedItems);
        },
      },
      {
        key: 'value',
        val: item ? item.name : '',
      },
      {
        key: 'style',
        val: {...props.textInputStyle},
      },
      {
        key: 'placeholderTextColor',
        val: props.placeholderTextColor,
      },
      {
        key: 'placeholder',
        val: props.placeholder,
      },
    ];
    oldSupport.forEach(kv => {
      if (!Object.keys(textInputProps).includes(kv.key)) {
        if (kv.key === 'onTextChange' || kv.key === 'onChangeText') {
          textInputProps['onChangeText'] = kv.val;
        } else {
          textInputProps[kv.key] = kv.val;
        }
      } else {
        if (kv.key === 'onTextChange' || kv.key === 'onChangeText') {
          textInputProps['onChangeText'] = kv.val;
        }
      }
    });
    return (
      <View
        onLayout={event => {
          let {x, y, width, height} = event.nativeEvent.layout;
          setViewHeight(height);
        }}
        style={{
          flexDirection: 'row',
          width: 200,
          borderWidth: 1,
          borderColor: '#ccc',
        }}>
        {textInputProps.value === null ? (
          <TextInput
            {...textInputProps}
            style={{
              padding: 12,
              borderRadius: 5,
              justifyContent: 'center',
              alignItems: 'center',
              width: 150,
              height: 50,
            }}
            onBlur={e => {
              if (props.onBlur) {
                props.onBlur(e);
              }
              if (props.textInputProps && props.textInputProps.onBlur) {
                props.textInputProps.onBlur(e);
              }
              setFocus(false);
              setItem(props.selectedItems);
            }}
          />
        ) : (
          <View
            style={{
              height: 40,
              width: 130,
              flexDirection: 'row',
              alignItems: 'center',
              justifyContent: 'space-between',
              margin: 5,
              marginLeft: 10,
              marginRight: 10,
              backgroundColor: '#d9c979',
              borderRadius: 20,
              paddingLeft: 10,
            }}>
            <Text numberOfLines={1}>{textInputProps.value}</Text>
            <TouchableOpacity onPress={props.onRemoveItem}>
              <Entypo name={'cross'} style={{fontSize: 20}} />
            </TouchableOpacity>
          </View>
        )}
        <View
          style={{
            width: 48,
            backgroundColor: '#454545',
            justifyContent: 'center',
            alignItems: 'center',
          }}>
          <Entypo name={'chevron-down'} />
        </View>
      </View>
    );
  };

  const renderSelectedItems = () => {
    let items = props.selectedItems || [];
    if (items !== undefined && items.length > 0 && props.chip && props.multi) {
      return (
        <View
          style={{
            flexDirection: 'row',
            flexWrap: 'wrap',
            paddingBottom: 10,
            marginTop: 5,
          }}>
          {items.map((item: any, index: number) => {
            return (
              <View
                key={index}
                style={{
                  width: item.name.length * 8 + 60,
                  justifyContent: 'center',
                  flex: 0,
                  backgroundColor: '#eee',
                  flexDirection: 'row',
                  alignItems: 'center',
                  margin: 5,
                  padding: 8,
                  borderRadius: 15,
                }}>
                <Text style={{color: '#555'}}>{item.name}</Text>
                <TouchableOpacity
                  onPress={() =>
                    setTimeout(() => {
                      props.onRemoveItem(item, index);
                    }, 0)
                  }
                  style={{
                    backgroundColor: '#f16d6b',
                    alignItems: 'center',
                    justifyContent: 'center',
                    width: 25,
                    height: 25,
                    borderRadius: 100,
                    marginLeft: 10,
                  }}>
                  <Text>X</Text>
                </TouchableOpacity>
              </View>
            );
          })}
        </View>
      );
    }
  };

  return (
    <View
      //keyboardShouldPersist="always"
      style={{...props.containerStyle}}>
      {renderSelectedItems()}
      {renderListType()}
      {renderTextInput()}
    </View>
  );
};

export default SearchableDropdown;

I have created an working example based on your code我已经根据您的代码创建了一个工作示例

backgroundColor and zIndex in your App.tsx were the culprit. App.tsx 中的 backgroundColor 和 zIndex 是罪魁祸首。

React Native/JSX is not html and you shouldn't treat it like that. React Native/JSX 不是 html,你不应该那样对待它。 The document flow behaves different and there is no w3c which defines how component should work.文档流的行为不同,并且没有定义组件应该如何工作的 w3c。

There are a bunch of issues with your approach eg if you want to add the dropdown in another scrollview/flatlist you have a nested scrollview which won't work properly.你的方法有很多问题,例如,如果你想在另一个滚动视图/平面列表中添加下拉列表,你有一个无法正常工作的嵌套滚动视图。

I would suggest to solve your needs with another design approach我建议用另一种设计方法来解决您的需求

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

相关问题 在Android中反应本机ScrollView不起作用 - React Native ScrollView in android not working ScrollView 水平分页仅适用于 Android 不适用于 IOS react native expo cli - ScrollView horizontal pagination only works on Android doesn't work on IOS react native expo cli React Native Push Notifications 在 Android 中不工作,但在 iOS 上工作正常 - React Native Push Notifications not working in Android but works fine on iOS React Native HTTPS Api 调用在 IOS 中有效,但在 ZE84E30B9390CDB64DDB6DB2CZ 中无效 - React Native HTTPS Api calls works in IOS but not working in Android 反应本机 ScrollView keyboardShouldPersistTaps 不工作 Android - React native ScrollView keyboardShouldPersistTaps not working Android React-Native 水平滚动视图不起作用,但适用于垂直 - React-Native Horizontal Scrollview not working but works well with vertical React Native 在 Android 设备上崩溃,但在 iOS 上工作 - React Native crashes on Android device but works on iOS React Native Android Undefined不是在IOS中起作用的功能 - React native android undefined is not a function works in IOS React Native - TabNavigator 在 Android 的 ScrollView 内不起作用 - React Native - TabNavigator isn't working inside ScrollView in Android React Native ScrollView Horizontal 不起作用 - React Native ScrollView Horizontal not working
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM