You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:05:16