2

我有以下代码来创建“动态”文本输入。标签放置在文本输入上方。当 textinput 获得焦点时,标签会移动到 textinput 上方,并且字体大小和颜色会发生变化。在 textinput 模糊时,标签会向后移动(如果 textinput 中没有输入)。

此代码包含react-native-reanimated代码,动画应该在 UI 线程而不是 JS 线程上工作。

当我在 IOS 模拟器(测试 iPhone 7 -> iPhone 11 Pro)上测试此代码并专注于文本输入以便动画运行时,JS 线程下降了大约 3-6 帧(54-57 fps),这没关系我猜测。在真实设备(iPhone 7)上,JS 线程丢帧大约 20-30 帧(有时甚至更多)。当我开始输入 textinput 时,我得到一个缓慢的回调(我在输入时检查 textinput 的输入)。在模拟器上,回调是立即的。在真实设备上,有时最多需要 2 秒才能检查输入。

import React, { useState, useEffect } from 'react';
import { View, TextInput } from 'react-native';
import Animated, { Easing, Extrapolate } from 'react-native-reanimated';
import { interpolateColor, useTimingTransition } from 'react-native-redash';
import Colors from '../../constants/Colors';

const { interpolate } = Animated;

const AuthenticationInput = React.forwardRef((props, ref) => {
  const {
    ref,
    label,
    onChangeText,
    secureTextEntry,
    returnKeyType,
    icon
  } = props;

  const [value, setValue] = useState('');

  const [trans, setTrans] = useState(0);

  const transition = useTimingTransition(trans, {
    duration: 250,
    easing: Easing.inOut(Easing.ease)
  });

  // move the label in the x direction
  const moveX = interpolate(transition, {
    inputRange: [0, 1],
    outputRange: [12.5, 0],
    extrapolate: Extrapolate.CLAMP
  });

  // move the label in the y direction
  const moveY = interpolate(transition, {
    inputRange: [0, 1],
    outputRange: [12.5, -20],
    extrapolate: Extrapolate.CLAMP
  });

  // change the font size of the label
  const fontSize = interpolate(transition, {
    inputRange: [0, 1],
    outputRange: [15, 12.5],
    extrapolate: Extrapolate.CLAMP
  });

  // change the color of the label
  const color = interpolateColor(transition, {
    inputRange: [0, 1],
    outputRange: ['#aaa', '#000']
  });

  // pass the input of the textinput to the
  // onChangeText function passed as a prop
  useEffect(() => {
    onChangeText(value)
  }, [value]);

  return (
    <View style={{
      marginHorizontal: 25,
      marginTop: 25,
      borderRadius: 5,
      backgroundColor: Colors.white
    }}
    >
      <Animated.View style={{
        position: 'absolute',
        transform: [{ translateX: moveX }, { translateY: moveY }]
      }}
      >
        <Animated.Text style={{
          fontSize,
          color
        }}
        >
          {label}
        </Animated.Text>
      </Animated.View>
      <View style={{ flexDirection: 'row', alignItems: 'center' }}>
        <TextInput
          ref={ref}
          autoCapitalize="none"
          autoCompleteType="off"
          autoCorrect={false}
          secureTextEntry={secureTextEntry}
          onChangeText={(v) => setValue(v)}
          style={{
            margin: 0,
            padding: 12.5,
            flex: 1,
            fontSize: 15
          }}
          hitSlop={{
            top: 10,
            right: 10,
            bottom: 10,
            left: 10
          }}
          onFocus={() => setTrans(1)}
          onBlur={() => {
            if (value.length === 0) {
              setTrans(0);
            }
          }}
          returnKeyType={returnKeyType}
       />
        <View style={{ padding: 12.5 }}>
          {icon}
        </View>
      </View>
    </View>
  );
});

export default AuthenticationInput;
4

0 回答 0