From 7a8e2066ec83be5db3ab240d32dcded673feff4c Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Sat, 7 Nov 2015 18:37:47 +0100 Subject: [PATCH 1/3] [ViewPager] Add setPageWithoutAnimation and make it imperative like ScrollView --- .../ViewPager/ViewPagerAndroid.android.js | 28 ++++++---- .../react/views/viewpager/ReactViewPager.java | 12 ++-- .../ReactViewPagerCommandHelper.java | 56 +++++++++++++++++++ .../viewpager/ReactViewPagerManager.java | 41 +++++++++++--- 4 files changed, 112 insertions(+), 25 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPagerCommandHelper.java diff --git a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js index 45b109134f2044..4e213a3b06964c 100644 --- a/Libraries/Components/ViewPager/ViewPagerAndroid.android.js +++ b/Libraries/Components/ViewPager/ViewPagerAndroid.android.js @@ -5,21 +5,20 @@ */ 'use strict'; +var NativeModules = require('NativeModules'); var NativeMethodsMixin = require('NativeMethodsMixin'); var React = require('React'); var ReactElement = require('ReactElement'); var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); var ReactPropTypes = require('ReactPropTypes'); +var RCTUIManager = NativeModules.UIManager; + var createReactNativeComponentClass = require('createReactNativeComponentClass'); var dismissKeyboard = require('dismissKeyboard'); var VIEWPAGER_REF = 'viewPager'; -var ViewPagerValidAttributes = { - selectedPage: true, -}; - /** * Container that allows to flip left and right between child views. Each * child view of the `ViewPagerAndroid` will be treated as a separate page @@ -152,16 +151,24 @@ var ViewPagerAndroid = React.createClass({ } }, setPage: function(selectedPage) { - this.setState({ - selectedPage, - }); + RCTUIManager.dispatchViewManagerCommand( + React.findNodeHandle(this), + RCTUIManager.AndroidViewPager.Commands.setPage, + [selectedPage], + ); + }, + setPageWithoutAnimation: function(selectedPage) { + RCTUIManager.dispatchViewManagerCommand( + React.findNodeHandle(this), + RCTUIManager.AndroidViewPager.Commands.setPageWithoutAnimation, + [selectedPage], + ); }, render: function() { return ( { + void setPage(T viewPager, int page); + void setPageWithoutAnimation(T viewPager, int page); + } + + public static Map getCommandsMap() { + return MapBuilder.of( + "setPage", + COMMAND_SET_PAGE, + "setPageWithoutAnimation", + COMMAND_SET_PAGE_WITHOUT_ANIMATION); + } + + public static void receiveCommand( + PagerCommandHandler viewManager, + T viewPager, + int commandType, + @Nullable ReadableArray args) { + Assertions.assertNotNull(viewManager); + Assertions.assertNotNull(viewPager); + Assertions.assertNotNull(args); + switch (commandType) { + case COMMAND_SET_PAGE: { + viewManager.setPage(viewPager, args.getInt(0)); + return; + } + case COMMAND_SET_PAGE_WITHOUT_ANIMATION: { + viewManager.setPageWithoutAnimation(viewPager, args.getInt(0)); + return; + } + default: + throw new IllegalArgumentException(String.format( + "Unsupported command %d received by %s.", + commandType, + viewManager.getClass().getSimpleName())); + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPagerManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPagerManager.java index 0002a7876c1dac..ebbb6214d59d13 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPagerManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/viewpager/ReactViewPagerManager.java @@ -13,15 +13,20 @@ import android.view.View; +import com.facebook.react.bridge.ReadableArray; import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.ReactProp; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewGroupManager; +import javax.annotation.Nullable; + /** * Instance of {@link ViewManager} that provides native {@link ViewPager} view. */ -public class ReactViewPagerManager extends ViewGroupManager { +public class ReactViewPagerManager + extends ViewGroupManager + implements ReactViewPagerCommandHelper.PagerCommandHandler { private static final String REACT_CLASS = "AndroidViewPager"; @@ -35,17 +40,39 @@ protected ReactViewPager createViewInstance(ThemedReactContext reactContext) { return new ReactViewPager(reactContext); } - @ReactProp(name = "selectedPage") - public void setSelectedPage(ReactViewPager view, int page) { - // TODO(8496821): Handle selectedPage property cleanup correctly, now defaults to 0 - view.setCurrentItemFromJs(page); - } - @Override public boolean needsCustomLayoutForChildren() { return true; } + + @Override + public @Nullable Map getCommandsMap() { + return ReactViewPagerCommandHelper.getCommandsMap(); + } + + @Override + public void receiveCommand( + ReactViewPager viewPager, + int commandId, + @Nullable ReadableArray args) { + ReactViewPagerCommandHelper.receiveCommand(this, viewPager, commandId, args); + } + + @Override + public void setPage( + ReactViewPager viewPager, + int page) { + viewPager.setCurrentItemFromJs(page, true); + } + + @Override + public void setPageWithoutAnimation( + ReactViewPager viewPager, + int page) { + viewPager.setCurrentItemFromJs(page, false); + } + @Override public Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.of( From 455ed92463ddf635a0d74cc8229c9ee8c419fead Mon Sep 17 00:00:00 2001 From: Brent Vatne Date: Sun, 8 Nov 2015 13:09:58 +0100 Subject: [PATCH 2/3] [ViewPager] Make initialPage work again and update the example --- .../ViewPagerAndroidExample.android.js | 39 ++++++++++++++--- .../ViewPager/ViewPagerAndroid.android.js | 42 ++++++++++++------- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/Examples/UIExplorer/ViewPagerAndroidExample.android.js b/Examples/UIExplorer/ViewPagerAndroidExample.android.js index 8dcbbb06ec67bc..e4f33458e95b36 100644 --- a/Examples/UIExplorer/ViewPagerAndroidExample.android.js +++ b/Examples/UIExplorer/ViewPagerAndroidExample.android.js @@ -96,23 +96,39 @@ var ViewPagerAndroidExample = React.createClass({ description: 'Container that allows to flip left and right between child views.' }, getInitialState: function() { - return {page: 0, progress: {position: 0, offset: 0}}; + return { + page: 0, + animationsAreEnabled: true, + progress: { + position: 0, + offset: 0, + }, + }; }, + onPageSelected: function(e) { this.setState({page: e.nativeEvent.position}); }, + onPageScroll: function(e) { this.setState({progress: e.nativeEvent}); }, + move: function(delta) { var page = this.state.page + delta; - this.viewPager && this.viewPager.setPage(page); - this.setState({page}); + this.go(page); }, + go: function(page) { - this.viewPager && this.viewPager.setPage(page); + if (this.state.animationsAreEnabled) { + this.viewPager.setPage(page); + } else { + this.viewPager.setPageWithoutAnimation(page); + } + this.setState({page}); }, + render: function() { var pages = []; for (var i = 0; i < PAGES; i++) { @@ -131,7 +147,7 @@ var ViewPagerAndroidExample = React.createClass({ ); } - var page = this.state.page; + var { page, animationsAreEnabled } = this.state; return ( { this.viewPager = viewPager; }}> {pages} + + { animationsAreEnabled ? +