Dropdown.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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=ripple,
  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={({pressed }) => [
  113. pressed && isIOS && {
  114. backgroundColor: rippleColor
  115. },
  116. style
  117. ]}
  118. android_ripple={rippleStyle}
  119. onPress={() => showList()}>
  120. { showText &&
  121. ( selected
  122. ? <Text style={[ui.flex1, textStyle]} numberOfLines={1}>{selected}</Text>
  123. : <Text style={[textStyle, placeholderStyle]} numberOfLines={1}>{placeholder}</Text>
  124. )
  125. }
  126. { showIcon &&
  127. <Entypo
  128. name={'chevron-thin-down'}
  129. size={14}
  130. color={iconColor}
  131. style={iconStyle}
  132. />
  133. }
  134. </Pressable>
  135. <Modal
  136. isVisible={visible}
  137. onTouchOutside={() => showDialog(false)}
  138. onBackdropPress={() => showDialog(false)}
  139. onBackButtonPress={() => showDialog(false)}
  140. {...Dialog.modalProps}
  141. >
  142. <View style={styles.dialog}>
  143. { title !== '' && <Text style={styles.title}>{title}</Text> }
  144. <FlatList
  145. data={list}
  146. ref={refFlat}
  147. renderItem={renderItem}
  148. initialScrollIndex={currentIndex}
  149. keyExtractor={(item, index) => index}
  150. style={{maxHeight: $vh(55)}}
  151. getItemLayout={(data, index) => (
  152. {length: itemHeight, offset: itemHeight * index, index}
  153. )}
  154. />
  155. </View>
  156. </Modal>
  157. </>
  158. );
  159. }
  160. const styles = StyleSheet.create({
  161. dialog: {
  162. width: getDialogWidth(),
  163. marginLeft: 'auto',
  164. marginRight: 'auto',
  165. paddingTop: isIOS ? 12 : 8,
  166. paddingBottom: isIOS ? 12 : 8,
  167. backgroundColor: colorLight,
  168. borderRadius: isIOS ? 10 : 3
  169. },
  170. title: {
  171. color: '#000',
  172. paddingTop: 8,
  173. paddingLeft: 16,
  174. paddingBottom: 16,
  175. fontSize: 17,
  176. fontWeight: 'bold'
  177. },
  178. valueView: {
  179. paddingLeft: 16,
  180. paddingRight: 32,
  181. alignItems: 'center',
  182. flexDirection: 'row'
  183. },
  184. valueText: {
  185. color: '#000',
  186. fontSize: 16
  187. },
  188. itemView: {
  189. borderRadius: 0,
  190. backgroundColor: colorLight
  191. },
  192. itemText: {
  193. flex: 1,
  194. color: textPrimary,
  195. fontSize: 14,
  196. textAlign: 'left',
  197. fontWeight: 'normal'
  198. },
  199. placeText: {
  200. flex: 1,
  201. color: textPlacehoder
  202. },
  203. iconStyle: {
  204. top: '50%',
  205. right: 16,
  206. marginTop: -7,
  207. position: 'absolute',
  208. }
  209. });