Flipkart / recyclerlistview

High performance listview for React Native and web!
Apache License 2.0
5.22k stars 428 forks source link

Recyclerlistview have to be a bounded size #694

Open serverlocal017 opened 2 years ago

serverlocal017 commented 2 years ago

Hello,

I know there a posts where I can solve this issue but this dont work correctly for me.

if I use { minWidth: 1, maxWidth: 1 }, then I only see two items, the rest is not visible, but I can scroll down so .

I used also flex: 1 but not working. What can I also do now to solve this issue ?

App.tsx

const renderItem: ListRenderItem<IArr> = ({ item }) => {
  return (
    <View style={{width, flex: 1}}>
      <RecyclerList />
    </View>
  )
};

interface INav {
  rNav: {
    transform: {
      translateX: number;
    }[]
  },
  onPress: (i: number) => void;
}

const Header = ({ rNav, onPress }: INav) => {
  return (
    <View style={{flex: 1}}>
    <View style={[{flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', marginVertical: 20, backgroundColor: '#ccc', width}]}>
      {
        arr.map((el, i) => (
          <Pressable onPress={() => onPress(i)} key={i}>
            <Text>{el.text}</Text>
          </Pressable>
        ))
      }
    </View>
    <Animated.View style={[{backgroundColor: 'red', height: 8, width: width / 4}, rNav]} />
    </View>
  )
};

export default function App() {
  const translateX = useSharedValue(0);

  const gestureEvent = useAnimatedScrollHandler((e) => {
    translateX.value = e.contentOffset.x
  });

  const sr = useRef(null);
  const scrollRef = useRef<FlatList>(null);

  const onPress = (i: number) => {
    //translateX.value = i * width
    scrollRef.current?.scrollToIndex({ animated: true, index: i });
  };

  const rNav = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: translateX.value * 0.25 }]
    }
  });

  return (
    <GestureHandlerRootView style={s.container}>

      <ScrollView onEnded={() => console.log('s')} nestedScrollEnabled style={{flex: 1}}>

        <View style={{height: 300, backgroundColor: 'red'}}>
          <Text>Hello</Text>  
        </View>

       <Header onPress={(i) => onPress(i)} rNav={rNav} />

        <AnimatedFlatlist
          onScroll={gestureEvent}
          ref={scrollRef}
          onEndReached={() => console.log('S')}
          keyExtractor={(item, i) => item.id}
          data={arr}
          style={{minWidth: 1, minHeight: 1}}
          horizontal
          pagingEnabled
          scrollViewProps={{nestedScrollEnabled: true}}
          renderItem={renderItem}
        />

      </ScrollView>

    </GestureHandlerRootView>
  )
}

Recyclerlistview:

import React, { useMemo } from 'react';
import { Dimensions, Image, StyleSheet, Text, View } from 'react-native';
import { RecyclerListView, LayoutProvider, DataProvider } from 'recyclerlistview';

const Data = [
  {
    item: {
      id: '1',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '2',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '3',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '4',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '5',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '6',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '7',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '8',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '9',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
  {
    item: {
      id: '10',
      name: 'Hello',
      image: 'https://picsum.photos/200/300'
    },
    type: 'NORMAL'
  },
];

const { width } = Dimensions.get('window');

export default function RecyclerList() {

  const data = useMemo(() => {
    return new DataProvider((r1, r2) => {
      return r1 !== r2;
      }, index => {
        return 'index' + index;
      }
    )
  }, []);

  const dataprovider = useMemo(() => {
    return data.cloneWithRows(Data);
  }, []);

  const layoutprovider = new LayoutProvider((i) => {
    return dataprovider.getDataForIndex(i).type;
    }, (type, dim) => {
      switch(type) {
        case 'NORMAL':
          dim.height = 250;
          dim.width = width;
        break;
        default:
          dim.height = 0;
          dim.width = 0;
        break;
      }
    }
  );

  const rowRenderer = (type, data) => {
    const { name, image } = data.item;
    return (
      <View>
        <Text>{name}</Text>
        <Image source={{uri: image}} style={{height: 200, width: 200}} resizeMode='contain' />
      </View>
    )
  };

  return (
    <View style={{flex: 1}}>
      <RecyclerListView
        dataProvider={dataprovider}
        layoutProvider={layoutprovider}
        rowRenderer={rowRenderer}
        style={{flex: 1}}
        onEndReached={() => console.log('LOOL')}
        forceNonDeterministicRendering
      />
    </View>
  )
}
fkazemi5236 commented 2 years ago

you should to define height and that's worked!

<RecyclerListView
        dataProvider={dataprovider}
        layoutProvider={layoutprovider}
        rowRenderer={rowRenderer}
        style={{flex: 1 , height: 500}}

        onEndReached={() => console.log('LOOL')}
        forceNonDeterministicRendering
      />
kaueDM commented 2 years ago

Use layoutSize prop to set a default Layout value. I tried with flex and minimum sizes but doesn't work as expected.

My solution:

<RecyclerListView
          layoutProvider={layoutProvider}
          dataProvider={dataProvider}
          rowRenderer={rowRenderer}
          canChangeSize // <- Required prop for `layoutSize`
          layoutSize={{ width: NUMBER, height: NUMBER }} // <- default size for the rendering items
        />

layoutSize is an object with width and height