有条件的动画组件是 janky
Conditionally animated component is janky
我正在尝试为我的应用程序创建一个 InputAccessoryView。它有一个 TextInput 和一个 Pressable 按钮。
我想做的是,当 TextInput 为空值时隐藏按钮,否则使用反应本机动画显示按钮。
我想出了按预期工作的工作组件。对于我使用的动画 useNativeDriver: true
.
但是,有一个问题:
- 当文本为空并且我输入一个词然后暂停时,显示的动画就会流畅地播放。 (如下图)
- 但是当文本为空并且我正在 连续输入 时,显示的动画会以一种卡顿的方式播放。 (如下图)
这是代码,还有 link 到 expo snack:
export default function App() {
const [text, setText] = React.useState('');
const translateY = React.useRef(new Animated.Value(0)).current;
React.useEffect(() => {
if (text.length > 0) {
// animate the add button to show by coming up
_animateShowAddButton();
} else {
// animate the add button to hide by going down
_animateHideAddButton();
}
// return null
}, [text]);
const _animateShowAddButton = () => {
Animated.timing(translateY, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start();
};
const _animateHideAddButton = () => {
Animated.timing(translateY, {
toValue: 100,
duration: 300,
useNativeDriver: true,
}).start();
};
const onPressFunction = () => {
console.log('onPressFunction');
};
return (
<View style={styles.container}>
<Text style={styles.paragraph}>Some text view</Text>
<View style={styles.myInputAccessory}>
<TextInput
placeholder="Enter text"
style={styles.textInputStyle}
onChangeText={(text) => setText(text)}
/>
<Animated.View
style={[
{
transform: [
{
translateY: translateY,
},
],
},
]}>
<Pressable style={styles.buttonStyle} onPress={onPressFunction}>
<Ionicons name="send" size={24} color="white" />
</Pressable>
</Animated.View>
</View>
</View>
);
}
每当文本更改时,动画似乎暂停(并再次播放)。你能帮我当文本不为空时如何使按钮动画流畅显示吗?
问题在于,由于第二个参数 [text]
,useEffect
会在每次文本更改时触发。因此,动画会在每次文本更改时开始。
您可以通过使用一些状态“锁定”动画来防止这种情况。以下是您的组件的相关更改:
function App() {
const [isAnimating, setIsAnimating] = useState(false);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
// only start a new animation if we're not currently animating
if (!isAnimating) {
// only animate show if currently invisible
if (!isVisible && text.length > 0) {
_animateShowAddButton();
// only animate hide if currently visible
} else if (isVisible && text.length === 0) {
_animateHideAddButton();
}
}
// check if we need to animate whenever text changes
// also check whenever animation finishes
}, [text, isAnimating]);
const _animateShowAddButton = () => {
// secure the lock so another animation can't start
setIsAnimating(true);
setIsVisible(true);
Animated.timing(translateY, {
toValue: 0,
duration: 300,
useNativeDriver: true,
// release the lock on completion
}).start(() => setIsAnimating(false));
};
const _animateHideAddButton = () => {
// secure the lock so another animation can't start
setIsAnimating(true);
setIsVisible(false);
Animated.timing(translateY, {
toValue: 100,
duration: 300,
useNativeDriver: true,
// release the lock on completion
}).start(() => setIsAnimating(false));
};
}
我正在尝试为我的应用程序创建一个 InputAccessoryView。它有一个 TextInput 和一个 Pressable 按钮。
我想做的是,当 TextInput 为空值时隐藏按钮,否则使用反应本机动画显示按钮。
我想出了按预期工作的工作组件。对于我使用的动画 useNativeDriver: true
.
但是,有一个问题:
- 当文本为空并且我输入一个词然后暂停时,显示的动画就会流畅地播放。 (如下图)
- 但是当文本为空并且我正在 连续输入 时,显示的动画会以一种卡顿的方式播放。 (如下图)
这是代码,还有 link 到 expo snack:
export default function App() {
const [text, setText] = React.useState('');
const translateY = React.useRef(new Animated.Value(0)).current;
React.useEffect(() => {
if (text.length > 0) {
// animate the add button to show by coming up
_animateShowAddButton();
} else {
// animate the add button to hide by going down
_animateHideAddButton();
}
// return null
}, [text]);
const _animateShowAddButton = () => {
Animated.timing(translateY, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start();
};
const _animateHideAddButton = () => {
Animated.timing(translateY, {
toValue: 100,
duration: 300,
useNativeDriver: true,
}).start();
};
const onPressFunction = () => {
console.log('onPressFunction');
};
return (
<View style={styles.container}>
<Text style={styles.paragraph}>Some text view</Text>
<View style={styles.myInputAccessory}>
<TextInput
placeholder="Enter text"
style={styles.textInputStyle}
onChangeText={(text) => setText(text)}
/>
<Animated.View
style={[
{
transform: [
{
translateY: translateY,
},
],
},
]}>
<Pressable style={styles.buttonStyle} onPress={onPressFunction}>
<Ionicons name="send" size={24} color="white" />
</Pressable>
</Animated.View>
</View>
</View>
);
}
每当文本更改时,动画似乎暂停(并再次播放)。你能帮我当文本不为空时如何使按钮动画流畅显示吗?
问题在于,由于第二个参数 [text]
,useEffect
会在每次文本更改时触发。因此,动画会在每次文本更改时开始。
您可以通过使用一些状态“锁定”动画来防止这种情况。以下是您的组件的相关更改:
function App() {
const [isAnimating, setIsAnimating] = useState(false);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
// only start a new animation if we're not currently animating
if (!isAnimating) {
// only animate show if currently invisible
if (!isVisible && text.length > 0) {
_animateShowAddButton();
// only animate hide if currently visible
} else if (isVisible && text.length === 0) {
_animateHideAddButton();
}
}
// check if we need to animate whenever text changes
// also check whenever animation finishes
}, [text, isAnimating]);
const _animateShowAddButton = () => {
// secure the lock so another animation can't start
setIsAnimating(true);
setIsVisible(true);
Animated.timing(translateY, {
toValue: 0,
duration: 300,
useNativeDriver: true,
// release the lock on completion
}).start(() => setIsAnimating(false));
};
const _animateHideAddButton = () => {
// secure the lock so another animation can't start
setIsAnimating(true);
setIsVisible(false);
Animated.timing(translateY, {
toValue: 100,
duration: 300,
useNativeDriver: true,
// release the lock on completion
}).start(() => setIsAnimating(false));
};
}