Search code examples
react-nativewidthstyling

how to set up a width of an item depending on how many items render in react native


im rendering flatlist items that are coming from looped values, it is currently rendering 5 items , i want to change the width of these items depending on the number being rendered , example if i want to render 10 items the width will adjust accordingly. i tried different ways but none seem to be working. ps: my goal is to render these items without the need for scrolling, i want the 10 items to be displayed fully

here is my code so far:

    import React, { useEffect, useState } from 'react';
import { View, FlatList, Text, TouchableOpacity } from 'react-native';
import { StyleSheet } from 'react-native';
import { Button } from 'react-native-paper';

export default function Detailmodal({ value, update, setModal }) {
    const [ max, setMax ] = useState(35);
    const [ min, setMin ] = useState(30);
    const [ data, setData ] = useState([]);

    useEffect(
        () => {
            let tempData = [];

            for (let i = min; i <= max; i++) {
                tempData.push(i);
            }
            setData(tempData);
        },
        [ min, max ]
    );

    const toggleNext = () => {
        setMin(max);
        setMax(max + 5);
    };

    const togglePrev = () => {
        setMax(min);
        setMin(min - 5);
    };

    const Item = ({ value }) => (
        <TouchableOpacity onPress={() => updateParent(value)}>
            <View style={styles.temp}>
                <Text style={styles.title}>{value}</Text>
            </View>
        </TouchableOpacity>
    );

    const renderItem = ({ item }) => {
        return <Item value={item} />;
    };

    const updateParent = (value) => {
        update(value);
        setModal(false);
    };

    return (
        <View style={styles.container}>
            <Button mode='contained' onPress={togglePrev}>
                prev
            </Button>
            <FlatList data={data} renderItem={renderItem} keyExtractor={(item) => item.name} horizontal />
            <Button mode='contained' onPress={toggleNext}>
                next
            </Button>
        </View>
    );
}

const styles = StyleSheet.create({
    container             : {
        flexDirection   : 'row',
        justifyContent  : 'center',
        alignItems      : 'center',
        margin          : 50,
        paddingVertical : 50,
        backgroundColor : 'white'
    },
    contentContainerStyle : {
        justifyContent : 'center',
        alignItems     : 'center'
    },
    value                 : {
        fontWeight : '500',
        fontSize   : 50,
        color      : 'black',
        position   : 'absolute'
    },
    txtInput              : {
        fontSize  : 25,
        textAlign : 'center'
    },
    temp                  : {
        backgroundColor  : '#b19cd9',
        height           : 170,
        justifyContent   : 'center',
        marginVertical   : 20,
        marginHorizontal : 15,
        padding          : 15,
        width            : 140,

        alignItems       : 'center'
    },
    title                 : {
        fontSize : 32
    }
});

Solution

  • are you sure you want that approach? Coz if there are 100 items, displaying all without scrolling will be kind of messy

    If yes you want that approach then -> Do check out the working solution here: snakc link

    You can change the style. Basically im adding a 10px padding in the method calculateWidth.

    Here is the solution:

    import { View, FlatList, Text, TouchableOpacity,Dimensions } from 'react-native';
    import { StyleSheet } from 'react-native';
    import { Button } from 'react-native-paper';
    
    export default function Detailmodal({ value, update, setModal }) {
        const [ max, setMax ] = useState(35);
        const [ min, setMin ] = useState(30);
        const [ data, setData ] = useState([]);
    
        const deviceWidth = Dimensions.get('window').width;
    
        useEffect(
            () => {
                let tempData = [];
    
                for (let i = min; i <= max; i++) {
                    tempData.push(i);
                }
                setData(tempData);
            },
            [ min, max ]
        );
    
        const toggleNext = () => {
            setMin(max);
            setMax(max + 5);
        };
    
        const togglePrev = () => {
            setMax(min);
            setMin(min - 5);
        };
    
        const calculateWidth = () => {
          const dataLength = data.length;
          const paddingRequired = (dataLength+2)*10;
          const finalWidth = (deviceWidth - paddingRequired)/dataLength;
          return finalWidth;
    
        }
    
        const Item = ({ value }) => {
          const width = calculateWidth()
          return(
            <TouchableOpacity style={[styles.temp,{width:width}]} onPress={() => updateParent(value)}>
                    <Text style={styles.title}>{value}</Text>
            </TouchableOpacity>
          )
           
        }
    
        const renderItem = ({ item }) => {
            return <Item value={item} />;
        };
    
        const updateParent = (value) => {
            update(value);
            setModal(false);
        };
    
        return (
            <View style={styles.container}>
                <Button mode='contained' onPress={togglePrev}>
                    prev
                </Button>
                <FlatList data={data} renderItem={renderItem} keyExtractor={(item) => item.name} horizontal />
                <Button mode='contained' onPress={toggleNext}>
                    next
                </Button>
            </View>
        );
    }
    
    const styles = StyleSheet.create({
        container             : {
            justifyContent  : 'center',
            alignItems      : 'center',
            backgroundColor : 'white'
        },
        contentContainerStyle : {
            justifyContent : 'center',
            alignItems     : 'center'
        },
        value                 : {
            fontWeight : '500',
            fontSize   : 50,
            color      : 'black',
            position   : 'absolute'
        },
        txtInput              : {
            fontSize  : 25,
            textAlign : 'center'
        },
        temp                  : {
            backgroundColor  : '#b19cd9',
            height           : 170,
            justifyContent   : 'center',
            marginVertical   : 20,
            marginHorizontal : 5,
            // padding          : 15,
            // width            : 140,
    
            alignItems       : 'center'
        },
        title                 : {
            fontSize : 32
        }
    });