react-native-modal-dropdown
react-native-modal-dropdown copied to clipboard
List view is deprecated in react native 0.60
List VIew is deprecated in react native 0.60. So the quick fix is to use deprecated-react-native-listview
Need to add
import ListView from "deprecated-react-native-listview";
instead of
import ListView from from 'react-native';
Okey,so in node_modules/react-native-modal-dropdown/component/ModalDropdown.js
Remove
import ListView from from 'react-native';
Add
import ListView from "deprecated-react-native-listview";
is anyone working on it to fix this?
Just opened a PR: https://github.com/sohobloo/react-native-modal-dropdown/pull/225
change list view to flat list:
import React, { Component } from "react";
import { StyleSheet, Dimensions, View, Text, FlatList, TouchableWithoutFeedback, TouchableNativeFeedback, TouchableOpacity, TouchableHighlight, Modal, ActivityIndicator } from "react-native";
import PropTypes from "prop-types"; import ListView from "deprecated-react-native-listview"; const TOUCHABLE_ELEMENTS = [ "TouchableHighlight", "TouchableOpacity", "TouchableWithoutFeedback", "TouchableNativeFeedback" ];
export default class ModalDropdown extends Component { static propTypes = { disabled: PropTypes.bool, scrollEnabled: PropTypes.bool, defaultIndex: PropTypes.number, defaultValue: PropTypes.string, options: PropTypes.array,
accessible: PropTypes.bool,
animated: PropTypes.bool,
showsVerticalScrollIndicator: PropTypes.bool,
keyboardShouldPersistTaps: PropTypes.string,
style: PropTypes.oneOfType([
PropTypes.number,
PropTypes.object,
PropTypes.array
]),
textStyle: PropTypes.oneOfType([
PropTypes.number,
PropTypes.object,
PropTypes.array
]),
dropdownStyle: PropTypes.oneOfType([
PropTypes.number,
PropTypes.object,
PropTypes.array
]),
dropdownTextStyle: PropTypes.oneOfType([
PropTypes.number,
PropTypes.object,
PropTypes.array
]),
dropdownTextHighlightStyle: PropTypes.oneOfType([
PropTypes.number,
PropTypes.object,
PropTypes.array
]),
adjustFrame: PropTypes.func,
renderRow: PropTypes.func,
renderSeparator: PropTypes.func,
renderButtonText: PropTypes.func,
onDropdownWillShow: PropTypes.func,
onDropdownWillHide: PropTypes.func,
onSelect: PropTypes.func
};
static defaultProps = { disabled: false, scrollEnabled: true, defaultIndex: -1, defaultValue: "Please select...", options: null, animated: true, showsVerticalScrollIndicator: true, keyboardShouldPersistTaps: "never" };
constructor(props) { super(props);
this._button = null;
this._buttonFrame = null;
this._nextValue = null;
this._nextIndex = null;
this.state = {
accessible: !!props.accessible,
loading: !props.options,
showDropdown: false,
buttonText: props.defaultValue,
selectedIndex: props.defaultIndex
};
}
componentWillReceiveProps(nextProps) { let { buttonText, selectedIndex } = this.state; const { defaultIndex, defaultValue, options } = nextProps; buttonText = this._nextValue == null ? buttonText : this._nextValue; selectedIndex = this._nextIndex == null ? selectedIndex : this._nextIndex; if (selectedIndex < 0) { selectedIndex = defaultIndex; if (selectedIndex < 0) { buttonText = defaultValue; } } this._nextValue = null; this._nextIndex = null;
this.setState({
loading: !options,
buttonText,
selectedIndex
});
}
render() { return ( <View {...this.props}> {this._renderButton()} {this._renderModal()} </View> ); }
_updatePosition(callback) { if (this._button && this._button.measure) { this._button.measure((fx, fy, width, height, px, py) => { this._buttonFrame = { x: px, y: py, w: width, h: height }; callback && callback(); }); } }
show() { this._updatePosition(() => { this.setState({ showDropdown: true }); }); }
hide() { this.setState({ showDropdown: false }); }
select(idx) { const { defaultValue, options, defaultIndex, renderButtonText } = this.props;
let value = defaultValue;
if (idx == null || !options || idx >= options.length) {
idx = defaultIndex;
}
if (idx >= 0) {
value = renderButtonText
? renderButtonText(options[idx])
: options[idx].toString();
}
this._nextValue = value;
this._nextIndex = idx;
this.setState({
buttonText: value,
selectedIndex: idx
});
}
_renderButton() { const { disabled, accessible, children, textStyle } = this.props; const { buttonText } = this.state;
return (
<TouchableOpacity
ref={button => (this._button = button)}
disabled={disabled}
accessible={accessible}
onPress={this._onButtonPress}
>
{children || (
<View style={styles.button}>
<Text style={[styles.buttonText, textStyle]} numberOfLines={1}>
{buttonText}
</Text>
</View>
)}
</TouchableOpacity>
);
}
_onButtonPress = () => { const { onDropdownWillShow } = this.props; if (!onDropdownWillShow || onDropdownWillShow() !== false) { this.show(); } };
_renderModal() { const { animated, accessible, dropdownStyle } = this.props; const { showDropdown, loading } = this.state; if (showDropdown && this._buttonFrame) { const frameStyle = this._calcPosition(); const animationType = animated ? "fade" : "none"; return ( <Modal animationType={animationType} visible={true} transparent={true} onRequestClose={this._onRequestClose} supportedOrientations={[ "portrait", "portrait-upside-down", "landscape", "landscape-left", "landscape-right" ]} > <TouchableWithoutFeedback accessible={accessible} disabled={!showDropdown} onPress={this._onModalPress} > <View style={styles.modal}> <View style={[styles.dropdown, dropdownStyle, frameStyle]}> {loading ? this._renderLoading() : this._renderDropdown()} </View> </View> </TouchableWithoutFeedback> </Modal> ); } }
_calcPosition() { const { dropdownStyle, style, adjustFrame } = this.props;
const dimensions = Dimensions.get("window");
const windowWidth = dimensions.width;
const windowHeight = dimensions.height;
const dropdownHeight =
(dropdownStyle && StyleSheet.flatten(dropdownStyle).height) ||
StyleSheet.flatten(styles.dropdown).height;
const bottomSpace =
windowHeight - this._buttonFrame.y - this._buttonFrame.h;
const rightSpace = windowWidth - this._buttonFrame.x;
const showInBottom =
bottomSpace >= dropdownHeight || bottomSpace >= this._buttonFrame.y;
const showInLeft = rightSpace >= this._buttonFrame.x;
const positionStyle = {
height: dropdownHeight,
top: showInBottom
? this._buttonFrame.y + this._buttonFrame.h
: Math.max(0, this._buttonFrame.y - dropdownHeight)
};
if (showInLeft) {
positionStyle.left = this._buttonFrame.x;
} else {
const dropdownWidth =
(dropdownStyle && StyleSheet.flatten(dropdownStyle).width) ||
(style && StyleSheet.flatten(style).width) ||
-1;
if (dropdownWidth !== -1) {
positionStyle.width = dropdownWidth;
}
positionStyle.right = rightSpace - this._buttonFrame.w;
}
return adjustFrame ? adjustFrame(positionStyle) : positionStyle;
}
_onRequestClose = () => { const { onDropdownWillHide } = this.props; if (!onDropdownWillHide || onDropdownWillHide() !== false) { this.hide(); } };
_onModalPress = () => { const { onDropdownWillHide } = this.props; if (!onDropdownWillHide || onDropdownWillHide() !== false) { this.hide(); } };
_renderLoading() { return <ActivityIndicator size="small" />; }
_renderDropdown() {
const { options, showsVerticalScrollIndicator } = this.props;
return (
<FlatList
data={options}
style={styles.list}
renderItem={this.renderItem}
showsVerticalScrollIndicator={showsVerticalScrollIndicator}
/>
);
}
renderItem = ({ item, index, separators }) => {
const {
renderRow,
dropdownTextStyle,
dropdownTextHighlightStyle,
accessible
} = this.props;
const { selectedIndex } = this.state;
const key = row_${index}
;
const highlighted = index == selectedIndex;
const row = !renderRow ? (
<Text
style={[
styles.rowText,
dropdownTextStyle,
highlighted && styles.highlightedRowText,
highlighted && dropdownTextHighlightStyle
]}
>
{item}
</Text>
) : (
renderRow(item, index, highlighted)
);
const preservedProps = {
key,
accessible,
onPress: () => this._onRowPress(item, index)
};
if (TOUCHABLE_ELEMENTS.find(name => name == row.type.displayName)) {
const props = { ...row.props };
props.key = preservedProps.key;
props.onPress = preservedProps.onPress;
const { children } = row.props;
switch (row.type.displayName) {
case "TouchableHighlight": {
return <TouchableHighlight {...props}>{children}</TouchableHighlight>;
}
case "TouchableOpacity": {
return <TouchableOpacity {...props}>{children}</TouchableOpacity>;
}
case "TouchableWithoutFeedback": {
return (
<TouchableWithoutFeedback {...props}>
{children}
</TouchableWithoutFeedback>
);
}
case "TouchableNativeFeedback": {
return (
<TouchableNativeFeedback {...props}>
{children}
</TouchableNativeFeedback>
);
}
default:
break;
}
}
return <TouchableHighlight {...preservedProps}>{row}</TouchableHighlight>;
};
_onRowPress(item, index) { const { onSelect, renderButtonText, onDropdownWillHide } = this.props; if (!onSelect || onSelect(index, item) !== false) { const value = (renderButtonText && renderButtonText(item)) || item.toString(); this._nextValue = value; this._nextIndex = index; this.setState({ buttonText: value, selectedIndex: index }); } if (!onDropdownWillHide || onDropdownWillHide() !== false) { this.setState({ showDropdown: false }); } }
_renderSeparator = (sectionID, rowID, adjacentRowHighlighted) => {
const key = spr_${rowID}
;
return <View style={styles.separator} key={key} />;
};
}
const styles = StyleSheet.create({ button: { justifyContent: "center" }, buttonText: { fontSize: 12 }, modal: { flexGrow: 1 }, dropdown: { position: "absolute", height: (33 + StyleSheet.hairlineWidth) * 5, borderWidth: StyleSheet.hairlineWidth, borderColor: "lightgray", borderRadius: 2, backgroundColor: "white", justifyContent: "center" }, loading: { alignSelf: "center" }, list: { //flexGrow: 1, }, rowText: { paddingHorizontal: 6, paddingVertical: 10, fontSize: 11, color: "gray", backgroundColor: "white", textAlignVertical: "center" }, highlightedRowText: { color: "black" }, separator: { height: StyleSheet.hairlineWidth, backgroundColor: "lightgray" } });
you can use my fork
@riyga25 did you open a PR for this? I would love to see your changes merged into the next Version. Thanks for your effort.
But I even found a Bug at your implementation. If I click on an entry in the Item-List I got "highlightRow" is not a function.
To fix this change Line 392 from:
highlightRow(rowID);
to
highlightRow.highlight(rowID);
And btw. it seems that key's for Items are missing (got an yellow-alert-box for this.
@xstable No, I did't, I think PR will not be accepted, because the project seems dead. Thanks! I fixed it, but I didn't check) I hope it's work
So please give them a change to merge anyway. Hopefully @sohobloo will merge it one day.
Okey,so in node_modules/react-native-modal-dropdown/component/ModalDropdown.js
Remove
import ListView from from 'react-native';
Add
import ListView from "deprecated-react-native-listview";
Thanks man, this worked out for me