0

Ich versuche, ein Element in einer horizontalen ListView zu zentrieren, wenn ausgewählt. Meine aktuelle Strategie besteht darin, zuerst das Element zu messen und zu den x-Koordinaten des referenzierten Elements innerhalb der Ansicht zu scrollen.Wie zentriere ich ein Element in einem React Native ListView?

enter image description here

Derzeit jedes Mal wenn ich ein Element drücken ListView scrollt die sehr x: 538

Ende Gibt es einen einfacheren Weg, dies zu implementieren, während der Code staatenlos/functional zu halten?

const ItemScroll = (props) => { 

    const createItem = (obj, rowID) => { 

    const isCurrentlySelected = obj.id === props.currentSelectedID 

    function scrollToItem(_scrollViewItem, _scrollView) { 
     // measures the item coordinates 
     _scrollViewItem.measure((fx) => { 
     console.log('measured fx: ', fx) 
     const itemFX = fx; 
     // scrolls to coordinates 
     return _scrollView.scrollTo({ x: itemFX }); 
     }); 
    } 
    return (
     <TouchableHighlight 
     ref={(scrollViewItem) => { _scrollViewItem = scrollViewItem; }} 
     isCurrentlySelected={isCurrentlySelected} 
     style={isCurrentlySelected ? styles.selectedItemContainerStyle : styles.itemContainerStyle} 
     key={rowID} 
     onPress={() => { scrollToItem(_scrollViewItem, _scrollView); props.onEventFilterPress(obj.id, rowID) }}> 
     <Text style={isCurrentlySelected ? styles.selectedItemStyle : styles.itemStyle} > 
      {obj.title} 
     </Text> 
     </TouchableHighlight> 
    ) 
    }; 
    return (
    <View> 
     <ScrollView 
     ref={(scrollView) => { _scrollView = scrollView; }} 
     horizontal> 
     {props.itemList.map(createItem)} 
     {props.onItemPress} 
     </ScrollView> 
    </View> 
); 
}; 

aktualisieren

Mit @Ludovic Vorschläge, die ich jetzt zu FlatList wechseln habe, bin ich nicht sicher, wie scrollToIndex auslösen mit einer funktionalen Komponente. Unten ist mein neues ItemScroll

const ItemScroll = (props) => { 

    const { 
     itemList, 
     currentSelectedItem 
     onItemPress } = props 

    const renderItem = ({item, data}) => { 
    const isCurrentlySelected = item.id === currentSelectedItem 

    const _scrollToIndex =() => { return { viewPosition: 0.5, index: data.indexOf({item}) } } 

    return (
     <TouchableHighlight 
     // Below is where i need to run onItemPress in the parent 
     // and scrollToIndex in this child. 
     onPress={[() => onItemFilterPress(item.id), scrollToIndex(_scrollToIndex)]} > 
     <Text style={isCurrentlySelected ? { color: 'red' } : { color: 'blue' }} > 
      {item.title} 
     </Text> 
     </TouchableHighlight> 
    ) 
    } 
    return (
    <FlatList 
     showsHorizontalScrollIndicator={false} 
     data={itemList} 
     keyExtractor={(item) => item.id} 
     getItemLayout={(data, index) => (
      // Max 5 items visibles at once 
      { length: Dimensions.get('window').width/5, offset: Dimensions.get('window').width/5 * index, index } 
    )} 
     horizontal   
     // Here is the magic : snap to the center of an item 
     snapToAlignment={'center'} 
     // Defines here the interval between to item (basically the width of an item with margins) 
     snapToInterval={Dimensions.get('window').width/5} 
     renderItem={({item, data}) => renderItem({item, data})} /> 
); 
}; 

Antwort

1

Meiner Meinung nach, sollten Sie scrollToIndexFlatList

FlatList haben eine Methode verwenden, die zu einem Element Ihrer Daten direkt gehen können. Es ist fast dasselbe wie ein ScrollView, aber schlauer. Leider ist die Dokumentation sehr schlecht. Hier

ist ein Beispiel für eine FlatList ich

tat
let datas = [{key: 0, text: "Hello"}, key: 1, text: "World"}] 

<FlatList 
    // Do something when animation ended 
    onMomentumScrollEnd={(e) => this.onScrollEnd(e)} 
    ref="flatlist" 
    showsHorizontalScrollIndicator={false} 
    data={this.state.datas} 
    keyExtractor={(item) => item.key} 
    getItemLayout={(data, index) => (
     // Max 5 items visibles at once 
     {length: Dimensions.get('window').width/5, offset: Dimensions.get('window').width/5 * index, index} 
    )} 
    horizontal={true} 
    // Here is the magic : snap to the center of an item 
    snapToAlignment={'center'} 
    // Defines here the interval between to item (basically the width of an item with margins) 
    snapToInterval={Dimensions.get('window').width/5}  
    style={styles.scroll} 
    renderItem={ ({item}) => 
     <TouchableOpacity 
      onPress={() => this.scrollToIndex(/* scroll to that item */)} 
      style={styles.cell}> 
      <Text>{item.text}</Text> 
     </TouchableOpacity> 
    } 
/> 

Mehr über FlatList: https://facebook.github.io/react-native/releases/next/docs/flatlist.html

+0

Wie würde ich den Index für 'scrollToIndex' angeben? Ist es der Schlüssel, der Index in einem Array sichtbarer Elemente oder der Index im gesamten Array? – Chris

+0

Index im Array – Ludovic

+0

Würde 'onPress = {() => scrollToIndex ({viewPosition: 0.5, index: data.indexOf ({item})})} eine Lösung sein? – Chris

Verwandte Themen