-
Notifications
You must be signed in to change notification settings - Fork 298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zIndex problem in android dropdown picker #164
Comments
Hello, |
@hossein-zare |
<DropDownPicker
ref={ref => this.dropDownPickerRef = ref}
onOpen={() => { Keyboard.dismiss() }}
items={services}
selectedItem={selectedServices}
dropDownMaxHeight={200}
showArrow={true}
multiple={true}
containerStyle={{
minHeight: 55,
backgroundColor: colors.lightGrey,
marginTop: 10,
borderRadius: 10,
paddingHorizontal: 10,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.10,
shadowRadius: 10.84,
elevation: 5,
}}
itemStyle={{ justifyContent: 'flex-start' }}
/> This code snippet is enough, Send me whatever is in the Render function & the styles. |
@hossein-zare thanks for your response I did some customization in the picker component Complete Usage import React, { Component } from 'react';
import {
View,
Dimensions,
StyleSheet,
Keyboard,
Platform
} from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import InputField from '../../../components/InputField'
import DropDownPicker from '../../../components/DropDownPicker'
import icons from '../../../assets/icons'
import colors from '../../../utils/colors';
const { height } = Dimensions.get('screen');
const inputAccessoryViewID = 'SignUpScreen'
export default class SignUpScreen extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
name: '',
previousSelectedIndex: 0,
services: [
{ id: 0, name: 'service 1', isChecked: false },
{ id: 1, name: 'service 2', isChecked: false },
{ id: 2, name: 'service 3', isChecked: false },
{ id: 3, name: 'service 4', isChecked: false },
],
selectedServices: [],
password: '',
isHiddenPassword: true,
rememberPassword: true,
}
}
render() {
const {
email,
name,
services,
selectedServices,
password,
isHiddenPassword
} = this.state
const { navigation } = this.props
return (
<View style={styles.container}>
<Header
leftIcon={icons.backArrow}
onLeftAction={() => {
navigation.goBack()
}}
hearderText={"Sign Up"}
/>
<KeyboardAwareScrollView
innerRef={ref => { this.scroll = ref }}
// bounces={false}
keyboardShouldPersistTaps='handled'
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
contentContainerStyle={{ flexGrow: 1 }}
extraHeight={160}
style={{ flexGrow: 1, width: '100%', paddingHorizontal: 15, paddingTop: 20, paddingBottom: 50 }}>
<View style={{ flex: 1, overflow: 'visible', marginHorizontal: 15 }}>
<InputField
fieldRef={ref => this.fieldName = ref}
onParentPress={() => { if (this.fieldName) this.fieldName.focus() }}
value={name}
autoCapitalize={'words'}
placeholder={'Full Name'}
textContentType={'name'}
autoCompleteType={'name'}
returnKeyType='next'
onChangeText={(text) => {
this.setState({ name: text })
}}
onSubmitEditing={() => {
this.fieldEmail.focus()
}}
inputAccessoryViewID={inputAccessoryViewID}
/>
<DropDownPicker
ref={ref => this.dropDownPickerRef = ref}
onOpen={() => { Keyboard.dismiss() }}
items={services}
selectedItem={selectedServices}
dropDownMaxHeight={200}
showArrow={true}
multiple={true}
containerStyle={[styles.pickerContainer, { paddingHorizontal: 0, flexDirection: 'column' }]}
style={{ backgroundColor: colors.transparent, borderWidth: 0 }}
placeholder={'Select your service(s)'}
placeholderStyle={{ color: colors.mediumGrey }}
itemStyle={{ justifyContent: 'flex-start' }}
dropDownStyle={[{ backgroundColor: '#fafafa' }, Platform.OS == 'android' ? { position: 'relative', top: 0 } : {}]}
onChangeItem={(item, index) => {
let servicesTemp = services
servicesTemp[index].isChecked = item.isChecked == true ? false : true
this.setState({ servicesTemp: servicesTemp }, () => {
let selectedServicesFiltered = servicesTemp.filter((item) => item.isChecked)
this.setState({ selectedServices: selectedServicesFiltered })
})
}}
/>
<InputField
fieldRef={ref => this.fieldEmail = ref}
onParentPress={() => { if (this.fieldEmail) this.fieldEmail.focus() }}
value={email}
autoCapitalize={'none'}
placeholder={'Email Address'}
textContentType={'emailAddress'}
keyboardType={'email-address'}
autoCompleteType={'email'}
returnKeyType='next'
onChangeText={(text) => {
this.setState({ email: text })
}}
onSubmitEditing={() => {
this.fieldPassword.focus()
}}
inputAccessoryViewID={inputAccessoryViewID}
/>
<InputField
fieldRef={ref => this.fieldPassword = ref}
onParentPress={() => { if (this.fieldPassword) this.fieldPassword.focus() }}
inputContainer={{ paddingRight: 10 }}
value={password}
placeholder={'Password'}
secureTextEntry={isHiddenPassword}
returnKeyType='next'
onChangeText={(text) => {
this.setState({ password: text })
}}
onSubmitEditing={() => {
this.fieldConfrimPassword.focus()
}}
rightIcon={isHiddenPassword ? icons.eyeOpen : icons.eyeClose}
rightIconStyle={{ tintColor: '#A4A4A4' }}
onRightIconPress={() => {
this.setState({ isHiddenPassword: !isHiddenPassword })
}}
inputAccessoryViewID={inputAccessoryViewID}
/>
</View>
</KeyboardAwareScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: "center",
width: '100%',
backgroundColor: colors.background,
},
pickerContainer: {
flexDirection: 'row',
minHeight: 55,
alignItems: 'center',
backgroundColor: colors.lightGrey,
marginTop: 10,
borderRadius: 10,
paddingHorizontal: 10,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.10,
shadowRadius: 10.84,
elevation: 5,
},
}); Input import React, { Component } from 'react';
import {
Platform,
StyleSheet,
TextInput,
View,
Text,
TouchableOpacity,
Image,
} from 'react-native';
import _ from 'lodash'
import colors from '../utils/colors';
export default InputField = (props) => {
const {
inputContainer,
onParentPress,
inputStyle,
fieldRef,
value,
onChangeText,
onSubmitEditing,
onFocus,
onKeyPress,
leftIcon,
rightIcon,
rightText,
leftIconStyle,
rightIconStyle,
onRightIconPress,
hideShadowElevation,
rightIconContainerStyle
} = props
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => {
if (onParentPress && typeof onParentPress == 'function') onParentPress()
}}
style={[styles.inputContainer, inputContainer, hideShadowElevation ? {} : styles.shadowElevation]}>
{leftIcon &&
<Image
style={[styles.iconStyle, { marginRight: 5 }, leftIconStyle]}
source={leftIcon}
/>
}
<TextInput
{...props}
ref={ref => {
if (fieldRef && typeof fieldRef == 'function') fieldRef(ref)
}}
style={[styles.inputStyle, inputStyle]}
value={value}
placeholderTextColor={colors.mediumGrey}
onChangeText={(text) => {
if (onChangeText && typeof onChangeText == 'function') onChangeText(text)
}}
onSubmitEditing={() => {
if (onSubmitEditing && typeof onSubmitEditing == 'function') onSubmitEditing()
}}
onFocus={(event: Event) => { if (onFocus && typeof onFocus == 'function') onFocus(event) }}
onKeyPress={({ nativeEvent }) => { if (onKeyPress && typeof onKeyPress == 'function') onKeyPress(nativeEvent) }}
/>
{rightIcon &&
<TouchableOpacity
disabled={_.isNil(onRightIconPress)}
style={[{ padding: 10 }, rightIconContainerStyle]}
onPress={() => {
if (onRightIconPress) onRightIconPress()
}}>
{rightText ?
<Text style={{ color: colors.green }}>{rightText}</Text>
:
<Image
style={[styles.iconStyle, rightIconStyle]}
source={rightIcon}
/>
}
</TouchableOpacity>
}
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
inputContainer: {
flexDirection: 'row',
height: 55,
alignItems: 'center',
backgroundColor: colors.lightGrey,
marginTop: 10,
borderRadius: 10,
paddingHorizontal: 15
},
inputStyle: {
flex: 1,
},
shadowElevation: {
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.10,
shadowRadius: 10.84,
elevation: 5,
},
iconStyle: {
width: 20,
height: 20,
resizeMode: 'contain'
}
}) Custom Picker import React from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
ScrollView,
Platform,
TextInput,
Image,
ViewPropTypes
} from 'react-native';
import icons from '../assets/icons';
import colors from '../utils/colors';
import CheckBoxRound from './CheckBoxRound'
class DropDownPicker extends React.Component {
constructor(props) {
super(props);
this.state = {
searchableText: null,
isVisible: props.isVisible,
initialScroll: props?.autoScrollToDefaultValue,
defaultValueIndex: 0,
dropdownListMarginTop: 56
};
this.dropdownCoordinates = [];
}
componentDidMount() {
// this.props.controller(this);
}
componentDidUpdate() {
// ScrollView scrollTo() can only be used after the ScrollView is rendered
// Automatic scrolling to first defaultValue occurs on first render of dropdown ScrollView
const item = this.props.items[this.state.defaultValueIndex];
const isItemVisible = item && (typeof item.hidden === 'undefined' || item.hidden === false);
if (this.state.initialScroll && this.state.isVisible && isItemVisible) {
setTimeout(() => {
this.scrollViewRef.scrollTo({
x: 0,
y: this.dropdownCoordinates[this.state.defaultValueIndex],
animated: true,
});
this.setState({ initialScroll: false });
}, 200);
}
}
toggle() {
this.setState({
isVisible: !this.state.isVisible,
}, () => {
const isVisible = this.state.isVisible;
if (isVisible) {
this.open(false);
} else {
this.close(false);
}
});
}
isOpen() {
return this.state.isVisible;
}
open(setState = true) {
this.setState({
...(setState && { isVisible: true })
}, () => this.props.onOpen());
}
close(setState = true) {
this.setState({
...(setState && { isVisible: false }),
searchableText: null
}, () =>
this.props.onClose()
);
}
getLayout(layout) {
let height = layout.height < 56 ? 56 : layout.height
this.setState({
dropdownListMarginTop: height
});
}
onChangeItemPress = (item, index) => {
const { onChangeItem, multiple } = this.props
if (multiple) {
onChangeItem(item, index)
} else {
this.close()
onChangeItem(item, index)
}
}
render() {
const {
items,
onChangeItem,
disabled,
containerStyle,
style,
selectedItem,
multiple,
dropDownStyle,
showArrow,
dropDownMaxHeight,
searchable,
searchableStyle,
placeholder,
searchablePlaceholder,
searchablePlaceholderTextColor,
searchTextInputProps,
activeItemStyle,
scrollViewProps,
itemStyle,
labelStyle,
activeLabelStyle,
searchableError,
} = this.props
const { searchableText, dropdownListMarginTop, isVisible } = this.state
return (
<View style={[styles.containerStyle, containerStyle]}>
<TouchableOpacity
onLayout={(event) => this.getLayout(event.nativeEvent.layout)}
disabled={disabled}
onPress={() => this.toggle()}
activeOpacity={1}
style={[styles.dropDown, { flexDirection: 'row', flex: 1, minHeight: 55 }, style, this.state.isVisible && styles.noBottomRadius]}>
<View style={{ flex: 1 }}>
{multiple ?
selectedItem.length > 0 ?
<View style={{ flex: 1, justifyContent: 'center' }}>
<View style={{ flexDirection: 'row', flexWrap: 'wrap', alignItems: 'center' }}>
{selectedItem.map((item, index) => {
if (item.isChecked == true) {
return (
<View key={index} style={{ margin: 5, paddingHorizontal: 10, paddingVertical: 5, backgroundColor: colors.primary, borderRadius: 10, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ color: colors.white }}>{item.name}</Text>
</View>
)
} else return null
})}
</View>
</View>
:
<Text style={{ color: colors.mediumGrey }}>{placeholder}</Text>
:
<Text style={{ color: selectedItem.name ? colors.primary : colors.mediumGrey }}>{selectedItem.name ? selectedItem.name : placeholder}</Text>
}
</View>
{showArrow && (
<View style={isVisible ? styles.closeIconStyle : styles.downArrowStyle}>
<Image
style={{ width: '100%', height: '100%', resizeMode: 'contain', tintColor: colors.mediumGrey }}
source={isVisible ? icons.cross : icons.downArrow}
/>
</View>
)}
</TouchableOpacity>
<View style={[
styles.dropDown,
styles.dropDownBox,
!this.state.isVisible && styles.hidden, {
top: dropdownListMarginTop,
width: '100%',
maxHeight: dropDownMaxHeight,
zIndex: 5000
},
dropDownStyle,
]}>
{
searchable && (
<View style={{ width: '100%', flexDirection: 'row' }}>
<TextInput
style={[styles.input, searchableStyle]}
value={searchableText}
placeholder={searchablePlaceholder}
placeholderTextColor={searchablePlaceholderTextColor}
{...searchTextInputProps}
onChangeText={(text) => {
this.setState({ searchableText: text })
if (searchTextInputProps.onChangeText) searchTextInputProps.onChangeText(text);
}}
/>
</View>
)
}
<ScrollView
style={{ width: '100%' }}
nestedScrollEnabled={true}
ref={ref => {
this.scrollViewRef = ref;
}}
{...scrollViewProps}>
{items?.filter(item => typeof item.hidden === 'undefined' || item.hidden === false).length > 0 ?
items?.map((item, index) => (
<View
key={index}
onLayout={event => {
const layout = event.nativeEvent.layout;
this.dropdownCoordinates[index] = layout.y;
}}
>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
{/* {multiple && */}
<CheckBoxRound
isChecked={item.isChecked}
onPress={() => {
this.onChangeItemPress(item, index)
}}
/>
{/* } */}
<TouchableOpacity
key={index}
onPress={() => {
this.onChangeItemPress(item, index)
}}
style={[styles.dropDownItem, itemStyle]}
disabled={multiple}>
<View style={{ alignItems: 'center', flexDirection: 'row' }}>
<Text style={[labelStyle]}>
{item.name}
</Text>
</View>
</TouchableOpacity>
</View>
{index + 1 != items.length && <View style={{ flex: 1, backgroundColor: '#DDDDDDAA', height: 1 }} />}
</View>
)) : (
<View style={styles.notFound}>
{this.props.searchableError()}
</View>
)}
</ScrollView>
</View>
</View>
);
}
}
DropDownPicker.defaultProps = {
placeholder: 'Select an item',
dropDownMaxHeight: 200,
style: {},
dropDownStyle: {},
containerStyle: {},
itemStyle: {},
labelStyle: {},
selectedLabelStyle: {},
placeholderStyle: {},
activeItemStyle: {},
activeLabelStyle: {},
arrowStyle: {},
arrowColor: '#000',
showArrow: true,
arrowSize: 15,
customArrowUp: (size, color) => <Image style={{ width: size, height: size, resizeMode: 'contain', tintColor: color }} source={icons.check} />,
customArrowDown: (size, color) => <Image style={{ width: size, height: size, resizeMode: 'contain', tintColor: color }} source={icons.check} />,
customTickIcon: (size, color) => <Image style={{ width: size, height: size, resizeMode: 'contain', tintColor: color }} source={icons.check} />,
zIndex: 5000,
disabled: false,
searchable: false,
searchablePlaceholder: 'Search for an item',
searchableError: () => <Text>Not Found</Text>,
searchableStyle: {},
searchablePlaceholderTextColor: 'gray',
isVisible: false,
autoScrollToDefaultValue: false,
multiple: false,
multipleText: '%d items have been selected',
min: 0,
max: 10000000,
selectedLabelLength: 1000,
labelLength: 1000,
scrollViewProps: {},
searchTextInputProps: {},
controller: () => { },
onOpen: () => { },
onClose: () => { },
onChangeItem: () => { },
onChangeList: () => { },
};
const styles = StyleSheet.create({
containerStyle: {
zIndex: 5000
},
arrow: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
},
dropDown: {
paddingHorizontal: 20,
paddingVertical: 5,
backgroundColor: '#fff',
borderRadius: 10,
borderWidth: 1,
borderColor: '#dfdfdf',
alignItems: 'center'
},
dropDownBox: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
width: '100%',
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
},
dropDownItem: {
paddingHorizontal: 10,
height: 55,
justifyContent: 'center',
width: '100%',
flexDirection: 'row',
justifyContent: 'center'
},
input: {
flex: 1,
borderColor: '#dfdfdf',
borderBottomWidth: 1,
paddingHorizontal: 0,
paddingVertical: 8,
marginBottom: 10,
},
hidden: {
position: 'relative',
display: 'none',
borderWidth: 0
},
noBottomRadius: {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
},
notFound: {
marginVertical: 10,
marginBottom: 15,
alignItems: 'center'
},
checkBox: {
marginHorizontal: 5,
borderRadius: 10,
width: 20,
height: 20,
alignItems: 'center',
justifyContent: 'center',
padding: 5,
},
shadowElevation: {
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.10,
shadowRadius: 10.84,
elevation: 5,
},
downArrowStyle: {
width: 15,
height: 15,
},
closeIconStyle: {
width: 20,
height: 20,
backgroundColor: colors.white,
padding: 5,
borderRadius: 10,
marginRight: -2,
alignItems: 'center',
justifyContent: 'center'
}
});
export default DropDownPicker; |
As i said in the first response to your issue you have to read https://github.com/hossein-zare/react-native-dropdown-picker#zindex-conflicts-untouchable-items-overlapping-pickers section. There are some places that conflicts may occur that's why you should try each step one after another if not solved.
Please apply the following changes: pickerContainer: {
flexDirection: 'row',
minHeight: 55,
alignItems: 'center',
marginTop: 10,
paddingHorizontal: 10,
},
pickerStyle: {
backgroundColor: colors.lightGrey,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.10,
shadowRadius: 10.84,
elevation: 5,
borderRadius: 10,
borderWidth: 0
} <DropDownPicker
...
containerStyle={[styles.pickerContainer, { paddingHorizontal: 0, flexDirection: 'column' }]}
style={styles.pickerStyle}
...
/> Similar issue: |
Same error, and no solution yet. :( |
@LeandroFrazao Please review it here |
Thank you so much, should read README of package.. |
I just went on a deep dive on this one and learned more than I wanted to about zIndexing, sibling views, android layout optimizations, elevation etc. Would you believe if you have nested views you can reuse the dropdown open state to dynamically change container zindex all by itself and it seems to work ? Maybe solution, pending feedback #376 |
##Description
It's working fine on iOS but on android, it's visible on the top other components but not clickable I tried all the things like zIndex or elevation. Kindly assist me with this.
##Screen Recording
https://user-images.githubusercontent.com/33172988/103146567-56e83d00-476d-11eb-9647-f78451a0d16e.mov
The text was updated successfully, but these errors were encountered: