Code Monkey home page Code Monkey logo

react-native-smooth-picker's People

Contributors

dependabot[bot] avatar pedroaugustoramalhoduarte avatar rdhox avatar steedmonteiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

react-native-smooth-picker's Issues

initialScrollToIndex does not work with fewer than 11 items

The issue is easy to replicate:
In the example in this repo, remove all cities after "Amsterdam".
initiateScrollToIndex no longer works now. It is not until you scroll that the list jumps to the correct index.

This is how the SmoothPicker initially renders with the below code:
Screen Shot 2021-03-17 at 10 02 15

const dataCity = [
  "Paris",
  "Berlin",
  "Lisbonne",
  "Budapest",
  "Londres",
  "Prague",
  "Rome",
  "Barcelone",
  "Amsterdam",
];

const opacities = {
  0: 1,
  1: 1,
  2: 0.6,
  3: 0.3,
  4: 0.1,
};
const sizeText = {
  0: 20,
  1: 15,
  2: 10,
};

const Item = React.memo(({ opacity, selected, vertical, fontSize, name }) => {
  return (
    <View
      style={[
        styles.OptionWrapper,
        {
          opacity,
          borderColor: selected ? "#ABC9AF" : "transparent",
          width: vertical ? 190 : "auto",
        },
      ]}>
      <Text style={{ fontSize }}>{name}</Text>
    </View>
  );
});

const ItemToRender = ({ item, index }, indexSelected, vertical) => {
  const selected = index === indexSelected;
  const gap = Math.abs(index - indexSelected);

  let opacity = opacities[gap];
  if (gap > 3) {
    opacity = opacities[4];
  }
  let fontSize = sizeText[gap];
  if (gap > 1) {
    fontSize = sizeText[2];
  }

  return (
    <Item
      opacity={opacity}
      selected={selected}
      vertical={vertical}
      fontSize={fontSize}
      name={item}
    />
  );
};

const Test = () => {
  function handleChange(index) {
    setSelected(index);
    refPicker.current.scrollToIndex({
      animated: false,
      index: index,
      viewOffset: -30,
    });
  }

  const [selected, setSelected] = useState(5);
  const refPicker = useRef(null);
  return (
    <View style={styles.container}>
      <View style={styles.wrapperHorizontal}>
        <SmoothPicker
          initialScrollToIndex={selected}
          refFlatList={refPicker}
          keyExtractor={(_, index) => index.toString()}
          horizontal={true}
          scrollAnimation
          showsHorizontalScrollIndicator={false}
          data={dataCity}
          renderItem={(option) => ItemToRender(option, selected, false)}
        />
      </View>
      <View style={styles.wrapperVertical}>
        <SmoothPicker
          initialScrollToIndex={selected}
          onScrollToIndexFailed={() => {}}
          keyExtractor={(_, index) => index.toString()}
          showsVerticalScrollIndicator={false}
          data={dataCity}
          scrollAnimation
          onSelected={({ item, index }) => handleChange(index)}
          renderItem={(option) => ItemToRender(option, selected, true)}
          magnet
        />
      </View>
      <View>
        <Text>{`Your selection is ${dataCity[selected]}`}</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    paddingTop: 60,
    paddingBottom: 30,
    flex: 1,
    flexDirection: "column",
    justifyContent: "space-evenly",
    alignItems: "center",
    backgroundColor: "#F5FCFF",
  },
  wrapperHorizontal: {
    height: 100,
    justifyContent: "center",
    alignItems: "center",
    margin: "auto",
    color: "black",
  },
  wrapperVertical: {
    width: 250,
    height: 350,
    justifyContent: "center",
    alignItems: "center",
    margin: "auto",
    color: "black",
  },
  OptionWrapper: {
    justifyContent: "center",
    alignItems: "center",
    marginTop: 10,
    marginBottom: 10,
    paddingTop: 10,
    paddingBottom: 10,
    paddingLeft: 30,
    paddingRight: 30,
    height: 50,
    borderWidth: 3,
    borderRadius: 10,
  },
});

export default Test;

After digging through the code a bit, I've found that in _renderItem in SmoothPicker.js, when there are 11 or more items, this._alignAfterMount() does run (in the if statement below), while if there are fewer items, it never runs.

So, for a reason I don't understand, when there are 11 or more items, the if/else statement below is run through data.length+1 times, but it is run through only data.length times when there are fewer than 11 items?

          if (this.countItems === data.length) {
            this.countItems = 0;
            this._alignAfterMount();
          } else {
            this.countItems = this.countItems + 1;
          }

initialScrollToIndex doesn't scroll to the last item

Thank you for the package, it works pretty good!
Although, I have one issue - which is a bit frustrating.
initialScrollToIndex newer opens the last item of the array. It just behaves in a weird way.
Setup:

 <SmoothPicker
                keyExtractor={(_, index) => index.toString()}
                showsVerticalScrollIndicator={false}
                initialScrollToIndex={dataCity.length - 1}
                data={dataCity}
                horizontal={true}
                scrollAnimation
                showsHorizontalScrollIndicator={false}
                renderItem={option => ItemToRender(option, selected, true)}
                magnet
            />

RTL support

Hi,
It seems that there is no rtl support. when I try to use the component on rtl the direction of the scroll is the opposite direction from the chosen index. like if I scroll left the chosen one scroll right.
if this could be fixed, it will be great!

Skips padding / margin

Hey there!

When having the scroll picker in a fixed height wrapper (which is in a display flex column container):

If I have a TextInput e.g. underneath the scrollpicker, the values inside always jumping when focusing the TextInput.

Do you knwo how to fix that?

BR, Sebi

enable using external scrolltoindex to select item

Hi,

The component looks excellent and very unusable.

I have a minor request.

I want to also enable picking an item by pressing the item itself.

Now, due to the ref feature in this component, I can use "scrollToIndex" to achieve the aforementioned goal. However, this choice does not affect the internal state of the smooth picker component and thus, when performing the scrollToIndex, the selection does not change.

My request is could you please add a prop which on change changes the selected item/index or could you please a "scrollToIndex" method that can allow to programmatically scroll to the item and perform the internal state change?

initialScrollToIndex does not work when input data size is reduced

Following code works fine

const petTypes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

export default class Example extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selected: 5
    };
  }

  onPetChange = index => {
    this.setState({
        selected: index
    });
  };

  render() {
    return (
      <SmoothPicker
        style={{ marginTop: 300 }}
        horizontal
        initialScrollToIndex={this.state.selected}
        keyExtractor={(_, index) => index.toString()}
        ref={ref => (this.refPetList = ref)}
        showsHorizontalScrollIndicator={false}
        bounces={true}
        magnet={true}
        scrollAnimation
        data={petTypes}
        onSelected={({ item, index }) => this.onPetChange(index)}
        renderItem={({ item, index }) => {
          return this.petPickerItem(index, item);
        }}
      />
    );
  }

  petPickerItem = (index, item) => {
    return <Text style={this.state.selected === index?{color:"red"}:{color: "#000000"}}>{index}</Text>;
  };
}

Result for the above code
Screen Shot 2019-08-30 at 2 35 04 AM

When the input array is reduced by one value to the following
const petTypes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

Following is the result
Screen Shot 2019-08-30 at 2 37 15 AM

Uncontrolled movement with fast scrolling in horizontal mode release mode

I'm facing this issue only in release mode that the smooth picker moves uncontrollably in horizontal mode with fast scrolling.
Not able to reproduce this in Debug mode and hence not able to solve it. Scrolling stops abruptly after some time or when I close the App and restart.

"react-native-smooth-picker": "^1.0.2",

 <SmoothPicker
   initialScrollToIndex={selected}
   refFlatList={refPicker}
   keyExtractor={(_, index) => index.toString()}
   horizontal={true}
   scrollAnimation
   showsHorizontalScrollIndicator={false}
   data={constants.MyArray}
   renderItem={option => ItemToRender(option, selected, false)}
   onSelected={({ item, index }) => handleChange(index)}
   style={{backgroundColor: 'white', paddingLeft: 5, paddingRight: 5}}
 />

function handleChange(index) {
    setSelected(index);
    refPicker.current.scrollToIndex({
      animated: true,
      index: index,
      viewOffset: -30,
    });
  }

const ItemToRender = ({item, index}, indexSelected, vertical) => {
  const selected = index === indexSelected;
  const gap = Math.abs(index - indexSelected);

  let opacity = opacities[gap];
  if (gap > 3) {
    opacity = opacities[4];
  }
  let fontSize = sizeText[gap];
  if (gap > 1) {
    fontSize = sizeText[2];
  }

  return <Item opacity={opacity} selected={selected} vertical={vertical} fontSize={fontSize} name={item}/>;
};

Picker is not smooth for large data more than 150

Hello ,

The package is very Good.
Only i'm facing issue for large array data.
I want to use horizontal scroll option for 200 to 250 data.

this is my code
const data = Array.from(Array(250).keys()).slice(100, 250);
<SmoothPicker
initialScrollToIndex={selected}
onScrollToIndexFailed={() => {}}
keyExtractor={(_, index) => Math.random()}
showsHorizontalScrollIndicator={false}
data={data}
scrollAnimation={true}
onSelected={({ item, index }) => handleChange(index,item)}
renderItem={(option) => ItemToRender(option, selected, true)}
magnet
selectOnPress
horizontal
/>

const Item = React.memo(({ opacity, selected, horizontal, fontSize, name }) => {
color = selected ? "#fff" : "#717171";
return (
<View
style={[
styles.OptionWrapper,
{
opacity,
width: horizontal ? 10 : "auto",
backgroundColor: selected ? "#ff9800" : "transparent",
},
]}
>
{selected ? (

) : (

)}

);
});

const ItemToRender = ({ item, index }, indexSelected, horizontal) => {
const selected = index === indexSelected;
const gap = Math.abs(index - indexSelected);

let opacity = opacities[gap];
if (gap > 3) {
opacity = opacities[4];
}
let fontSize = sizeText[gap];
if (gap > 1) {
fontSize = sizeText[2];
}
return (
<Item
opacity={opacity}
selected={selected}
horizontal={horizontal}
fontSize={fontSize}
name={ <View
style={[

      {
        backgroundColor: '#4c3e5c30' ,
        height: 15,
        width:0.3,
        marginRight: 1
      },
    ]}
  ><Text>{item}</Text></View>}
/>

);
};
If you have any solution, Please help me.

Thanks

Use custom FlatList component

I need to use FlatList from react-native-gesture-handler for being able to scroll on nested component.

Maybe could be something like this:

import { FlatList } from 'react-native-gesture-handler';

<SmoothPicker
  ...
  flatListComponent={<FlatList />}
/>

initialScrollToIndex is not working correctly

I've tried to use the prop initialScrollToIndex to make the picker select its first item when it is rendered. So I used the following code:

<SmoothPicker
  offsetSelection={0}
  horizontal={true}
  snapInterval={50}
  showsHorizontalScrollIndicator={false}
  initialScrollToIndex={0}

  data={data.map((item, index) => item.text)}
  onSelected={({item, index}) => this.handleChangeSelectedItem(index)}
  renderItem={({item, index}) => (
    <Text
      style={index===this.state.selectedIndex ? stylestext_selected : styles.text}
      key={item}
    >
      {item}
    </Text>
  )}

  magnet={true}
  scrollAnimation={true}
  snapToAlignment={'start'}
/>

Unfortunately, no item in the list is selected, when its rendered first:

bildschirmfoto 2019-01-25 um 13 49 20

Did I make a mistake when using the prop?

initialScrollToIndex behaving in a weird way

I'm having a problem with initialScrollToIndex method, so when my component renders the list should immediately scroll to a certain given index, i was passing that through redux. the behavior i'm getting is that when the component mounts the initialScrollToIndex sometimes works sometimes it doesn't. first i thought its from redux so i simply gave it a static index of 10, though the unstable behavior remains. sometimes it moves sometimes no.

<SmoothPicker
offsetSelection={0}
initialScrollToIndex={initialIndex}
magnet
// scrollAnimation
horizontal
data={result}
activeOpacityButton={0}
keyExtractor={( index) => index.toString()}
onSelected={({ item, index }) => this.handleChange(item, index)}
renderItem={({item,index}) => this.renderScrollItem(item,index)}
/>

Regular React Support

When I try to use this component with regular React, I get an error that it's using experimental features. Would it be possible to either not use the experiment features or make another version that's compatible with normal React?

Export interface SmoothPickerProps

Hello, thanks for this amazing lib!!

I am building an custom date picker from this smooth picker, and it would be a great help if the interface props from SmoothPicker were exported. I would like to create a PR for it.

Showing scrollToIndex is not a function

Hi,
Tried your example to implement smooth scroll when on scrolling found handleChange method throws error which is
TypeError: refPicker.current.scrollToIndex is not a function. (In 'refPicker.current.scrollToIndex({animated: false,index: index,viewOffset: -30})','refPicker.current.scrollToIndex' is undefined).
Also when scrolling values not properly selecting and set in to useState by index. Please suggest what is the issue here and how to fix it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.