as

Settings
Sign out
Notifications
Alexa
亚马逊应用商店
AWS
文档
Support
Contact Us
My Cases
新手入门
设计和开发
应用发布
参考
支持

TVFocusGuide

TVFocusGuide

TVFocusGuide可帮助您编写直观的电视应用。它支持autofocus,有助于找到/恢复焦点,并记住多次访问时的焦点。它还支持trappingfocus redirection,后者让您可以在应用中自定义焦点行为。

该组件确保即使可设定焦点控件与其他控件未直接对齐,也可以导航到这些控件。RNTester中提供了一个示例,该示例展示了使用该组件的两种不同方式。

属性 值​ 描述
destinations any[]? 要注册为FocusGuideView目的地的Component数组
autoFocus boolean? 如果为true,TVFocusGuide将自动为您管理焦点。它会在第一次访问时将焦点重定向到第一个可设定焦点的子项上。它还会记住最后一个聚焦的子项,并在随后的访问中将焦点重定向到该子项。在一起使用时,destinations属性会优先于此属性。
trapFocus* (Up、Down、Left、Right) 防止焦点在给定方向上从容器中逸出。  

以下动画显示了使用TVFocusGuideView时的导航控件。

有关上述焦点处理改进的更多信息,可以参阅这篇文章(仅提供英文版)。

示例

已复制到剪贴板。


import React from 'react';
import {
  Dimensions,
  View,
  StyleSheet,
  TouchableHighlight,
  Text
} from 'react-native';
import {
  TVFocusGuideView
} from '@amazon-devices/react-native-kepler';

const screenHeight = Dimensions.get('window').height;
const scale = screenHeight / 1080;
const width = 200 * scale;
const height = 120 * scale;
const theme = {
  LinkColor: '#0984ffff',
  LabelColor: '#ffffffff',
  TertiarySystemFillColor: '#3085C3',
  BackgroundColor: '#0c0700ff'
};
const Button = React.forwardRef((props: $FlowFixMeProps, ref) => {
  const [focused, setFocused] = React.useState(false);
  return (
    <TouchableHighlight
      onPress={() => {
        if (props.onPress) {
          props.onPress();
        }
        console.log(`${props.label} in press`);
      }}
      onFocus={() => {
        if (props.onFocus) {
          props.onFocus();
        }
        console.log(`${props.label} in focus`);
        setFocused(true);
      }}
      onBlur={() => {
        if (props.onBlur) {
          props.onBlur();
        }
        console.log(`${props.label} in blur`);
        setFocused(false);
      }}
      style={focused ? styles.buttonStyleFocused : styles.buttonStyle}
      ref={ref}>
      <Text style={[{ color: theme.LinkColor }, styles.buttonText]}>
        {props.label}
      </Text>
    </TouchableHighlight>
  );
});

const ThemedView = (props: $FlowFixMeProps) => {
  return (
    <View style={[styles.buttonStyle, props.style]}>
      <Text style={[{ color: theme.LabelColor }, styles.buttonText]}>
        {props.label}
      </Text>
    </View>
  );
};

const TVFocusGuideExample = () => {
  const [destination, setDestination] = React.useState(null);
  const [destinationText, setDestinationText] = React.useState('');
  const destinations = destination?.current ? [destination?.current] : [];

  const buttonTopRight = React.useRef(null);
  const buttonBottomLeft = React.useRef(null);

  const rightButtonInFocusViewContainer = React.useRef(null);
  const containerDestinations = rightButtonInFocusViewContainer?.current
    ? [rightButtonInFocusViewContainer?.current]
    : [];

  const _setDestination = (o: Object, text: string) => {
    setDestination(o);
    setDestinationText(text);
  };

  return (
    <View
      style={[styles.container, { backgroundColor: theme.BackgroundColor }]}>
      <View style={styles.rowContainer}>
        <Button onPress={() => {}} label="左上角" />
        <Button
          onPress={() => {}}
          onFocus={() => _setDestination(buttonBottomLeft, 'bottom left')}
          ref={buttonTopRight}
          label="右上角"
        />
        <ThemedView label={`焦点指南指向${destinationText}`} />
        {/* @ts-expect-error */}
        <TVFocusGuideView
          style={styles.containerFocusGuide}
          destinations={containerDestinations}>
          <Button onPress={() => {}} label="被包装按钮1" />
          <Button onPress={() => {}} label="被包装按钮2" />
          <Button
            ref={rightButtonInFocusViewContainer}
            onPress={() => {}}
            label="被包装按钮3"
          />
        </TVFocusGuideView>
      </View>
      <View style={styles.rowContainer}>
        <Button
          onPress={() => {}}
          onFocus={() => _setDestination(buttonTopRight, 'top right')}
          ref={buttonBottomLeft}
          label="左下角"
        />
        <TVFocusGuideView
          style={[
            { backgroundColor: theme.TertiarySystemFillColor },
            styles.focusGuide
          ]}
          destinations={destinations}>
          <Text style={[{ color: theme.LabelColor }, styles.buttonText]}>
            焦点指南
          </Text>
        </TVFocusGuideView>
        <ThemedView label="" />
        <ThemedView
          style={{
            width: width * 3
          }}
          label="如果从外部导航上方的蓝色 焦点指南容器始终
                  指向按钮3"
        />
      </View>
    </View>
  );
};

const marginSize = 20 * scale;
const styles = StyleSheet.create({
  container: {
    marginTop: -marginSize,
    height: screenHeight
  },
  rowContainer: {
    flexDirection: 'row',
    padding: 100 * scale
  },
  buttonText: {
    fontSize: 30 * scale
  },
  buttonStyle: {
    width,
    height,
    marginLeft: marginSize,
    marginRight: marginSize,
    marginTop: marginSize,
    marginBottom: marginSize
  },
  buttonStyleFocused: {
    opacity: 0.5,
    borderColor: 'white',
    borderWidth: 4,
    width,
    height,
    marginLeft: marginSize,
    marginRight: marginSize,
    marginTop: marginSize,
    marginBottom: marginSize
  },
  focusGuide: {
    width,
    height,
    marginLeft: marginSize,
    marginRight: marginSize,
    marginTop: marginSize,
    marginBottom: marginSize
  },
  containerFocusGuide: {
    backgroundColor: 'transparent',
    borderColor: 'blue',
    borderWidth: 2,
    flexDirection: 'row'
  }
});

export default TVFocusGuideExample;



参考

属性

autoFocus

如果为true,TVFocusGuide将自动为您管理焦点。它会在第一次访问时将焦点重定向到第一个可设定焦点的子项上。它还会记住最后一个聚焦的子项,并在随后的访问中将焦点重定向到该子项。在使用时,destinations属性会优先于此属性。

类型 必填
布尔值

trapFocus* (Up、Down、Left、Right)

防止焦点在给定方向上从容器中逸出。

类型 必填
布尔值

destinations

要注册为FocusGuideView目的地的Component数组。

类型 必填
引用项的数组

方法

setDestinations

已复制到剪贴板。


setDestinations([ref1, ref2, ...]);

要注册为FocusGuideView目的地的Component数组。

类型 必填
引用项的数组

已知问题

  • 如果未挂载组件,setDestinations回调将无法更新。要么改用destinations属性,要么在调用setDestinations之前使用setTimeout添加延迟。
  • 使用严格的类型检查在.tsx中导入时,TVFocusGuide会失败并显示错误Property 'children' does not exist on type(属性“children”在类型上不存在)。应用可以在使用组件之前添加{/* @ts-expect-error */}{/* @ts-ignore */}以避免错误。

已复制到剪贴板。


const TVApp = () => {
  return (
    <View>
      {/* @ts-expect-error */}
      <TVFocusGuideView>
        <Text>Hello World</Text>
      </TVFocusGuideView>
    </View>
  );
};

其他资源

有关其他库的信息,请参阅支持的第三方库和服务


Last updated: 2025年9月30日