wix / react-native-navigation

A complete native navigation solution for React Native
https://wix.github.io/react-native-navigation/
MIT License
13.04k stars 2.67k forks source link

Top bar title component blinks when changing pages #3864

Closed reganperkins closed 5 years ago

reganperkins commented 6 years ago

Issue Description

When switching pages the topBar's title blinks if you are using a component instead of text. This happens even if it is a super simple component that only returns <Text>test title</Text>. Previously when using a custom component for the whole topBar it did not blink and appeared immediately between page renders

Steps to Reproduce / Code Snippets / Screenshots

Navigation.setStackRoot(this.props.componentId, {
    component: {
        name: 'teams',
        passProps: { teams: true },
        options: {
            topBar : {
                title: {
                    component: {
                        name: 'CustomTopBar',
                        alignment: 'fill'
                    },
                }
            },
        },
    }
});

export default class TopBarHeader extends BaseComponent {
    constructor() {
        super(...arguments);
    }
    static displayName = 'TopBar:Header';

    render() {
        return <Text>test</Text>
    }
}

Environment

smerat commented 6 years ago

same issue. any resolution?

manfromanotherland commented 6 years ago

Same issue here. Kind of got around the issue by setting dimensions to the component, so instead of flickering it fades when changes tabs. Still not great tho.

FeniXenAaaa commented 6 years ago

Mine is flickering showing three dots for a sec and jumping left/right sides. Take a look (screen captured from Genymotion but same issue on real device) screen-recording- 9-5-2018-3-21-17-pm The topBar is configured as following:

topBar: { drawBehind: false, animate: false, background: { color: '#d94515' }, title: { fontSize: 16, color: '#FFFFFF', fontFamily: 'Helvetica', alignment: 'center' } }

guyca commented 6 years ago

@FeniXenAaaa Can you please update the latest version any see if you still see the three dots issue?

I tested with the following component and didn't see three dots

const React = require('react');
const {
  Text
} = require('react-native');

class SimpleTopBarHeader extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
        <Text>test123</Text>
    );
  }
}

Regarding the "blink" issue - I think it's because it takes time for a react component to render... need to think how this can be addressed atm.

FeniXenAaaa commented 6 years ago

@guyca updated to 2.0.2556. Still got both issues but kinda less visible. But now I'm starting to get weird error. Take a look: screen-recording- 9-19-2018-5-11-32-pm

image

guyca commented 6 years ago

@FeniXenAaaa Doesn't seem like this red screen is related to this issue. I still can't reproduce the ellipsis issue - maybe it's related to the component you're displaying. Can you share your component's code with us?

yusufyildirim commented 6 years ago

@guyca I'm not using any custom component, I'm just using bare title but this issue still exists for me

simonhintersonnleitner commented 6 years ago

@guyca I have the same issue on Android with the lastest version (2.0.2569)

topbar_flickers_bug_android

My topbar component looks like this.

import React from 'react';

import {
  CachedImage,
  ImageCacheProvider,
} from 'react-native-cached-image';

import {
  ImageBackground,
  StyleSheet,
  View,
  Dimensions,
} from 'react-native';

import images from '../../images';

const screenWidth = Dimensions.get('window').width;

export default () => {
  console.disableYellowBox = true;
  const Image = (
    <ImageCacheProvider>
      <CachedImage
        resizeMode="contain"
        source={images.logo_small}
        style={styles.logo}
        ttl={60 * 60 * 24 * 365}
      />
    </ImageCacheProvider>
  );

  return (
    <View style={styles.topBarContainer}>
      <ImageBackground
        source={images.top_bar_background}
        style={styles.imageBackgroundContainer}
        resizeMode="cover"
      >
        {Image}
      </ImageBackground>
    </View>
  );
};

const styles = StyleSheet.create({
  topBarContainer: {
    backgroundColor: '#d64e55',
    width: '110%',
    height: 60,
    left: -20,
    top: 0,
    shadowColor: 'rgba(0,0,0, .5)',
    shadowOffset: { height: 1, width: 2 },
    shadowOpacity: 1,
    shadowRadius: 2,
  },
  imageBackgroundContainer: {
    backgroundColor: '#d64e55',
    width: screenWidth,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    height: 60,
    position: 'absolute',
    zIndex: 0,
    marginLeft: 20,
  },
  logo: {
    marginTop: 5,
    width: 45,
    height: 45,
  },
});

Any ideas whats wrong?

guyca commented 6 years ago

@simonhintersonnleitner This is caused by a design short sight - options are applied when a view is attached to hierarchy and visible. In some cases this is too late, for example when a react view is displayed in the TopBar. React views take time to render, typically less then 100 ms.

I'll address this issue asap

bdrobinson commented 5 years ago

@guyca how's this looking? Is it a complex change? I'm also getting flickering with react components inside top bar buttons.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe the issue is still relevant, please test on the latest Detox and report back. Thank you for your contributions.

stale[bot] commented 5 years ago

The issue has been closed for inactivity.

FRizzonelli commented 5 years ago

@guyca This is moved to Done but the problem is still present. If you use a component it flickers because as you mention it takes time to render.

I don't see any commit on this or PR merged, why is this closed so?

tukantje commented 5 years ago

Bot has closed this for inactivity. It is still a glaring issue, and an important one at that.

LoganArnett commented 5 years ago

Still seeing the flicker on my top bar component, is there any more movement on this?

AbanoubNassem commented 5 years ago

this issue still exist in the latest version

FRizzonelli commented 5 years ago

@guyca @yogevbd @ItsNoHax Hello guys! This indeed shouldn't be closed, as many of us are still in trouble with the issue. Can you guys give us some advice on how to start to fix this or any ETA? Thank you

FRizzonelli commented 5 years ago

@simonhintersonnleitner This is caused by a design short sight - options are applied when a view is attached to hierarchy and visible. In some cases this is too late, for example when a react view is displayed in the TopBar. React views take time to render, typically less then 100 ms.

I'll address this issue asap

Based on this I started looking in the source code. Basically the problem is related to the fact that on screen push, there is a call to clearOptions which is removing our custom component background from the topBar and then we are re-adding the view on the pushed screen. TopBar is shared among screens (btw I don't understand why, if you can give us some more info on why you make this choice would be great!). My current idea is to avoid to remove the custom component if starting screen and landing screen share the same custom component Id.

TopBar.java

public void clear() {
  if (component != null && !((TopBarBackgroundView) this.component).getComponentName().equals(((TopBarBackgroundView) root.getChildAt(0)).getComponentName())) {
      root.removeView(component);
      component = null;
  }

  titleBar.clear();
}
public void setBackgroundComponent(View component) {
  this.component = component;
  if (root.getChildAt(0) instanceof LinearLayout) {
       root.addView(component, 0);
   }
}

This implementation is terrible, but I've got a working result. With those lines of code, if you push a screen with the same custom background as the starting screen, you'll see no flicker. Do you guys have any better idea on how to proper implement this? Should we pass a prop from the options to enable this check? Any help is really appreciated!

FRizzonelli commented 5 years ago

Came up with this https://github.com/wix/react-native-navigation/pull/5110 after texting a bit with @guyca, this should fix the flicker of custom background of the topbar

1uss1 commented 5 years ago

I'm encountering this same 'blinking' issue on iOS with the latest version (2.20.2)

FRizzonelli commented 5 years ago

@julaak How's your setRoot?

1uss1 commented 5 years ago

@FRizzonelli setRoot looks roughly like this

Navigation.setRoot({
    root: {
      sideMenu: {
        right: {
          component: {
            name: 'SideMenu'
          },
        },
        center: {
          bottomTabs: {
            children: [
              {
                stack: {
                  children: [
                    {
                      component: {
                        name: 'SomeScreen',
                        options: {
                          bottomTab: {
                            text: 'Home',
                            icon: require('./images/bottomTabs/icon.png')
                          }
                        }
                      }
                    }
                  ]
                }
              },
              ....more children...
            ]
          }
        }
      }
    }
  });

Inside the screens we're using the Navigation.push() API to move to another screen.

Navigation.push(this.props.componentId, {
      component: {
        name: "OtherScreen"
      }
});

Inside the screens we use Navigation.mergeOptions() API to change the topBar title component, which is when the blinking happens.

    Navigation.mergeOptions(this.props.componentId, {
      topBar: {
        visible: true,
        title: {
          component: {
            name: 'ComponentName',
            alignment: 'center',
            passProps: {
              title: 'Top Bar Component Title',
              onPress: () => this.onTopBarPressed(),
              otherData: otherData
            }
          }
        }
      }
    });

Every time we use the Navigation.mergeOptions() API, the top bar contents (title component) blinks, even though only the passProps change. I guess the optimal behaviour would be to re-use the existing component in this case. However I'm not familiar how the underlying code works and if that is feasible.

ferrydarma commented 5 years ago

This workaround works like magic. Give it a try guys: https://medium.com/@linasmnew/react-native-navigation-wix-fix-top-left-corner-flickering-bcf5f9aa57cd

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe the issue is still relevant, please test on the latest Detox and report back. Thank you for your contributions.

stale[bot] commented 5 years ago

The issue has been closed for inactivity.

nihp commented 5 years ago

I am facing this issue. My header section is flickering any solution for this?

drixbarsali commented 4 years ago

No deal for me, still blinking on android using 6.5.0

guyca commented 4 years ago

@drixbarsali Have you tried assigning the same id to the background component?

topBar: {
  background: {
    component: {
      name: 'SomeComp',
      id: 'bgCompId'
    }
  }
}

If it doesn't work, please test it on both platforms are report back. Thanks!

drixbarsali commented 4 years ago

I have tested real quick and seems it works on both platforms, is a little jumpy, but i think the problem is with my style... gonna do more teste, but thanks :)

drixbarsali commented 4 years ago

@guyca did not work... let me explain it better, what is happening is this.. I have component setted as title, everytime on android that i push a screen it blinks... did not happens on IOS

Screenrecorder-2020-05-26-12-03-18-401

topBar: { visible: mergedOptions.topBarVisible, title: { component: { id:"customHeaderNew", name: 'CustomHeader', passProps: { route: { params: mergedOptions.routeProps }, alignment: 'center', waitForRender: false, }, }, }, background: { color: mergedOptions.topBarBackground, }, backButton: { visible: false, }, },

GrEg00z commented 3 years ago

This issue still exists on RN 0.63.4 & react-native-navigation 7.8.1, while setting tabsAttachMode to onSwitchToTab. With the default value (together), the topbar blinks only when setRoute is called.

Since there is not actual solution to use tabs navigation with onSwitchToTab mode and get the top bar blinks, the last (extrem) solution for me was to switch on react-navigation, from there you can use tabs navigation with lazy loading (corresponding to onSwitchToTab), and without top bar blinks.

Desintegrator commented 1 year ago

same with 7.30.3 (Top bar buttons components blinks)

pep108 commented 1 year ago

Came up with this #5110 after texting a bit with @guyca, this should fix the flicker of custom background of the topbar

I am still getting the flicker with a custom topbar background using tabs on iOS with version 7.33.0

williamgurzoni commented 1 year ago

Do we have any solutions for this? I'm having this issue when trying to use the topBar background component as the title on Android get those horizontal margins.