React Native tvOS垂直滚动时如何实现聚焦项居中显示?
React Native FlatList 聚焦项自动居中及滚动异常修复
问题分析
当前FlatList仅能显示3个列表项,需求是项获得焦点时自动居中显示,但存在按两次方向键才能让非聚焦项滚动至聚焦状态的问题,此前尝试设置偏移量和改用ScrollView未解决。
解决方案
核心思路是主动监听项的聚焦事件,通过FlatList的scrollToIndex方法将聚焦项滚动到屏幕中心,同时维护选中状态的样式更新。以下是修改后的完整代码:
import React, { useState, useRef } from 'react'; import { FlatList, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; const data = Array.from({ length: 20 }, (_, index) => index + 1); // 每个item的固定高度(含上下margin),用于getItemLayout提升性能 const ITEM_HEIGHT = 150 + 16; // item高度150 + marginVertical各8 export default function App() { const [selectedIndex, setSelectedIndex] = useState(0); const flatListRef = useRef(null); const renderItem = ({ item, index }) => ( <TouchableOpacity style={[ styles.item, selectedIndex === index && styles.selectedItem ]} onFocus={() => { setSelectedIndex(index); // 滚动到当前聚焦项,viewPosition:0.5确保项居中显示 flatListRef.current?.scrollToIndex({ index, animated: true, viewPosition: 0.5, }); }} > <Text style={styles.text}>{item}</Text> </TouchableOpacity> ); // 预计算项位置,提升滚动性能 const getItemLayout = (data, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, }); return ( <View style={styles.container}> <FlatList ref={flatListRef} data={data} renderItem={renderItem} keyExtractor={(item) => item.toString()} getItemLayout={getItemLayout} keyboardShouldPersistTaps="handled" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, item: { marginVertical: 8, height: 150, width: 100, backgroundColor: '#f9c2ff', justifyContent: 'center', borderRadius: 5, }, selectedItem: { backgroundColor: '#ffb6c1', }, text: { fontSize: 18, textAlign: 'center', }, });
关键修改说明
- 聚焦触发滚动:给每个
TouchableOpacity绑定onFocus事件,焦点变化时立即调用scrollToIndex,通过viewPosition: 0.5强制聚焦项居中。 - 性能优化:用
getItemLayout预先计算项的位置和高度,避免FlatList动态测量,提升滚动流畅度。 - 状态联动样式:通过
selectedIndex切换项的背景色,直观区分聚焦状态。
问题根源
原代码未主动监听聚焦事件并触发滚动逻辑,默认焦点导航仅移动焦点但不会自动调整滚动位置到居中,导致需要两次按键:第一次移动焦点,第二次触发系统默认的滚动补全。主动调用scrollToIndex可在焦点变化时直接将项滚动到目标位置,解决两次按键的问题。
内容的提问来源于stack exchange,提问作者Shivam
相关产品推荐
相关产品推荐

