Skip to content

Instantly share code, notes, and snippets.

@dereknelson
Created March 29, 2018 18:03
Show Gist options
  • Save dereknelson/110dde0b537217d06043e58ba877cac5 to your computer and use it in GitHub Desktop.
Save dereknelson/110dde0b537217d06043e58ba877cac5 to your computer and use it in GitHub Desktop.
Alphabetized List implementation
import React, { Component, } from 'react';
import { View, Text, TouchableOpacity, FlatList, ListItem, Image, TextInput, Dimensions,
Animated, StyleSheet, SectionList, PanResponder, PixelRatio, ScrollView } from 'react-native';
import sectionListGetItemLayout from 'react-native-section-list-get-item-layout'
var { height, width } = Dimensions.get('window')
/* this component is re-used between displaying the friends/groups and being able to pick them in metoo posts, so there are a few different if statements that
help the component decide whether to render something that is clickable that will be highlighted/checked or if it should navigate upon clicking */
export default class AlphabetizedList extends Component {
constructor(props){
super(props)
alphabet = [ { title: 'A', data: []}, { title: 'B', data: [] }, {title: 'C', data: []}, {title: 'D', data: []}, {title: 'E', data: []}, {title: 'F', data: []}, {title: 'G', data: []}, {title: 'H', data: []},
{title: 'I', data: []}, {title: 'J', data: []}, {title: 'K', data: []}, {title: 'L', data: []}, {title: 'M', data: []}, {title: 'N', data: []}, {title: 'O', data: []}, {title: 'P', data: []}, {title: 'Q', data: []},
{title: 'R', data: []}, {title: 'S', data: []}, {title: 'T', data: []}, {title: 'U', data: []}, {title: 'V', data: []}, {title: 'W', data: []}, {title: 'X', data: []}, {title: 'Y', data: []}, {title: 'Z', data: []} ]
this.state = { results: ["Kaleb", "Alex", "Alden", "Alex", "Alyssa", "Amanda", "Amarinda", "Andy", "alyssa", "Antonio", "Justin", "Apple", "Baylor", "ashlynn", "Augusto", "Alex", "ben", "carter", "Billy",
"Garrett", "Brendan", "Brady", "Brady", "Brandon", "Brevin", "Brendan", "Bros", "Camille", "Carina", "caro", "Eron", "Carter", "Charlie", "Chris", "Christine", "Cleo", "Colleen", "Collin", "Cora", "Corey", "Cory",
"Connor", "Dakota", "Dan", "Dan", "dennis", "Derek", "Stephen", "Alex", "drew", "Isaac", "Will", "eliza", "ellie", "Emily", "faith", "Peter", "Ike", "Ryan", "James", "Francesca", "Gabe", "Garrett", "George", "Giuseppe",
"Matt", "Greg", "Vincent", "Grant", "Haidar", "Jakob", "Hanna", "Harry", "helena", "Hunter", "Sean", "Ian", "Ian", "Jordan", "jack", "Jacob", "Jake", "Jake", "Jake", "Jacob", "Chris", "James", "Jed", "Jess", "jill", "Jim",
"Jimi", "Joe", "Jon", "Jonny", "Josh", "Jo", "Jullian", "Jonathan", "Kailee"],
searchText: '', alphabet: alphabet, alphabetPlaceHolder: alphabet, }
this.getItemLayout = sectionListGetItemLayout({
// The height of the row with rowData at the given sectionIndex and rowIndex
// getItemHeight: (this.state.alphabet, 0, 0) => sectionIndex === 0 ? 100 : 50,
getItemHeight: (rowData, sectionIndex, rowIndex) => sectionIndex === 0 ? 150 : 20,
// These three properties are optional
getSeparatorHeight: () => 1 / PixelRatio.get(), // The height of your separators
getSectionHeaderHeight: () => 10, // The height of your section headers
getSectionFooterHeight: () => 0, // The height of your section footers
})
}
componentWillMount(){
var alphabet = this.sort()
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: (event, gestureState) => true,
onStartShouldSetPanResponderCapture: (event, gestureState) => true,
onMoveShouldSetPanResponder: (event, gestureState) => true,
onMoveShouldSetPanResponderCapture: (event, gestureState) => true,
onPanResponderGrant: (event, gestureState) => {
for (i = 0; i < alphabet.length; i++){
var { letterPosition, letterHeight } = alphabet[i]
letterPosition += this.offset
if (event.nativeEvent.pageY < letterPosition + letterHeight && event.nativeEvent.pageY > letterPosition){
this.scroll(i)
break
}
}
},
onPanResponderMove: (event, gestureState) => {
for (i = 0; i < alphabet.length; i++){
var { letterPosition, letterHeight } = alphabet[i]
letterPosition += this.offset
if (event.nativeEvent.pageY < letterPosition + letterHeight && event.nativeEvent.pageY > letterPosition){
this.scroll(i)
break
}
}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
},
onPanResponderTerminate: (evt, gestureState) => {
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return true;
},
})
}
render() {
var { alphabet } = this.state
return (
<View onLayout={(event) => this.getOffset(event)} style={{ flexDirection: 'row', backgroundColor: 'white'}}>
<SectionList
sections={alphabet}
ref={ref => this.list = ref}
keyExtractor={(item, index) => index}
renderItem={this.renderItem}
ListHeaderComponent={this.SearchBar}
SectionSeparatorComponent={this.separator}
getItemLayout={this.getItemLayout}
/>
<View style={{ position: 'absolute', right: 5, height: height, justifyContent: 'center', }} >
<this.renderSidebar/>
</View>
</View>
)
}
renderItem = ({item, index}) => (
<View style={{ flexDirection: 'row', alignItems: 'center', borderWidth: StyleSheet.hairlineWidth, borderColor: 'gray', paddingVertical: 5}} >
<Text style={{ fontSize: 20, paddingLeft: 15 }}>
{item}
</Text>
</View>
)
onLayout = (event) => {
var { x, y, width, height } = event.nativeEvent.layout;
this.totalHeight = height
}
// for the sake of simplicity, this doesn't actually do anything, but is more for adding complexity to the height of the overall component
SearchBar = () => (
<View style={{ flexDirection: 'row', alignItems: 'center', borderColor: 'gray', borderWidth: StyleSheet.hairlineWidth, }}>
<TextInput
style={{ width: width * .95, backgroundColor: 'white', paddingLeft: 15, fontSize: 18, paddingVertical: 15 }}
value={this.state.searchText}
ref={ref => this.textInput = ref}
onChangeText={(text) => this.setState({ searchText })}
placeholder='Search friends'
autoCapitalize={'none'}
autoCorrect={false}
clearButtonMode="while-editing"
/>
</View>
)
separator = (separator) => {
if (separator.trailingItem != null){
return (
<Text style={{ paddingLeft: 20, fontSize: 20, color: 'blue' }} >
{separator.section.title}
</Text>
)
}
return null
}
keyExtractor = (item, index) => item.uuid;
scroll = (index) => {
this.list.scrollToLocation({ itemIndex: 0, sectionIndex: index, viewPosition: 0, animated: false })
}
setLetterPosition = (event, i) => {
var { alphabet } = this.state
// the + 60 is for the safeareaview which doesn't get counted in onlayout
alphabet[i].letterPosition = event.nativeEvent.layout.y + 60, alphabet[i].letterHeight = event.nativeEvent.layout.height
}
getOffset = (event) => {
this.offset = event.nativeEvent.layout.y
}
renderSidebar = () => {
var { alphabet } = this.state
return (
<View {...this.panResponder.panHandlers} hitSlop={{ left: 5 }} onLayout={(event) => this.getOffset(event)}
style={{ flexDirection: 'column', flexBasis: 'auto', alignContent: 'center', justifyContent: 'center', alignItems: 'center' }} >
{ alphabet.map((data, i) => {
return (
<Text key={i} onLayout={(event) => this.setLetterPosition(event, i)} style={{ fontSize: 13, color: 'gray'}} >
{data.title}
</Text>
)
}) }
</View>
)
}
sort = () => {
const { results } = this.state
var alphabet = [ { title: 'A', data: []}, { title: 'B', data: [] }, {title: 'C', data: []}, {title: 'D', data: []}, {title: 'E', data: []}, {title: 'F', data: []}, {title: 'G', data: []}, {title: 'H', data: []},
{title: 'I', data: []}, {title: 'J', data: []}, {title: 'K', data: []}, {title: 'L', data: []}, {title: 'M', data: []}, {title: 'N', data: []}, {title: 'O', data: []}, {title: 'P', data: []}, {title: 'Q', data: []},
{title: 'R', data: []}, {title: 'S', data: []}, {title: 'T', data: []}, {title: 'U', data: []}, {title: 'V', data: []}, {title: 'W', data: []}, {title: 'X', data: []}, {title: 'Y', data: []}, {title: 'Z', data: []} ]
for (i = 0; i < results.length; i++){
const letter = results[i][0].toLowerCase()
if (letter == 'a') alphabet[0].data.push(results[i])
if (letter == 'b') alphabet[1].data.push(results[i])
if (letter == 'c') alphabet[2].data.push(results[i])
if (letter == 'd') alphabet[3].data.push(results[i])
if (letter == 'e') alphabet[4].data.push(results[i])
if (letter == 'f') alphabet[5].data.push(results[i])
if (letter == 'g') alphabet[6].data.push(results[i])
if (letter == 'h') alphabet[7].data.push(results[i])
if (letter == 'i') alphabet[8].data.push(results[i])
if (letter == 'j') alphabet[9].data.push(results[i])
if (letter == 'k') alphabet[10].data.push(results[i])
if (letter == 'l') alphabet[11].data.push(results[i])
if (letter == 'm') alphabet[12].data.push(results[i])
if (letter == 'n') alphabet[13].data.push(results[i])
if (letter == 'o') alphabet[14].data.push(results[i])
if (letter == 'p') alphabet[15].data.push(results[i])
if (letter == 'q') alphabet[16].data.push(results[i])
if (letter == 'r') alphabet[17].data.push(results[i])
if (letter == 's') alphabet[18].data.push(results[i])
if (letter == 't') alphabet[19].data.push(results[i])
if (letter == 'u') alphabet[20].data.push(results[i])
if (letter == 'v') alphabet[21].data.push(results[i])
if (letter == 'w') alphabet[22].data.push(results[i])
if (letter == 'x') alphabet[23].data.push(results[i])
if (letter == 'y') alphabet[24].data.push(results[i])
if (letter == 'z') alphabet[25].data.push(results[i])
}
// this.totalHeight = 0
// for (i = 0; i < alphabet.length; i++){
// this.totalHeight += alphabet[i].data.length * 69
// alphabet[i].height = this.totalHeight // entirely coincidentally, the height of each friend is 69
// }
this.setState({ alphabet })
return alphabet
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment