电视设备构建
实现电视设备支持的目的是使现有的 React Native 应用可以在 Apple TV 和 Android TV 上运行,而应用的 JavaScript 代码只需很少或无需更改。
¥TV devices support has been implemented with the intention of making existing React Native applications work on Apple TV and Android TV, with few or no changes needed in the JavaScript code for the applications.
- Android TV
- 🚧 tvOS
已弃用。电视支持已移至 React Native for TV 存储库。
¥Deprecated. TV support has moved to the React Native for TV repository.
构建变更
¥Build changes
-
原生层:要在 Android TV 上运行 React Native 项目,请确保对
AndroidManifest.xml
进行以下更改¥Native layer: To run React Native project on Android TV make sure to make the following changes to
AndroidManifest.xml
<!-- Add custom banner image to display as Android TV launcher icon -->
<application
...
android:banner="@drawable/tv_banner"
>
...
<intent-filter>
...
<!-- Needed to properly create a launch intent when running on Android TV -->
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
...
</application>
-
JavaScript 层:
Platform.android.js
中添加了对 Android TV 的支持。你可以通过执行以下操作来检查代码是否在 Android TV 上运行¥JavaScript layer: Support for Android TV has been added to
Platform.android.js
. You can check whether code is running on Android TV by doing
const Platform = require('Platform');
const running_on_android_tv = Platform.isTV;
代码变更
¥Code changes
-
访问可触摸控件:在 Android TV 上运行时,Android 框架将根据视图中可聚焦元素的相对位置自动应用定向导航方案。
Touchable
mixin 添加了代码来检测焦点变化,并使用现有方法正确设置组件样式,并在使用电视遥控器选择视图时启动适当的操作,因此TouchableWithoutFeedback
、TouchableHighlight
、TouchableOpacity
和TouchableNativeFeedback
将按预期工作。尤其:¥Access to touchable controls: When running on Android TV the Android framework will automatically apply a directional navigation scheme based on relative position of focusable elements in your views. The
Touchable
mixin has code added to detect focus changes and use existing methods to style the components properly and initiate the proper actions when the view is selected using the TV remote, soTouchableWithoutFeedback
,TouchableHighlight
,TouchableOpacity
andTouchableNativeFeedback
will work as expected. In particular:-
当可触摸视图进入焦点时将执行
onFocus
¥
onFocus
will be executed when the touchable view goes into focus -
当可触摸视图失去焦点时将执行
onBlur
¥
onBlur
will be executed when the touchable view goes out of focus -
当按下电视遥控器上的 "select" 按钮实际选择可触摸视图时,将执行
onPress
。¥
onPress
will be executed when the touchable view is actually selected by pressing the "select" button on the TV remote.
-
-
电视遥控器/键盘输入:新的原生类
ReactAndroidTVRootViewHelper
为电视远程事件设置关键事件处理程序。当电视远程事件发生时,此类会触发 JS 事件。该事件将被TVEventHandler
JavaScript 对象的实例拾取。需要实现电视远程事件自定义处理的应用代码可以创建TVEventHandler
的实例并监听这些事件,如以下代码所示:¥TV remote/keyboard input: A new native class,
ReactAndroidTVRootViewHelper
, sets up key events handlers for TV remote events. When TV remote events occur, this class fires a JS event. This event will be picked up by instances of theTVEventHandler
JavaScript object. Application code that needs to implement custom handling of TV remote events can create an instance ofTVEventHandler
and listen for these events, as in the following code:
const TVEventHandler = require('TVEventHandler');
class Game2048 extends React.Component {
_tvEventHandler: any;
_enableTVEventHandler() {
this._tvEventHandler = new TVEventHandler();
this._tvEventHandler.enable(this, function (cmp, evt) {
if (evt && evt.eventType === 'right') {
cmp.setState({board: cmp.state.board.move(2)});
} else if (evt && evt.eventType === 'up') {
cmp.setState({board: cmp.state.board.move(1)});
} else if (evt && evt.eventType === 'left') {
cmp.setState({board: cmp.state.board.move(0)});
} else if (evt && evt.eventType === 'down') {
cmp.setState({board: cmp.state.board.move(3)});
} else if (evt && evt.eventType === 'playPause') {
cmp.restartGame();
}
});
}
_disableTVEventHandler() {
if (this._tvEventHandler) {
this._tvEventHandler.disable();
delete this._tvEventHandler;
}
}
componentDidMount() {
this._enableTVEventHandler();
}
componentWillUnmount() {
this._disableTVEventHandler();
}
}
-
开发菜单支持:在模拟器上,cmd-M 将调出开发菜单,类似于 Android。要在真正的 Android TV 设备上启动它,请按菜单按钮或长按遥控器上的快进按钮。(请不要摇晃 Android TV 设备,否则将无法工作:))
¥Dev Menu support: On the emulator, cmd-M will bring up the Dev Menu, similar to Android. To bring it up on a real Android TV device, press the menu button or long press the fast-forward button on the remote. (Please do not shake the Android TV device, that will not work :) )
-
已知的问题:
¥Known issues:
-
TextInput
组件目前无法工作(即它们无法自动接收焦点,请参阅 这条评论)。¥
TextInput
components do not work for now (i.e. they cannot receive focus automatically, see this comment).-
然而,可以使用参考来手动触发
inputRef.current.focus()
。¥It is however possible to use a ref to manually trigger
inputRef.current.focus()
. -
你可以将输入封装在
TouchableWithoutFeedback
组件内,并在该可触摸组件的onFocus
事件中触发焦点。这使得可以通过箭头键打开键盘。¥You can wrap your input inside a
TouchableWithoutFeedback
component and trigger focus in theonFocus
event of that touchable. This enables opening the keyboard via the arrow keys. -
每次按键后键盘可能会重置其状态(这可能仅发生在 Android TV 模拟器内)。
¥The keyboard might reset its state after each keypress (this might only happen inside the Android TV emulator).
-
-
Modal
组件内容无法获得焦点,具体参见 这个问题。¥The content of
Modal
components cannot receive focus, see this issue for details.
-
已弃用。电视支持已移至 React Native for TV 存储库。
¥Deprecated. TV support has moved to the React Native for TV repository.
构建变更
¥Build changes
-
原生层:React Native Xcode 项目现在都有 Apple TV 构建目标,名称以字符串 '-tvOS' 结尾。
¥Native layer: React Native Xcode projects all now have Apple TV build targets, with names ending in the string '-tvOS'.
-
react-native init:使用
react-native init
创建的新 React Native 项目将在其 XCode 项目中自动创建 Apple TV 目标。¥react-native init: New React Native projects created with
react-native init
will have Apple TV target automatically created in their XCode projects. -
JavaScript 层:
Platform.ios.js
中添加了对 Apple TV 的支持。你可以通过执行以下操作来检查代码是否在 AppleTV 上运行¥JavaScript layer: Support for Apple TV has been added to
Platform.ios.js
. You can check whether code is running on AppleTV by doing
const Platform = require('Platform');
const running_on_tv = Platform.isTV;
// If you want to be more specific and only detect devices running tvOS
// (but no Android TV devices) you can use:
const running_on_apple_tv = Platform.isTVOS;
代码变更
¥Code changes
-
对 tvOS 的一般支持:原生代码中 Apple TV 特定的更改均由 TARGET_OS_TV 定义封装。其中包括抑制 tvOS 不支持的 API(例如网页视图、滑块、开关、状态栏等)的更改,以及支持用户通过电视遥控器或键盘输入的更改。
¥General support for tvOS: Apple TV specific changes in native code are all wrapped by the TARGET_OS_TV define. These include changes to suppress APIs that are not supported on tvOS (e.g. web views, sliders, switches, status bar, etc.), and changes to support user input from the TV remote or keyboard.
-
通用代码库:由于 tvOS 和 iOS 共享大多数 Objective-C 和 JavaScript 代码,因此大多数 iOS 文档同样适用于 tvOS。
¥Common codebase: Since tvOS and iOS share most Objective-C and JavaScript code in common, most documentation for iOS applies equally to tvOS.
-
访问可触摸控件:在 Apple TV 上运行时,原生视图类是
RCTTVView
,它具有使用 tvOS 焦点引擎的附加方法。Touchable
mixin 添加了代码来检测焦点变化,并使用现有方法正确设置组件样式,并在使用电视遥控器选择视图时启动正确的操作,因此TouchableWithoutFeedback
、TouchableHighlight
和TouchableOpacity
将按预期工作。尤其:¥Access to touchable controls: When running on Apple TV, the native view class is
RCTTVView
, which has additional methods to make use of the tvOS focus engine. TheTouchable
mixin has code added to detect focus changes and use existing methods to style the components properly and initiate the proper actions when the view is selected using the TV remote, soTouchableWithoutFeedback
,TouchableHighlight
andTouchableOpacity
will work as expected. In particular:-
当可触摸视图进入焦点时将执行
onFocus
¥
onFocus
will be executed when the touchable view goes into focus -
当可触摸视图失去焦点时将执行
onBlur
¥
onBlur
will be executed when the touchable view goes out of focus -
当按下电视遥控器上的 "select" 按钮实际选择可触摸视图时,将执行
onPress
。¥
onPress
will be executed when the touchable view is actually selected by pressing the "select" button on the TV remote.
-
-
电视遥控器/键盘输入:新的原生类
RCTTVRemoteHandler
为电视远程事件设置手势识别器。当电视远程事件发生时,此类会触发由RCTTVNavigationEventEmitter
(RCTEventEmitter
的子类)拾取的通知,从而触发 JS 事件。该事件将被TVEventHandler
JavaScript 对象的实例拾取。需要实现电视远程事件自定义处理的应用代码可以创建TVEventHandler
的实例并监听这些事件,如以下代码所示:¥TV remote/keyboard input: A new native class,
RCTTVRemoteHandler
, sets up gesture recognizers for TV remote events. When TV remote events occur, this class fires notifications that are picked up byRCTTVNavigationEventEmitter
(a subclass ofRCTEventEmitter
), that fires a JS event. This event will be picked up by instances of theTVEventHandler
JavaScript object. Application code that needs to implement custom handling of TV remote events can create an instance ofTVEventHandler
and listen for these events, as in the following code:
const TVEventHandler = require('TVEventHandler');
class Game2048 extends React.Component {
_tvEventHandler: any;
_enableTVEventHandler() {
this._tvEventHandler = new TVEventHandler();
this._tvEventHandler.enable(this, function (cmp, evt) {
if (evt && evt.eventType === 'right') {
cmp.setState({board: cmp.state.board.move(2)});
} else if (evt && evt.eventType === 'up') {
cmp.setState({board: cmp.state.board.move(1)});
} else if (evt && evt.eventType === 'left') {
cmp.setState({board: cmp.state.board.move(0)});
} else if (evt && evt.eventType === 'down') {
cmp.setState({board: cmp.state.board.move(3)});
} else if (evt && evt.eventType === 'playPause') {
cmp.restartGame();
}
});
}
_disableTVEventHandler() {
if (this._tvEventHandler) {
this._tvEventHandler.disable();
delete this._tvEventHandler;
}
}
componentDidMount() {
this._enableTVEventHandler();
}
componentWillUnmount() {
this._disableTVEventHandler();
}
}
-
开发菜单支持:在模拟器上,cmd-D 将调出开发菜单,类似于 iOS。要在真正的 Apple TV 设备上启动它,请长按遥控器上的播放/暂停按钮。(请不要摇晃 Apple TV 设备,否则将无法工作:))
¥Dev Menu support: On the simulator, cmd-D will bring up the Dev Menu, similar to iOS. To bring it up on a real Apple TV device, make a long press on the play/pause button on the remote. (Please do not shake the Apple TV device, that will not work :) )
-
电视遥控动画:
RCTTVView
原生代码实现了 Apple 推荐的视差动画,以帮助在用户浏览视图时引导眼睛。可以使用新的可选视图属性禁用或调整动画。¥TV remote animations:
RCTTVView
native code implements Apple-recommended parallax animations to help guide the eye as the user navigates through views. The animations can be disabled or adjusted with new optional view properties. -
使用电视遥控器菜单按钮返回导航:
BackHandler
组件最初是为了支持 Android 后退按钮而编写的,现在还支持使用电视遥控器上的菜单按钮在 Apple TV 上进行后退导航。¥Back navigation with the TV remote menu button: The
BackHandler
component, originally written to support the Android back button, now also supports back navigation on the Apple TV using the menu button on the TV remote. -
TabBarIOS 行为:
TabBarIOS
组件封装了原生UITabBar
API,其在 Apple TV 上的工作方式有所不同。为了避免 tvOS 中标签栏重新渲染的抖动(参见 这个问题),所选标签栏项目只能在初始渲染时通过 JavaScript 设置,然后由用户通过原生代码进行控制。¥TabBarIOS behavior: The
TabBarIOS
component wraps the nativeUITabBar
API, which works differently on Apple TV. To avoid jittery re-rendering of the tab bar in tvOS (see this issue), the selected tab bar item can only be set from JavaScript on initial render, and is controlled after that by the user through native code. -
已知的问题:
¥Known issues:
-
列表视图滚动。可以通过在 ListView 和类似组件中将
removeClippedSubviews
设置为 false 来解决此问题。有关此问题的更多讨论,请参阅 这个 PR。¥ListView scrolling. The issue can be worked around by setting
removeClippedSubviews
to false in ListView and similar components. For more discussion of this issue, see this PR.
-