Dropdown.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import React, { useEffect, useRef, useState } from 'react';
  2. import { FlatList, Keyboard, Pressable, StyleSheet, Text, View } from 'react-native';
  3. import Modal from 'react-native-modal';
  4. import Button from './Button';
  5. import Dialog, { getDialogWidth } from './Dialog';
  6. //const DialogMaxWidth = $vw(85) > 500 ? 500 : $vw(85);
  7. //const DialogIOSWidth = $vw(75) > 450 ? 450 : $vw(75);
  8. export default Dropdown = ({
  9. list = [],
  10. title = '',
  11. value,
  12. onChange,
  13. nameKey,
  14. valueKey,
  15. prefixText='',//前缀
  16. suffixText='',//后缀
  17. itemHeight=50,
  18. prefixList='',//列表前缀
  19. suffixList='',//列表后缀
  20. rippleStyle,
  21. style = styles.valueView,
  22. textStyle = styles.valueText,
  23. placeholderStyle=styles.placeText,
  24. placeholder='',
  25. showText = true,
  26. showIcon = true,
  27. iconColor = '#888',
  28. iconStyle = styles.iconStyle,
  29. autoSelect = true,
  30. customerItemView
  31. }) => {
  32. const refFlat = useRef();
  33. const [visible, showDialog] = useState(false);
  34. const [selected, changeValue] = useState('');
  35. const [currentIndex, setCurrent] = useState(0);
  36. useEffect(() => {
  37. if (value !== selected) {
  38. if (nameKey && valueKey) {
  39. for (var i = 0; i < list.length; i++) {
  40. let item = list[i];
  41. if (item[valueKey] == value) {
  42. changeValue(prefixText+item[nameKey]+suffixText);
  43. if (list.length > 20) {
  44. setCurrent(i > 5 ? i - 4 : 0);
  45. }
  46. break;
  47. }
  48. }
  49. } else {
  50. changeValue(prefixText+value+suffixText);
  51. }
  52. }
  53. }, [value, []]);
  54. useEffect(() => {
  55. if (autoSelect && list.length > 0) {
  56. if (!value) {
  57. const item = list[0];
  58. /*if (nameKey) {
  59. changeValue(item[nameKey]);
  60. } else {
  61. changeValue(item);
  62. }*/
  63. if (onChange) {
  64. onChange(valueKey ? item[valueKey] : item, 0)
  65. }
  66. }
  67. }
  68. }, [list]);
  69. const showList = () => {
  70. Keyboard.dismiss();
  71. showDialog(true);
  72. /*if (currentIndex > 0) {
  73. console.log(refFlat.current);
  74. setTimeout(() => {
  75. if (refFlat.current) {
  76. refFlat.current.scrollToIndex({
  77. animated: false,
  78. index: currentIndex,
  79. viewPosition: 0.5
  80. })
  81. }
  82. }, 100)
  83. }*/
  84. }
  85. const renderItem = ({ item, index, separators }) => {
  86. if (customerItemView) {
  87. return customerItemView(item, index, () => {
  88. showDialog(false);
  89. if (onChange) {
  90. onChange(valueKey ? item[valueKey] : item, index)
  91. }
  92. })
  93. } else {
  94. return (
  95. <Button
  96. text={prefixList + (nameKey ? item[nameKey] : item) + suffixList}
  97. style={styles.itemView}
  98. textStyle={styles.itemText}
  99. onClick={() => {
  100. showDialog(false);
  101. if (onChange) {
  102. onChange(valueKey ? item[valueKey] : item, index)
  103. }
  104. }
  105. }/>
  106. )
  107. }
  108. }
  109. return (
  110. <>
  111. <Pressable
  112. style={style}
  113. android_ripple={rippleStyle}
  114. onPress={() => showList()}>
  115. { showText &&
  116. ( selected
  117. ? <Text style={[ui.flex1, textStyle]} numberOfLines={1}>{selected}</Text>
  118. : <Text style={[textStyle, placeholderStyle]} numberOfLines={1}>{placeholder}</Text>
  119. )
  120. }
  121. { showIcon &&
  122. <Entypo
  123. name={'chevron-thin-down'}
  124. size={14}
  125. color={iconColor}
  126. style={iconStyle}
  127. />
  128. }
  129. </Pressable>
  130. <Modal
  131. isVisible={visible}
  132. onTouchOutside={() => showDialog(false)}
  133. onBackdropPress={() => showDialog(false)}
  134. onBackButtonPress={() => showDialog(false)}
  135. {...Dialog.modalProps}
  136. >
  137. <View style={styles.dialog}>
  138. { title !== '' && <Text style={styles.title}>{title}</Text> }
  139. <FlatList
  140. data={list}
  141. ref={refFlat}
  142. renderItem={renderItem}
  143. initialScrollIndex={currentIndex}
  144. keyExtractor={(item, index) => index}
  145. style={{maxHeight: $vh(55)}}
  146. getItemLayout={(data, index) => (
  147. {length: itemHeight, offset: itemHeight * index, index}
  148. )}
  149. />
  150. </View>
  151. </Modal>
  152. </>
  153. );
  154. }
  155. const styles = StyleSheet.create({
  156. dialog: {
  157. width: getDialogWidth(),
  158. marginLeft: 'auto',
  159. marginRight: 'auto',
  160. paddingTop: isIOS ? 12 : 8,
  161. paddingBottom: isIOS ? 12 : 8,
  162. backgroundColor: colorLight,
  163. borderRadius: isIOS ? 10 : 3
  164. },
  165. title: {
  166. color: '#000',
  167. paddingTop: 8,
  168. paddingLeft: 16,
  169. paddingBottom: 16,
  170. fontSize: 17,
  171. fontWeight: 'bold'
  172. },
  173. valueView: {
  174. paddingLeft: 16,
  175. paddingRight: 32,
  176. alignItems: 'center',
  177. flexDirection: 'row'
  178. },
  179. valueText: {
  180. color: '#000',
  181. fontSize: 16
  182. },
  183. itemView: {
  184. borderRadius: 0,
  185. backgroundColor: colorLight
  186. },
  187. itemText: {
  188. flex: 1,
  189. color: textPrimary,
  190. fontSize: 14,
  191. textAlign: 'left',
  192. fontWeight: 'normal'
  193. },
  194. placeText: {
  195. flex: 1,
  196. color: textPlacehoder
  197. },
  198. iconStyle: {
  199. top: '50%',
  200. right: 16,
  201. marginTop: -7,
  202. position: 'absolute',
  203. }
  204. });