Range slider in React Native

107 Views Asked by At

I'm trying to figure out how to add those 'prefixes'. Do I need to handle it through styling manually, or is there a specific prop I should be using? I'm still getting the hang of it, so any guidance would be greatly appreciated

this is the figma design that i want to develop

I'am using '@ptomasroos/react-native-multi-slider' library

And this is the component of the range slider:

import MultiSlider from '@ptomasroos/react-native-multi-slider';
import React, { useEffect, useState } from 'react';
import { Dimensions, StyleSheet, Text, View } from 'react-native';

export default function RangeNumber({ onChange}) {
    const [value, setValue] = useState({ values: [0, 800000] });
    const multiSliderValuesChange = (values) => {
        setValue({
            values,
        });
    };
    useEffect(() => {
        onChange(value)
    }, [value])
    return (
        <View style={styles.container}>
            <MultiSlider
                values={[value.values[0], value.values[1]]}
                sliderLength={Dimensions.get('window').width * 0.83}
                selectedStyle={{ backgroundColor: Colors.DeepGreen }}
                // containerStyle={{
                //     justifyContent: 'center',
                //     alignItems: 'center'
                // }}
                onValuesChange={multiSliderValuesChange}
                markerStyle={{
                    height: 30,
                    width: 30,
                    borderWidth: 7,
                    borderRadius: 50,
                    backgroundColor: Colors.DeepGreen,
                    borderColor: Colors.white,
                }}
                trackStyle={{
                    height: 10,
                }}
                unselectedStyle={{
                    borderRadius: 10
                }}
                min={0}
                markerOffsetY={5}
                max={800000}
                step={100}

            />
            <View style={styles.rangeText}>
                <Text style={styles.textColor}>{value.values[0]} K</Text>
                <Text style={styles.text}> - </Text>
                <Text style={styles.textColor}>{value.values[1]} K</Text>
            </View>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        alignItems: 'flex-start',
        justifyContent: 'center',
        paddingHorizontal: 15,
        paddingVertical: 5,

    },
    title: {
        fontSize: 16,
        fontFamily: FONTS.PoppinsSemiBold
    },
    text: {
        color: '#FFFFFF',
        fontSize: 20,
        marginHorizontal: 10,
        marginTop: 10
    },
    rangeText: {
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'center',
        marginTop: -20
    },
    textColor: {
        color: '#DBDBDB',
        fontSize: 20
    }
});

this is the slider i got

1

There are 1 best solutions below

0
Kondwerani Kamsesa On BEST ANSWER

You will have to style manually. Ideally the custom label prop should do this Job but I can't seem to get it to work either.

I have managed to create a basic example that outputs like so:

Example Screenshot

Code:

import React from "react";

import { StyleSheet, View, Text, Image } from "react-native";
import MultiSlider from "@ptomasroos/react-native-multi-slider";

export default function App() {
  const [multiSliderValue, setMultiSliderValue] = React.useState([0, 100]);

  nonCollidingMultiSliderValuesChange = (values) => setMultiSliderValue(values);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Sliders</Text>

      <View style={styles.sliderOne}>
        <Text style={styles.text}>
          Two Markers with minimum overlap distance:
        </Text>
      </View>
      <MultiSlider
        values={[multiSliderValue[0], multiSliderValue[1]]}
        sliderLength={280}
        onValuesChange={nonCollidingMultiSliderValuesChange}
        min={0}
        max={100}
        step={1}
        allowOverlap={false}
        snapped
        minMarkerOverlapDistance={40}
        customMarkerLeft={(e) => {
          return <CustomMarker currentValue={e.currentValue} />;
        }}
        customMarkerRight={(e) => {
          return <CustomMarker currentValue={e.currentValue} />;
        }}
        isMarkersSeparated={true}
      />
    </View>
  );
}

const CustomMarker = ({ currentValue }) => {
  return (
    <View
      style={{
        transform: [{ rotate: "90deg" }],
      }}
    >
      <View
        collapsable={false}
        style={{
          marginLeft: 54,
          marginBottom: -32,
          width: 15,
          height: 15,
          borderRadius: 10,
          backgroundColor: "blue",
        }}
      ></View>
      <View
        style={{
          width: 40,
          height: 50,
          backgroundColor: "#146f79",
          borderRadius: 10,
          padding: 5,
          position: "relative",
          marginRight: 80,
          transform: [{ rotate: "180deg" }],
        }}
      >
        <Text
          style={{
            width: "100%",
            textAlign: "right",
            transform: [{ rotate: "90deg" }],
            color: "#fff",
          }}
        >
          {currentValue}
        </Text>
        <View
          style={{
            position: "absolute",
            left: -10,
            top: 25,
            width: 0,
            height: 0,
            backgroundColor: "transparent",
            borderStyle: "solid",
            borderRightWidth: 10,
            borderTopWidth: 10,
            borderRightColor: "transparent",
            borderTopColor: "#146f79",
            transform: [{ rotate: "90deg" }],
          }}
        />
        <View
          style={{
            position: "absolute",
            left: -10,
            top: 15,
            width: 0,
            height: 0,
            backgroundColor: "transparent",
            borderStyle: "solid",
            borderRightWidth: 10,
            borderTopWidth: 10,
            borderRightColor: "transparent",
            borderTopColor: "#146f79",
            transform: [{ rotate: "180deg" }],
          }}
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "center",
  },
  sliders: {
    margin: 20,
    width: 280,
  },
  text: {
    alignSelf: "center",
    paddingVertical: 20,
  },
  title: {
    fontSize: 30,
  },
  sliderOne: {
    flexDirection: "row",
    justifyContent: "space-around",
    marginBottom: 50,
  },
  image: {
    height: 40,
    width: 40,
  },
});

The code uses the custom marker that renders a "Floating" component above the marker to display the value. The floating component is made of three views, one bubble to display the value then two triangles to display the pointer.

Hope this helps or at least gives you a starting point.