Skip to content
This repository has been archived by the owner on Jan 5, 2022. It is now read-only.

Use with a Webview #123

Open
Keplyx opened this issue Apr 12, 2020 · 5 comments
Open

Use with a Webview #123

Keplyx opened this issue Apr 12, 2020 · 5 comments
Labels

Comments

@Keplyx
Copy link

Keplyx commented Apr 12, 2020

Information

  • react-native version: 0.61.4
  • react-navigation version: ^5.0.9
  • react-navigation-collapsible version: ^5.4.0
  • Platform (iOS/Android): Android (Maybe iOS but couldn't test it)
  • react-native init or Expo: Expo 37

Detail

The library works fine with a FlatList, but I couldn't figure how to make it work with a WebView.
I tried to create an animated view and pass it props like we would do with a FlatList, but the header would not move.

const AnimatedWebView = Animated.createAnimatedComponent(WebView);

const WebViewScreen = ({ navigation }: ScreenProps) => {
  const {
    onScroll,
    containerPaddingTop,
    scrollIndicatorInsetTop,
  } = useCollapsibleStack();

  return (
    <AnimatedWebView
      ref={this.webviewRef}
      onScroll={onScroll}
      contentContainerStyle={{ paddingTop: containerPaddingTop }}
      scrollIndicatorInsets={{ top: scrollIndicatorInsetTop }}
      source={{ uri: 'https://docs.expo.io' }}
    />
  );
};

Am I doing something wrong or is Webview support not implemented?

Snack

You can try the current behavior in this snack (edited from the one in the Readme, web doesn't work for some reason)

Thank you for your time

@Keplyx Keplyx added the bug Something isn't working label Apr 12, 2020
@Keplyx
Copy link
Author

Keplyx commented Apr 13, 2020

Found a workaround, jittery when scrolling slowly but works.

Native driver does not work with the webview, so it must be disabled in the stack config

        {createCollapsibleStack(
          <Stack.Screen
            name="WithWebView"
            component={WebViewScreen}
            options={{
              headerStyle: {backgroundColor: 'green'},
              headerTintColor: 'white',
              title: 'Collapsible WebView',
            }}
          />, {useNativeDriver: false}
        )}

This will make the header collapse, but the webview will start under it. Setting the padding like in a FlatList will render it at the right place, but will have a blank space under the header when scrolling. Content insets only works in iOS, so my workaround is to set the marginTop to the header height, the marginBottom to the negative header height so the global webview size does not change. Then set the transform to follow translateY prop to move the webview while scrolling.

<AnimatedWebView
      onScroll={onScroll}
      style={{
        marginTop: containerPaddingTop,
        marginBottom: -containerPaddingTop,
        transform: [{ translateY: translateY }],
      }}
      source={{ uri: 'https://docs.expo.io' }}
    />

You can edit the previous snack to see the effect.

@benevbright
Copy link
Owner

benevbright commented Apr 13, 2020

@Keplyx Thanks a lot for your discovery.

One question. You don't see this bug on Android RN? facebook/react-native#21801
RN Android has this bug for a long time when you use translateY on ScrollView/FlatList. I'm curious if it occurs on Webview as well.

@Keplyx
Copy link
Author

Keplyx commented Apr 13, 2020

@benevbright Didn't know about this Android RN bug.

I edited your library to return the current header height:

const currentHeight = Animated.add(headerHeight, translateY);

and set this value as marginTop to try and not use translateY, but it didn't change much, still laggy.

@Keplyx
Copy link
Author

Keplyx commented Apr 13, 2020

Found a workaround that does not involve editing the library and does not have any stutter! The trick is not to change the website container style to match the header position, but to change the actual website styling.

I simply injected javascript in the webview to add a margin to the body, matching the header size. I also added a transition time to smooth out the experience because the javascript is loaded after page render.

The downsides (because sadly this is not a fix...) are that the page content will take time to get the right position and that it may break some websites.

    const customJS = "document.getElementsByTagName('body')[0].style.marginTop = '" + containerPaddingTop +"px';"
        + "document.getElementsByTagName('body')[0].style.transition = '50ms';true;";
    return (
        <AnimatedWebView
            onScroll={onScroll}
            injectedJavaScript={customJS}
            javaScriptEnabled={true}
            source={{uri: 'https://docs.expo.io/'}}
        />
    );

@benevbright
Copy link
Owner

@Keplyx
Cool...!
I liked to suggest such a thing like that but I wasn't sure how to code that.
Thanks again.

@benevbright benevbright added note and removed bug Something isn't working labels Oct 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants