问题
I have two pickers on my screen. Whenever I navigate to the screen in iOS app I find that the pickers are always open and all options are visible.
It works perfectly fine in Android where the options are visible only after we click on the picker.
Can somebody suggest a solution to fix this in iOS?
回答1:
Use ActionSheet instead of Picker on iOS. https://facebook.github.io/react-native/docs/actionsheetios.html
As answered by jevakallio this is the default behaviour on iOS. But this doesn't give a good UX so remove all picker components and replace with ActionSheet.
I did and it works great. The reason I prefered ActionSheet over other components suggested by jevakallio because it is developed by the RN team and has a good native feeling. The last option suggested react-native-modal-picker is also very good.
回答2:
That's just how the iOS UIPickerView
component works - there's no way to customize it.
If you want a different kind of UI element, you'll need to write your own, or use one of the many open source libraries, such as:
- react-native-dropdown
- react-native-modal-dropdown
- react-native-modal-picker
Googling with these, and similar keywords, yields many other libraries as well.
回答3:
React-native-modal-picker was discontinued. react-native-modal-selector
回答4:
I don't know why you'd choose the answer with ActionSheet as accepted answer. However I'll give a workaround for this problem:
Put this values in your state:
this.state= {
pickerOpacity: 0,
opacityOfOtherItems: 1 //THIS IS THE OPACITY OF ALL OTHER ITEMS, WHICH COLLIDES WITH YOUR PICKER.
label: 'Firstvalue'
}
In your render method do following:
{this.checkIfIOS()}
<Picker
selectedValue={this.state.selected}
style={{ height: 50, alignSelf: 'center', opacity: this.state.pickerOpacity, marginBottom:30, width: 250}}
onValueChange={(itemValue, itemIndex) =>{
this.setState({
selected: itemValue,
label: itemValue
});
toggle();
}
}>
<Picker.Item label="Your Label" value="yourValue"/>
</Picker>
So now we've to check, whether our client is android or ios. Therefore import Platform and put the checkIfIos()-Method in your code:
import {Platform} from 'react-native'
checkIfIOS(){
if(Platform.OS === 'ios'){ // check if ios
console.log("IOS!!!");
//this button will (onpress) set our picker visible
return (<Button buttonStyle={{backgroundColor:'#D1D1D1', opacity: this.state.opacityOfOtherItems}} onPress={this.toggle()} color="#101010" title={this.state.label} onPress={this.changeOpacity}/>);
}else if(Platform.OS === 'android'){ //check if android
this.setState({
pickerOpacity: 1 //set picker opacity:1 -> picker is visible.
});
console.log("ANDROID!!!");
}
}
toggle(){
if(Platform.OS === 'ios'){
if(this.state.pickerOpacity == 0){
this.setState({
pickerOpacity: 1,
opacityOfOtherItems: 0 // THIS WILL HIDE YOUR BUTTON!
});
}else{
this.setState({
pickerOpacity: 0,
opacityOfOtherItems: 1
});
}
}
}
回答5:
Extending the ActionSheetIOS
answer, I created a custom component that is a drop-in replacement for Picker
(I'm using Button
from https://react-native-elements.github.io/react-native-elements/docs/overview.html):
import React from 'react';
import { ActionSheetIOS, Platform } from 'react-native';
import { Button } from 'react-native-elements';
class PickerDropDown extends React.Component {
onIOSButton = () => {
let options = this.props.children.map((item, i) => {
return item.props.label;
});
options.push("Cancel");
ActionSheetIOS.showActionSheetWithOptions(
{
options: options,
cancelButtonIndex: options.length - 1,
},
this.onIOSButtonPick
);
}
onIOSButtonPick = (buttonIndex) => {
if (buttonIndex < this.props.children.length && buttonIndex != this.props.selectedValue) {
if (typeof this.props.selectedValue === 'undefined' || (typeof this.props.selectedValue !== 'undefined' && buttonIndex != this.findIndexForValue(this.props.selectedValue))) {
this.props.onValueChange(this.props.children[buttonIndex].props.value, buttonIndex);
}
}
}
findLabelForValue = (searchValue) => {
for (let i = 0; i < this.props.children.length; i++) {
if (this.props.children[i].props.value == searchValue) {
return this.props.children[i].props.label;
}
}
return null;
}
findIndexForValue = (searchValue) => {
for (let i = 0; i < this.props.children.length; i++) {
if (this.props.children[i].props.value == searchValue) {
return i;
}
}
return -1;
}
render() {
if (Platform.OS === "ios") {
let title = "";
if (this.props.children && this.props.children.length > 0) {
if (typeof this.props.selectedValue !== 'undefined') {
title = this.findLabelForValue(this.props.selectedValue);
} else {
title = this.props.children[0].props.label;
}
}
return (
<Button
title={title}
onPress={this.onIOSButton}
type="clear"
icon={{
name: "arrow-drop-down",
size: 15,
color: "black"
}}
iconRight={true}
/>
);
} else {
return (
<Picker {...this.props} />
);
}
}
}
来源:https://stackoverflow.com/questions/41181683/react-native-ios-picker-is-always-open