Dropdown.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. import React, { useEffect, useRef, useState } from 'react';
  2. import { FlatList, Keyboard, Pressable, StyleSheet, Modal, View, Text } from 'react-native';
  3. import Button from './Button';
  4. import Dialog from './Dialog';
  5. import TextView from './TextView';
  6. import app from '../../app.json';
  7. import MyModal from './MyModal';
  8. //const DialogMaxWidth = $vw(85) > 500 ? 500 : $vw(85);
  9. //const DialogIOSWidth = $vw(75) > 450 ? 450 : $vw(75);
  10. export default Dropdown = ({
  11. list = [],
  12. title = '',
  13. value,
  14. onChange,
  15. nameKey,
  16. valueKey,
  17. prefixText='',//前缀
  18. suffixText='',//后缀
  19. itemHeight=50,
  20. prefixList='',//列表前缀
  21. suffixList='',//列表后缀
  22. rippleStyle=ripple,
  23. style = styles.valueView,
  24. textStyle = styles.valueText,
  25. placeholderStyle=styles.placeText,
  26. placeholder='',
  27. showText = true,
  28. showIcon = true,
  29. iconColor = '#888',
  30. iconStyle = styles.iconStyle,
  31. autoSelect = true,
  32. customerItemView
  33. }) => {
  34. const refFlat = useRef();
  35. const [visible, showDialog] = useState(false);
  36. const [selected, changeValue] = useState('');
  37. const [currentIndex, setCurrent] = useState(0);
  38. useEffect(() => {
  39. if (value !== selected) {
  40. changeItem();
  41. }
  42. }, [value, []]);
  43. useEffect(() => {
  44. if (autoSelect && list.length > 0) {
  45. if (value == undefined) {
  46. const item = list[0];
  47. if (nameKey) {
  48. changeValue(prefixText+item[nameKey]+suffixText);
  49. } else {
  50. changeValue(item);
  51. }
  52. setChange(valueKey ? item[valueKey] : item, 0);
  53. } else {
  54. changeItem(true);
  55. }
  56. }
  57. }, [list]);
  58. const changeItem = (init) => {
  59. if (nameKey && valueKey) {
  60. for (var i = 0; i < list.length; i++) {
  61. let item = list[i];
  62. if (item[valueKey] == value) {
  63. changeValue(prefixText+item[nameKey]+suffixText);
  64. if (list.length > 20) {
  65. setCurrent(i > 5 ? i - 4 : 0);
  66. }
  67. return;
  68. }
  69. }
  70. if (init) {
  71. const item = list[0];
  72. setChange(item[valueKey], 0);
  73. }
  74. } else {
  75. if (init) {
  76. let _i = list.indexOf(value);
  77. if (_i >= 0) {
  78. setChange(list[_i], _i);
  79. } else {
  80. setChange(list[0], 0);
  81. }
  82. } else {
  83. changeValue(prefixText+value+suffixText);
  84. }
  85. }
  86. }
  87. const showList = () => {
  88. Keyboard.dismiss();
  89. showDialog(true);
  90. /*if (currentIndex > 0) {
  91. console.log(refFlat.current);
  92. setTimeout(() => {
  93. if (refFlat.current) {
  94. refFlat.current.scrollToIndex({
  95. animated: false,
  96. index: currentIndex,
  97. viewPosition: 0.5
  98. })
  99. }
  100. }, 100)
  101. }*/
  102. }
  103. const renderItem = ({ item, index, separators }) => {
  104. const _value = (valueKey ? item[valueKey] : item);
  105. if (customerItemView) {
  106. return customerItemView(item, index, () => {
  107. showDialog(false);
  108. setChange(_value, index);
  109. })
  110. } else {
  111. return (
  112. <Button
  113. text={prefixList + (nameKey ? item[nameKey] : item) + suffixList}
  114. style={styles.itemView}
  115. textStyle={styles.itemText}
  116. onClick={() => {
  117. showDialog(false);
  118. setChange(_value, index);
  119. }}
  120. iconRight={(_value == value) && <MaterialIcons name="radio-button-checked" color={colorAccent} size={22}/>}
  121. />
  122. )
  123. }
  124. }
  125. const setChange = (v, i) => {
  126. setTimeout(() => {
  127. if (onChange) {
  128. onChange(v, i)
  129. }
  130. }, 300);
  131. }
  132. return (
  133. <>
  134. <Pressable
  135. style={({pressed }) => [
  136. pressed && isIOS && {
  137. backgroundColor: rippleColor
  138. },
  139. style
  140. ]}
  141. android_ripple={rippleStyle}
  142. onPress={() => showList()}>
  143. { showText &&
  144. ( selected
  145. ? <TextView style={[textStyle, styles.textView]} numberOfLines={1}>{selected}</TextView>
  146. : <TextView style={[placeholderStyle, styles.textView]} numberOfLines={1}>{placeholder}</TextView>
  147. )
  148. }
  149. { showIcon && (isIOS || app.isLumiWhitelabel
  150. ? <MaterialIcons
  151. name={'keyboard-arrow-down'}
  152. size={24}
  153. color={iconColor}
  154. style={iconStyle}
  155. />
  156. : <MaterialIcons
  157. name={'arrow-drop-down'}
  158. size={24}
  159. color={iconColor}
  160. style={iconStyle}
  161. />)
  162. }
  163. </Pressable>
  164. <MyModal
  165. visible={visible}
  166. style={styles.dialogContent}
  167. onLayerPress={() => showDialog(false)}>
  168. <View style={$padding(4, 0, 0)}>
  169. { title !== '' && <TextView style={styles.title}>{title}</TextView> }
  170. <FlatList
  171. data={list}
  172. ref={refFlat}
  173. renderItem={renderItem}
  174. initialScrollIndex={currentIndex}
  175. keyExtractor={(item, index) => index}
  176. style={{maxHeight: $vh(55)}}
  177. getItemLayout={(data, index) => (
  178. {length: itemHeight, offset: itemHeight * index, index}
  179. )}
  180. />
  181. </View>
  182. </MyModal>
  183. </>
  184. );
  185. }
  186. const styles = StyleSheet.create({
  187. dialog: {
  188. flex: 1,
  189. alignItems: 'center',
  190. justifyContent: 'center',
  191. backgroundColor: 'rgba(0,0,0,.6)'
  192. },
  193. dialogContent: {
  194. width: Dialog.dialogWidth,
  195. marginLeft: 'auto',
  196. marginRight: 'auto',
  197. paddingTop: isIOS ? 12 : 8,
  198. paddingBottom: isIOS ? 12 : 8,
  199. backgroundColor: colorLight,
  200. borderRadius: isIOS ? 10 : 4
  201. },
  202. title: {
  203. color: '#000',
  204. paddingTop: 8,
  205. paddingLeft: 16,
  206. paddingBottom: 16,
  207. fontSize: 17,
  208. fontWeight: 'bold'
  209. },
  210. valueView: {
  211. paddingLeft: 16,
  212. paddingRight: 8,
  213. alignItems: 'center',
  214. flexDirection: 'row'
  215. },
  216. valueText: {
  217. color: '#000',
  218. fontSize: 16
  219. },
  220. itemView: {
  221. borderRadius: 0,
  222. backgroundColor: colorLight
  223. },
  224. itemText: {
  225. flex: 1,
  226. color: textPrimary,
  227. fontSize: 14,
  228. textAlign: 'left',
  229. fontWeight: 'normal'
  230. },
  231. placeText: {
  232. flex: 1,
  233. color: textPlacehoder
  234. },
  235. iconStyle: {
  236. marginLeft: 8
  237. },
  238. textView: {
  239. flex: 1,
  240. flexDirection: 'column'
  241. }
  242. });