React Native ios picker is always open

后端 未结 8 663
天涯浪人
天涯浪人 2020-12-30 18:45

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

相关标签:
8条回答
  • 2020-12-30 19:26

    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 (
          <View>
            <Button
              title={title}
              onPress={this.onIOSButton}
              type="clear"
              icon={{
                name: "arrow-drop-down",
                size: 15,
                color: "black"
              }}
              iconRight={true}
            />
         </View>
          );
        } else {
          return (
            <Picker {...this.props} />
          );
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-30 19:32

    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
                 });
              }
         }
    }
    

    EDIT: Screenshot with iOS (Click here for Video)

    0 讨论(0)
  • 2020-12-30 19:33

    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.

    0 讨论(0)
  • 2020-12-30 19:33

    use

    <Picker itemStyle={{height:50}} > </Picker>

    it only affect ios picker. change picker itemstyle height to your standard.

    0 讨论(0)
  • 2020-12-30 19:35

    React-native-modal-picker was discontinued. react-native-modal-selector

    0 讨论(0)
  • 2020-12-30 19:35

    react-native-dropdown has reference bugs If you don't want to use Action Sheets but a 'real' picker, this one I found is way better...

    https://github.com/lawnstarter/react-native-picker-select

    0 讨论(0)
提交回复
热议问题