Apple TV: Enable long presses on TV remote; dev menu on TV device; example code
Summary: **Motivation** Properly support long presses on the Apple TV remote, and also enable dev menu functionality on a real Apple TV device (shaking an Apple TV doesn't work 😄 ) **Test plan** New example added to `RNTester`. Closes https://github.com/facebook/react-native/pull/15221 Differential Revision: D5526463 Pulled By: javache fbshipit-source-id: a61051e86bc82a9561eefc1704bed6b1f2617e05
This commit is contained in:
parent
e61257cd0a
commit
75284d3cd4
|
@ -336,6 +336,11 @@ const APIExamples: Array<RNTesterExample> = [
|
||||||
module: require('./TransformExample'),
|
module: require('./TransformExample'),
|
||||||
supportsTVOS: true,
|
supportsTVOS: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'TVEventHandlerExample',
|
||||||
|
module: require('./TVEventHandlerExample'),
|
||||||
|
supportsTVOS: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'VibrationExample',
|
key: 'VibrationExample',
|
||||||
module: require('./VibrationExample'),
|
module: require('./VibrationExample'),
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2017-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
* @providesModule TVEventHandlerExample
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var React = require('react');
|
||||||
|
var ReactNative = require('react-native');
|
||||||
|
|
||||||
|
var {
|
||||||
|
Platform,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
TVEventHandler,
|
||||||
|
} = ReactNative;
|
||||||
|
|
||||||
|
exports.framework = 'React';
|
||||||
|
exports.title = 'TVEventHandler example';
|
||||||
|
exports.description = 'iOS alerts and action sheets';
|
||||||
|
exports.examples = [{
|
||||||
|
title: 'TVEventHandler',
|
||||||
|
render() {return <TVEventHandlerView/>;}
|
||||||
|
}];
|
||||||
|
|
||||||
|
class TVEventHandlerView extends React.Component {
|
||||||
|
state: {
|
||||||
|
lastEventType: string
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
lastEventType: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_tvEventHandler: any;
|
||||||
|
|
||||||
|
_enableTVEventHandler() {
|
||||||
|
this._tvEventHandler = new TVEventHandler();
|
||||||
|
this._tvEventHandler.enable(this, function(cmp, evt) {
|
||||||
|
cmp.setState({
|
||||||
|
lastEventType: evt.eventType
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_disableTVEventHandler() {
|
||||||
|
if (this._tvEventHandler) {
|
||||||
|
this._tvEventHandler.disable();
|
||||||
|
delete this._tvEventHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._enableTVEventHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this._disableTVEventHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
if (Platform.isTVOS) {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<TouchableOpacity onPress={() => {}}>
|
||||||
|
<Text>
|
||||||
|
This example enables an instance of TVEventHandler to show the last event detected from the Apple TV Siri remote or from a keyboard.
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={{color: 'blue'}}>
|
||||||
|
{this.state.lastEventType}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Text>
|
||||||
|
This example is intended to be run on Apple TV.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,8 @@
|
||||||
#import "RCTView.h"
|
#import "RCTView.h"
|
||||||
#import "UIView+React.h"
|
#import "UIView+React.h"
|
||||||
|
|
||||||
|
#import "RCTDevMenu.h"
|
||||||
|
|
||||||
@implementation RCTTVRemoteHandler {
|
@implementation RCTTVRemoteHandler {
|
||||||
NSMutableArray<UIGestureRecognizer *> *_tvRemoteGestureRecognizers;
|
NSMutableArray<UIGestureRecognizer *> *_tvRemoteGestureRecognizers;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +62,15 @@
|
||||||
// Right
|
// Right
|
||||||
[self addTapGestureRecognizerWithSelector:@selector(swipedRight:)
|
[self addTapGestureRecognizerWithSelector:@selector(swipedRight:)
|
||||||
pressType:UIPressTypeRightArrow];
|
pressType:UIPressTypeRightArrow];
|
||||||
|
|
||||||
|
// Recognizers for long button presses
|
||||||
|
// We don't intercept long menu press -- that's used by the system to go to the home screen
|
||||||
|
|
||||||
|
[self addLongPressGestureRecognizerWithSelector:@selector(longPlayPausePressed:)
|
||||||
|
pressType:UIPressTypePlayPause];
|
||||||
|
|
||||||
|
[self addLongPressGestureRecognizerWithSelector:@selector(longSelectPressed:)
|
||||||
|
pressType:UIPressTypeSelect];
|
||||||
|
|
||||||
// Recognizers for Apple TV remote trackpad swipes
|
// Recognizers for Apple TV remote trackpad swipes
|
||||||
|
|
||||||
|
@ -100,9 +110,19 @@
|
||||||
[self sendAppleTVEvent:@"select" toView:r.view];
|
[self sendAppleTVEvent:@"select" toView:r.view];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)longPress:(UIGestureRecognizer *)r
|
- (void)longPlayPausePressed:(UIGestureRecognizer *)r
|
||||||
{
|
{
|
||||||
[self sendAppleTVEvent:@"longPress" toView:r.view];
|
[self sendAppleTVEvent:@"longPlayPause" toView:r.view];
|
||||||
|
|
||||||
|
// If shake to show is enabled on device, use long play/pause event to show dev menu
|
||||||
|
#if RCT_DEV
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTShowDevMenuNotification object:nil];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)longSelectPressed:(UIGestureRecognizer *)r
|
||||||
|
{
|
||||||
|
[self sendAppleTVEvent:@"longSelect" toView:r.view];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)swipedUp:(UIGestureRecognizer *)r
|
- (void)swipedUp:(UIGestureRecognizer *)r
|
||||||
|
@ -127,6 +147,14 @@
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
- (void)addLongPressGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType
|
||||||
|
{
|
||||||
|
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:selector];
|
||||||
|
recognizer.allowedPressTypes = @[@(pressType)];
|
||||||
|
|
||||||
|
[_tvRemoteGestureRecognizers addObject:recognizer];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType
|
- (void)addTapGestureRecognizerWithSelector:(nonnull SEL)selector pressType:(UIPressType)pressType
|
||||||
{
|
{
|
||||||
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:selector];
|
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:selector];
|
||||||
|
|
|
@ -12,6 +12,13 @@
|
||||||
#import <React/RCTBridge.h>
|
#import <React/RCTBridge.h>
|
||||||
#import <React/RCTBridgeModule.h>
|
#import <React/RCTBridgeModule.h>
|
||||||
|
|
||||||
|
#if RCT_DEV
|
||||||
|
|
||||||
|
RCT_EXTERN NSString *const RCTShowDevMenuNotification;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@class RCTDevMenuItem;
|
@class RCTDevMenuItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#if RCT_DEV
|
#if RCT_DEV
|
||||||
|
|
||||||
static NSString *const RCTShowDevMenuNotification = @"RCTShowDevMenuNotification";
|
NSString *const RCTShowDevMenuNotification = @"RCTShowDevMenuNotification";
|
||||||
|
|
||||||
@implementation UIWindow (RCTDevMenu)
|
@implementation UIWindow (RCTDevMenu)
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ class Game2048 extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
- *Dev Menu support*: On the simulator, cmd-D will bring up the developer menu, just like on 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 :) )
|
||||||
|
|
||||||
- *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.
|
- *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.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue