Перейти к содержанию

measure

measure позволяет синхронно получать размеры и положение представления на экране в потоке UI thread.

Справочник

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { measure } from 'react-native-reanimated';

function App() {
    const animatedRef = useAnimatedRef();

    const handlePress = () => {
        runOnUI(() => {
            // highlight-next-line
            const measurement = measure(animatedRef);
            if (measurement === null) {
                return;
            }
            // ...
        })();
    };

    return <Animated.View ref={animatedRef} />;
}

Определения типов

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
interface MeasuredDimensions {
    x: number;
    y: number;
    width: number;
    height: number;
    pageX: number;
    pageY: number;
}

function measure<T extends Component>(
    animatedRef: AnimatedRef<T>
): MeasuredDimensions | null;

Аргументы

animatedRef

animated ref, связанный с компонентом, от которого вы хотите получить измерения. Анимированная ссылка должна быть передана либо Анимированному компоненту, либо встроенному компоненту React Native.

Возвращает

measure возвращает объект, содержащий такие поля:

  • x число, представляющее координату X относительно родительского компонента,
  • y число, представляющее координату Y относительно родительского компонента,
  • width - число, представляющее ширину компонента,
  • height - число, обозначающее высоту компонента,
  • pageX - число, обозначающее координату X относительно экрана,
  • pageY - число, представляющее координату Y относительно экрана,

или возвращает null, если измерение выполнить не удалось.

Пример

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import React from 'react';
import {
    Button,
    StyleSheet,
    View,
    Text,
} from 'react-native';
import Animated, {
    measure,
    runOnJS,
    useAnimatedRef,
    useSharedValue,
    withTiming,
} from 'react-native-reanimated';

export default function App() {
    const animatedRef = useAnimatedRef();
    const width = useSharedValue(100);
    const [text, setText] = React.useState(width.value);

    const handlePress = () => {
        width.value = withTiming(
            width.value + 50,
            {},
            () => {
                // highlight-next-line
                const measurement = measure(animatedRef);
                if (measurement === null) {
                    return;
                }

                runOnJS(setText)(
                    Math.floor(measurement.width)
                );
            }
        );
    };

    return (
        <View style={styles.container}>
            <Animated.View
                ref={animatedRef}
                style={{ ...styles.box, width }}
            />
            <Text style={styles.label}>width: {text}</Text>
            <Button
                onPress={handlePress}
                title="Click me"
            />
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
    },
    box: {
        height: 100,
        backgroundColor: '#b58df1',
        borderRadius: 20,
    },
    label: {
        fontSize: 24,
        marginVertical: 16,
        color: '#b58df1',
    },
});

Замечания

  • measure реализована только в потоке UI thread. При использовании measure внутри обработчиков событий его необходимо обернуть функцией runOnUI.

  • Функция useAnimatedStyle сначала оценивается в JavaScript-потоке непосредственно перед присоединением представлений к нативной стороне. Поэтому для безопасного использования меры внутри useAnimatedStyle необходимо добавить в код условие, аналогичное приведенному ниже:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function App() {
        const animatedStyles = useAnimatedStyle(() => {
            // highlight-next-line
            if (_WORKLET) {
                // safely use measure
                const measurement = measure(animatedRef);
            }
        });
    }
    

    Последовательные запуски useAnimatedStyle выполняются в потоке UI.

  • Если вам нужны только размеры компонента и вы не будете использовать измерения во время анимации, вместо этого используйте свойство onLayout.

  • Иногда measure возвращает null (например, когда ref еще не присоединен к представлению). Для большей безопасности лучше добавить проверку null после измерения.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    const animatedRef = useAnimatedRef();
    
    const handlePress = () => {
        runOnUI(() => {
            const measurement = measure(animatedRef);
    
            // highlight-start
            if (measurement === null) {
                return;
            }
            // highlight-end
            // ...
        })();
    };
    
  • measure может использоваться только для рендерных компонентов. Например, попытка измерить внеэкранные элементы в FlatList вернет значение null.

  • Функция measure недоступна в удаленном JS-отладчике. Мы настоятельно рекомендуем использовать Chrome DevTools (также известный как chrome://inspect) для отладки приложений React Native.

Совместимость с платформами

Android iOS Web

Ссылки

Комментарии