In this lesson, you will learn how to create a responsive split-pane interface where users can drag a central divider to resize two adjacent panels dynamically.
The Logic of Dynamic Splitting
When building a resizable panel, we think of the layout as a parent container holding two children. Instead of using hard-coded flex values, we use a sharedValue (typically from react-native-reanimated) to represent the width or height of the first panel.
The divider acts as our "handle." We attach a GestureDetector to this handle, capturing the user's touch movement. As the user drags, we update the sharedValue, which triggers a re-render of our layout dimensions. Because we are optimizing for performance, we apply these changes directly to the style object of our components to ensure fluid movement.
Implementation Example
Imagine a horizontal split-pane where the first panel’s width is controlled by panelWidth:
const panelWidth = useSharedValue(200);
const gesture = Gesture.Pan()
.onUpdate((event) => {
// Constrain the resize to the screen bounds
panelWidth.value = Math.max(50, Math.min(event.absoluteX, 300));
});
return (
<View style={styles.container}>
<Animated.View style={{ width: panelWidth }} />
<GestureDetector gesture={gesture}>
<View style={styles.divider} />
</GestureDetector>
<View style={styles.rightPanel} />
</View>
);
Critical Layout Considerations
When the user drags the divider, the layout engine has to recalculate the positions of all siblings. To keep this performant:
- Avoid State for Geometry: Do not use
useStateto track the exact pixel movement during a drag. Updating React state causes re-renders that can cause jank. UseuseSharedValueto drive the layout update at the UI thread level. - Constrain Inputs: Always clamp your gesture values. If a user drags the divider completely off-screen, your layout may break or hide components entirely.
- Handle Threading: Since this is a layout-intensive task, ensure that your styling updates respect the "Native Driver" concepts we’ve previously discussed, allowing the UI thread to handle the transformation without blocking the JavaScript thread.
Key Takeaway: Use shared values to drive width or height properties directly in response to Pan gestures, ensuring the layout remains reactive without the overhead of standard React state updates.