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

[Android] Text with dynamic width parent makes text stretch/compress

Open joarkosberg opened this issue 1 year ago • 6 comments

Description

So I have two skia text components beside each other horizontally and I want them to stay close. The text of the components are dynamic related to a graph. So I need the width of the text parent to change based on the text width.

This is a combination of reanimated parent view and skia text field. So might not be skia specific, but looks like it maybe. Or just me using this wrong 😊

Version

0.1.188

Steps to reproduce

Per now I do something like the provided example, an animated view from reanimated (3) outside, with a canvas + text from skia inside. The reanimated view uses an animated style, with changing width based on the text, which is a shared value.

This works nicely on iOS, the view resizes nicely and the text is shown as it should. 2023-05-10 13 27 06

But on Android the text get compressed/stretched a lot when changing values. The background resizes fine in as seen in the gif, but the text compresses/stretches 2023-05-10 13 26 42

Snack, code example, screenshot, or link to a repository

    text: SharedValue<string>;
    fontSize: number; 
    const lineHeight = fontSize * 1.4;
    const font = useFont(font, fontSize);

    const animatedStyle = useAnimatedStyle(() => {
        const newSize =
            (font?.getTextWidth(text.value) ?? 0) * offsetMultiplier;
        return {
            width: newSize,
            height: lineHeight,
        };
    });

    return (
        <Animated.View style={animatedStyle}>
            <Canvas
                style={{
                    flex: 1
               }}
            >
                <Text
                    text={text}
                    font={font}
                    y={fontSize}
                    x={0}
                />
            </Canvas>
        </Animated.View>
    );

joarkosberg avatar May 10 '23 12:05 joarkosberg

Note that putting both texts inside one canvas, with dynamic X position of the second text works for both iOS and Android. Which probably is the preferred way of doing this 😊

joarkosberg avatar May 11 '23 06:05 joarkosberg

Could you try to extend the example so that I can copy it into the example app and run it? Make sure there are now other external dependencies in use except for Skia and Reanimated.

chrfalch avatar May 11 '23 08:05 chrfalch

We would definitely need a small standalone reproducible example here.

wcandillon avatar May 18 '23 07:05 wcandillon

Sorry for being a bit slow on providing example, I created a example from the react native starter with only skia and reanimated added here: https://github.com/joarkosberg/SkiaTest .

Added just one text component width dynamic width, where iOS is fine and Android compresses/stretches. Might be a problem with my usage as well here, but in case it is a bug 😊

iOS test app: Simulator Screen Recording - iPhone 8 - 2023-05-19 at 09 46 26

Android test app:

device-2023-05-19-094649.webm

joarkosberg avatar May 19 '23 07:05 joarkosberg

Oups, that looks bad 😅 Thanks for taking the time to make a reproducible example. Small question: would the same bug happens too with a circle for instance? Or is it only with Text?

wcandillon avatar May 19 '23 08:05 wcandillon

Oups, that looks bad 😅 Thanks for taking the time to make a reproducible example. Small question: would the same bug happens too with a circle for instance? Or is it only with Text?

Tested with circle now, it is the same behaviour as Text. Tested also with having height and width dynamic (radius*4), which made the circle not compress/stretch on android, but it got displaced when changing size. Seems like both this displacement and the compress/stretch is based on some of the last components properties.

device-2023-05-19-1016227.webm

joarkosberg avatar May 19 '23 08:05 joarkosberg