Kureev / react-native-blur

React Native Blur component
MIT License
3.74k stars 555 forks source link

Elements wrapped in BlurVIew don't positioning right [Android] #483

Open exoriri opened 1 year ago

exoriri commented 1 year ago

DESCRIPTION

I use your library and I like it. It works on iOS devices fine. But on Android, elements wrapped in <BlurView>{children}</BlurView run into each other. Sometimes when I change something in styles in dev mode, it works correctly, but when I build apk, bug appears again.

How can I fix it on Android? Thanks in advance. Code I use with BlurView attached below.

SCREENSHOT

photo_2022-07-29_01-09-21

PLATFORM

CODE

const BottomNavigationTabs: React.FC<BottomTabBarProps> = ({
  descriptors,
  state,
  navigation,
}) => {
  const focusedOptions = descriptors[state.routes[state.index].key].options;

  return (
    <>
        <BlurView blurType="light"
          blurAmount={15} style={{ height: 85, width: '100%', position: 'absolute', bottom: 0, }}>
        <View style={{ display: 'flex', flexDirection: 'row', position: 'absolute', bottom: 0, justifyContent: 'space-between' }}>
        {state.routes.map((route, index) => {
          const { options } = descriptors[route.key];
          const label =
            options.tabBarLabel !== undefined
              ? options.tabBarLabel
              : options.title !== undefined
              ? options.title
              : route.name;

          const isFocused = state.index === index;
          const focusedColor = isFocused ? colors.text1 : colorsOld.black;

          //Weird snippet, to render passed icon just call function with any return value, then just set color
          const icon =
            options.tabBarIcon &&
            React.cloneElement(
              //@ts-ignore
              options.tabBarIcon((props: any) => props),
              { color: focusedColor }
            );

          const onPress = () => {
            const event = navigation.emit({
              type: "tabPress",
              target: route.key,
              canPreventDefault: true,
            });

            if (!isFocused && !event.defaultPrevented) {
              navigation.navigate(route.name);
            }
          };

          const onLongPress = () => {
            navigation.emit({
              type: "tabLongPress",
              target: route.key,
            });
          };

          const tabBtn = (
            <TouchableOpacity
              accessibilityRole="button"
              accessibilityState={isFocused ? { selected: true } : {}}
              accessibilityLabel={options.tabBarAccessibilityLabel}
              testID={options.tabBarTestID}
              onPress={onPress}
              style={styles.tabButton}
              onLongPress={onLongPress}
              activeOpacity={0.7}
              key={route.key}
            >
              <View style={styles.tabItem}>
                <View style={styles.tabItemIcon}>{icon}</View>
                <Text style={{ ...styles.tabItemLabel, color: focusedColor }}>
                  {label}
                </Text>
              </View>
            </TouchableOpacity>
          );
          return tabBtn;
        })}
        </View>
        </BlurView>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    alignItems: "center",
    justifyContent: "center",
    paddingTop: 9,
    paddingBottom: 15,
  },
  tabButton: {
    paddingTop: 8,
    paddingBottom: 15,
    paddingHorizontal: 10,
    borderRadius: 10,
    zIndex: 10000
  },
  tabsContainer: {
    backgroundColor: colors.secondaryBg(0.5),
    width: "100%",
    left: 0,
    bottom: 0,
    zIndex: 999,
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-around",
  },
  tabItem: {
    justifyContent: "center",
    alignItems: "center",
  },
  tabItemIcon: {
    marginBottom: 6,
  },
  tabItemLabel: {
    fontSize: 12,
    fontFamily: "Inter-Medium",
  },
});
janglewood commented 1 year ago

I faced with same issue. Just use position: absolute for children element and don't put something inside .

exoriri commented 1 year ago

I faced with same issue. Just use position: absolute for children element and don't put something inside .

Thanks. Spent a lot of time figuring out how to make it works.

lpatrun commented 1 year ago

@exoriri you can try with this

` const [displayChildren, setDisplayChildren] = React.useState(false);

React.useEffect(() => {
    setTimeout(() => {
        setDisplayChildren(true);
    }, 0);
}, []);`

and use that var to display children. It will work as long as you don't open keyboard.

exoriri commented 1 year ago

@lpatrun thanks for the reply. I think this solution looks a bit better https://github.com/Kureev/react-native-blur/issues/483#issuecomment-1199210714

ospfranco commented 1 year ago

As another workaround:

{/* This looks stupid, but blur-view on android is broken
          Elements placed inside do not position correctly
          The work around is two overlays
      */}
      {store.ui.isLoading && (
        <BlurView
          blurType="dark"
          blurAmount={10}
          reducedTransparencyFallbackColor="black"
          style={tw`absolute inset-0`}
        />
      )}
      {store.ui.isLoading && (
        <View style={tw`absolute inset-0 items-center`}>
          <View className="flex-1" />
          <ActivityIndicator color="white" size="large" />
          <T style={tw`mt-6 text-white`}>{t`pleaseWait`}</T>
          <View className="flex-1" />
          <ABLLogoWhite className="h-12 w-12 mb-12" height={30} width={40} />
        </View>
      )}
AronBe commented 1 year ago

To fix this bug, for me worked to have some background color, e.g. backgroundColor: 'transparent' for the direct Blurview child so that items inside are positioned correctly.

<BlurView>
    <View style={{backgroundColor: 'transparent'}}>
       {children}
   </View>
</BlurView
Kingsmanam commented 10 months ago

To fix this bug, for me worked to have some background color, e.g. backgroundColor: 'transparent' for the direct Blurview child so that items inside are positioned correctly.

<BlurView>
    <View style={{backgroundColor: 'transparent'}}>
       {children}
   </View>
</BlurView

thanks man. works like a charm!