react-native-paper icon indicating copy to clipboard operation
react-native-paper copied to clipboard

iOS app open/close transition shows shadow on SegmentedButtons

Open astrojams1 opened this issue 9 months ago • 3 comments

Current behaviour

I am rendering a Segmented Button (basic, vanilla implementation) When I open or close the iOS app, I see a gradient within one of the segments.

Expected behaviour

No gradient.

How to reproduce?

Use iOS Add a segmented button to your view. Close or open the iOS app to show the gradient.

Preview

Implementation: <SegmentedButtons value={buttonValue} onValueChange={setButtonValue} buttons={[ { value: 'consumed', label: 'Consumed', showSelectedCheck: true }, { value: 'remaining', label: 'Remaining', showSelectedCheck: true }, ]} density="small" />

Screenshot: Image

What have you tried so far?

Explicitly setting a background color with style={[styles.group, { backgroundColor: theme.colors.background }]}

Your Environment

software version
ios 16.0
react-native 0.76.3
react-native-paper ^5.12.5

astrojams1 avatar Mar 20 '25 17:03 astrojams1

@astrojams1 Yes I am also facing same issue . SegmentedButtons may get re-evaluated when the app becomes active again, leading iOS to recreate the layers dynamically, sometimes causing unintended visual effects.

I believe that as a work around you can add activity indicator whenever the app comes from background to foreground.

Please find the code below :

import React, { useState, useEffect, useRef } from 'react'; import { AppState, View, ActivityIndicator } from 'react-native'; import { SegmentedButtons } from 'react-native-paper';

const MySegmentedControl = () => { const appState = useRef(AppState.currentState); const selectedValue = useRef('first'); // Avoid unnecessary re-renders const [isLoading, setIsLoading] = useState(false); // Controls Activity Indicator

useEffect(() => { const handleAppStateChange = (nextAppState) => { if (appState.current.match(/inactive|background/) && nextAppState === 'active') { // Show the loader and refresh SegmentedButtons setIsLoading(true); setTimeout(() => setIsLoading(false), 500); // Simulate a smooth refresh } appState.current = nextAppState; };

const subscription = AppState.addEventListener('change', handleAppStateChange);
return () => subscription.remove();

}, []);

return ( <View style={{ padding: 20, alignItems: 'center' }}> {isLoading ? ( <ActivityIndicator size="large" color="#6200EE" /> // React Native Paper theme color ) : ( <SegmentedButtons value={selectedValue.current} onValueChange={(val) => (selectedValue.current = val)} buttons={[ { value: 'first', label: 'First' }, { value: 'second', label: 'Second' }, { value: 'third', label: 'Third' }, ]} style={{ backgroundColor: 'white' }} // Ensures no transparency issues /> )} </View> ); };

export default MySegmentedControl;

kheravarun08 avatar Mar 22 '25 18:03 kheravarun08

I am seeing this with "^5.14.0", with the additions:

  • The drop shadow always shows on an iPhone 15 with iOS 18.4.1, whether animating or not
  • The drop shadow shows only while animating (like demonstrated by the OP) on an iPhone 16e with iOS 18.3.1
  • The drop shadow shows in the iOS Simulator on the iPhone 16 Plus (and I'm sure other devices) with iOS 18.1 if I double tap the home button (view the currently running app list) and it disappears after the app refocuses
  • The drop shadow shows in the iOS Simulator on the iPad (10th generation) with iOS 18.1 if I double tap the home button and it disappears after the app refocuses

I've updated to "^5.14.5" but haven't put out a TestFlight build. Based on the OP using the latest version, I don't think I'll see anything different.

ven-netk-zg avatar May 27 '25 14:05 ven-netk-zg

This behavior is weird

When went what wrong:

  1. On simulator/device it only occurs only when bringing the app from the background to the foreground
  2. On my phsyical iPad the shadow keeps visible when build for production
  3. Only the last button is affected (If there are three SegmentedButtons the shadow is only at the last one)
  4. Workaround set outline to any transparent color theme={{ colors: { outline: '#ffffff00' } }}

This seems to be an issue with expo/react-native -> https://github.com/facebook/react-native/issues/49442 I have created a minimal example: https://snack.expo.dev/@m.bahl/2e0d5d

MichelBahl avatar Jun 17 '25 12:06 MichelBahl