React Native iOS选择器始终处于打开状态

45

我屏幕上有两个选择器。每当我在iOS应用程序中导航到该屏幕时,我发现选择器总是打开,并且所有选项都可见。

enter image description here

在Android中,只有在我们点击选择器后选项才可见,它可以完美地工作。有人能提供一个解决方案来修复iOS中的这个问题吗?

如何移除选择器行 - sejn
你可以仅针对iOS,在选择的值上显示可触摸文本,当触摸时使选择器可见。然后在选择项目后再次隐藏选择器。 - bitsmanent
8个回答

27
在iOS上使用ActionSheet代替Picker。 https://facebook.github.io/react-native/docs/actionsheetios 根据jevakallio的回答,这是iOS上的默认行为。但这并不会提供良好的用户体验,所以请删除所有选择器组件,并用ActionSheet替换它们。 我这样做了,效果很好。我之所以更喜欢ActionSheet而不是jevakallio建议的其他组件,是因为它由RN团队开发,拥有良好的本地体验。最后一个建议react-native-modal-picker也很好。 输入图像描述

12
操作表不应仅用于动作吗? - Made in Moon
你也可以使用https://github.com/peacechen/react-native-modal-selector。它不会提供原生的选择器,但在两个平台上都能给出一致的感觉。 - Piyush Beli
1
好的,但是对于具有数十个选项(例如语言选择)的 Picker 呢?这不是一个安全的替代品。这是完全不同的组件。 - EntangledLoops

13

1
有用,但使用操作表来处理长列表的数据可能不是首选。在react-native-modal-picker/react-native-modal-selector中,底部会保留额外的填充。目前还没有找到完美的解决方案。 - AFLAH ALI

12

我不知道为什么您会选择ActionSheet作为接受的答案。但是我将为此问题提供解决方法:

将这些值放入您的状态中:

this.state= {
    pickerOpacity: 0,
    opacityOfOtherItems: 1 //THIS IS THE OPACITY OF ALL OTHER ITEMS, WHICH COLLIDES WITH YOUR PICKER.
    label: 'Firstvalue'
}

在你的渲染方法中执行以下操作:

{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>

现在我们需要检查客户端是Android还是iOS。因此,导入平台并将checkIfIos()-方法放入您的代码中:

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

编辑:iOS屏幕截图(点击此处观看视频

iOS中DatePicker的屏幕截图


你有没有这个的示例代码?我正在尝试实现它,但遇到了困难,也不确定其是否有效。 - Ren
很遗憾,你只需要放置toggle()和checkIfIOS()方法,并在渲染选择器之前运行checkIfOs,在你的选择器的onValueChange事件中使用toggle()方法。如果你能提供你的视图,我可以帮助你如何实现它。 - Sercan Samet Savran
1
@SercanSametSavran,你能提供一下选择器的截图吗? 在视图中按钮长什么样子? 似乎缺少this.changeOpacity()的实现。 - Erab BO
抱歉回复晚了。但我做了一些更好的事情,并上传了一个视频,您可以在其中看到日期选择器的实际效果(ios)。这是链接:https://streamable.com/pzaio - Sercan Samet Savran
1
这是目前为止最好的解决方案,应该被接受作为答案。 - bitsmanent
显示剩余3条评论

7

使用

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

它只影响iOS的Picker组件。将Picker中的itemStyle高度更改为您的标准即可。


其实这对我来说就是诀窍,所以我不需要使用其他方法!谢谢 - Meiki Neumann

7

2

扩展ActionSheetIOS的答案,我创建了一个自定义组件,可以直接替换Picker(我使用https://react-native-elements.github.io/react-native-elements/docs/overview.html中的Button):

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

它是什么样子?请提供一个视频或快照。 - IsmailS
我使用了这个代码并且它可以正常工作。只是它没有使用完整的可用宽度,就像选择器一样。 - IsmailS
1
我用<View>将其包装,并在上面设置了样式属性。 react-native-elements按钮上的样式未应用。 - IsmailS
1
最佳答案。此解决方案尽可能使用本地选择器,并且代码量很少。而且,这个可替换的解决方案实现起来非常快速。 - IsmailS
1
我使用了这个类,并进行了一些小的样式更改,按照@IsmailS的建议将其包装在<View>中,并将其发布到了Gist上:https://gist.github.com/thargenediad/7615e281baab25733ca0e7f5c7cb97d6我希望它能帮助某些人节省时间来尝试设计Kevin的组件。享受吧! - thargenediad

1

-3

使用native-base库而不是react-native进行导入


问题出在React Native选择器元素上,而第三方库如native-base并不是我们正在寻找的。 - Sathwik Gangisetty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接