mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1fdd8914a | ||
|
|
75f4033ca0 | ||
|
|
7f42a44751 | ||
|
|
b570c23cfe |
@@ -57,6 +57,11 @@ exports.examples = [
|
||||
onPress={() => { _scrollView.scrollTo({y: 0}); }}>
|
||||
<Text>Scroll to top</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.button}
|
||||
onPress={() => { _scrollView.scrollToEnd({animated: true}); }}>
|
||||
<Text>Scroll to bottom</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -79,6 +84,11 @@ exports.examples = [
|
||||
onPress={() => { _scrollView.scrollTo({x: 0}); }}>
|
||||
<Text>Scroll to start</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.button}
|
||||
onPress={() => { _scrollView.scrollToEnd({animated: true}); }}>
|
||||
<Text>Scroll to end</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -377,11 +377,11 @@ var ScrollResponderMixin = {
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function to scroll to a specific point in the scrollview.
|
||||
* This is currently used to help focus on child textviews, but can also
|
||||
* A helper function to scroll to a specific point in the ScrollView.
|
||||
* This is currently used to help focus child TextViews, but can also
|
||||
* be used to quickly scroll to any element we want to focus. Syntax:
|
||||
*
|
||||
* scrollResponderScrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})
|
||||
* `scrollResponderScrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})`
|
||||
*
|
||||
* Note: The weird argument signature is due to the fact that, for historical reasons,
|
||||
* the function also accepts separate arguments as as alternative to the options object.
|
||||
@@ -404,6 +404,26 @@ var ScrollResponderMixin = {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Scrolls to the end of the ScrollView, either immediately or with a smooth
|
||||
* animation.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* `scrollResponderScrollToEnd({animated: true})`
|
||||
*/
|
||||
scrollResponderScrollToEnd: function(
|
||||
options?: { animated?: boolean },
|
||||
) {
|
||||
// Default to true
|
||||
const animated = (options && options.animated) !== false;
|
||||
UIManager.dispatchViewManagerCommand(
|
||||
this.scrollResponderGetScrollableNode(),
|
||||
UIManager.RCTScrollView.Commands.scrollToEnd,
|
||||
[animated],
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Deprecated, do not use.
|
||||
*/
|
||||
|
||||
@@ -382,11 +382,11 @@ const ScrollView = React.createClass({
|
||||
/**
|
||||
* Scrolls to a given x, y offset, either immediately or with a smooth animation.
|
||||
*
|
||||
* Syntax:
|
||||
* Example:
|
||||
*
|
||||
* `scrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})`
|
||||
* `scrollTo({x: 0; y: 0; animated: true})`
|
||||
*
|
||||
* Note: The weird argument signature is due to the fact that, for historical reasons,
|
||||
* Note: The weird function signature is due to the fact that, for historical reasons,
|
||||
* the function also accepts separate arguments as as alternative to the options object.
|
||||
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
|
||||
*/
|
||||
@@ -404,7 +404,25 @@ const ScrollView = React.createClass({
|
||||
},
|
||||
|
||||
/**
|
||||
* Deprecated, do not use.
|
||||
* If this is a vertical ScrollView scrolls to the bottom.
|
||||
* If this is a horizontal ScrollView scrolls to the right.
|
||||
*
|
||||
* Use `scrollToEnd({animated: true})` for smooth animated scrolling,
|
||||
* `scrollToEnd({animated: false})` for immediate scrolling.
|
||||
* If no options are passed, `animated` defaults to true.
|
||||
*/
|
||||
scrollToEnd: function(
|
||||
options?: { animated?: boolean },
|
||||
) {
|
||||
// Default to true
|
||||
const animated = (options && options.animated) !== false;
|
||||
this.getScrollResponder().scrollResponderScrollToEnd({
|
||||
animated: animated,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Deprecated, use `scrollTo` instead.
|
||||
*/
|
||||
scrollWithoutAnimationTo: function(y: number = 0, x: number = 0) {
|
||||
console.warn('`scrollWithoutAnimationTo` is deprecated. Use `scrollTo` instead');
|
||||
|
||||
@@ -287,6 +287,29 @@ var ListView = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* If this is a vertical ListView scrolls to the bottom.
|
||||
* If this is a horizontal ListView scrolls to the right.
|
||||
*
|
||||
* Use `scrollToEnd({animated: true})` for smooth animated scrolling,
|
||||
* `scrollToEnd({animated: false})` for immediate scrolling.
|
||||
* If no options are passed, `animated` defaults to true.
|
||||
*
|
||||
* See `ScrollView#scrollToEnd`.
|
||||
*/
|
||||
scrollToEnd: function(options?: { animated?: boolean }) {
|
||||
if (this._scrollComponent) {
|
||||
if (this._scrollComponent.scrollToEnd) {
|
||||
this._scrollComponent.scrollToEnd(options);
|
||||
} else {
|
||||
console.warn(
|
||||
'The scroll component used by the ListView does not support ' +
|
||||
'scrollToEnd. Check the renderScrollComponent prop of your ListView.'
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setNativeProps: function(props: Object) {
|
||||
if (this._scrollComponent) {
|
||||
this._scrollComponent.setNativeProps(props);
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React"
|
||||
s.version = package['version']
|
||||
s.version = "0.41.0-rc.1"
|
||||
s.summary = package['description']
|
||||
s.description = <<-DESC
|
||||
React Native apps are built using the React JS
|
||||
|
||||
@@ -480,10 +480,10 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
|
||||
expectedCount -= 2;
|
||||
}
|
||||
|
||||
RCTLogError(@"%@.%@ was called with %zd arguments, but expects %zd. \
|
||||
If you haven\'t changed this method yourself, this usually means that \
|
||||
your versions of the native code and JavaScript code are out of sync. \
|
||||
Updating both should make this error go away.",
|
||||
RCTLogError(@"%@.%@ was called with %zd arguments but expects %zd arguments. "
|
||||
@"If you haven\'t changed this method yourself, this usually means that "
|
||||
@"your versions of the native code and JavaScript code are out of sync. "
|
||||
@"Updating both should make this error go away.",
|
||||
RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName,
|
||||
actualCount, expectedCount);
|
||||
return nil;
|
||||
|
||||
@@ -588,6 +588,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
_scrollView.contentOffset = contentOffset;
|
||||
}
|
||||
|
||||
- (BOOL)isHorizontal:(UIScrollView *)scrollView
|
||||
{
|
||||
return scrollView.contentSize.width > self.frame.size.width;
|
||||
}
|
||||
|
||||
- (void)scrollToOffset:(CGPoint)offset
|
||||
{
|
||||
[self scrollToOffset:offset animated:YES];
|
||||
@@ -602,6 +607,26 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is a vertical scroll view, scrolls to the bottom.
|
||||
* If this is a horizontal scroll view, scrolls to the right.
|
||||
*/
|
||||
- (void)scrollToEnd:(BOOL)animated
|
||||
{
|
||||
BOOL isHorizontal = [self isHorizontal:_scrollView];
|
||||
CGPoint offset;
|
||||
if (isHorizontal) {
|
||||
offset = CGPointMake(_scrollView.contentSize.width - _scrollView.bounds.size.width, 0);
|
||||
} else {
|
||||
offset = CGPointMake(0, _scrollView.contentSize.height - _scrollView.bounds.size.height);
|
||||
}
|
||||
if (!CGPointEqualToPoint(_scrollView.contentOffset, offset)) {
|
||||
// Ensure at least one scroll event will fire
|
||||
_allowNextScrollNoMatterWhat = YES;
|
||||
[_scrollView setContentOffset:offset animated:animated];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
|
||||
{
|
||||
[_scrollView zoomToRect:rect animated:animated];
|
||||
@@ -727,7 +752,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, onScroll)
|
||||
CGFloat snapToIntervalF = (CGFloat)self.snapToInterval;
|
||||
|
||||
// Find which axis to snap
|
||||
BOOL isHorizontal = (scrollView.contentSize.width > self.frame.size.width);
|
||||
BOOL isHorizontal = [self isHorizontal:scrollView];
|
||||
|
||||
// What is the current offset?
|
||||
CGFloat targetContentOffsetAlongAxis = isHorizontal ? targetContentOffset->x : targetContentOffset->y;
|
||||
|
||||
@@ -147,6 +147,21 @@ RCT_EXPORT_METHOD(scrollTo:(nonnull NSNumber *)reactTag
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(scrollToEnd:(nonnull NSNumber *)reactTag
|
||||
animated:(BOOL)animated)
|
||||
{
|
||||
[self.bridge.uiManager addUIBlock:
|
||||
^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry){
|
||||
UIView *view = viewRegistry[reactTag];
|
||||
if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) {
|
||||
[(id<RCTScrollableProtocol>)view scrollToEnd:animated];
|
||||
} else {
|
||||
RCTLogError(@"tried to scrollTo: on non-RCTScrollableProtocol view %@ "
|
||||
"with tag #%@", view, reactTag);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(zoomToRect:(nonnull NSNumber *)reactTag
|
||||
withRect:(CGRect)rect
|
||||
animated:(BOOL)animated)
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
|
||||
- (void)scrollToOffset:(CGPoint)offset;
|
||||
- (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated;
|
||||
/**
|
||||
* If this is a vertical scroll view, scrolls to the bottom.
|
||||
* If this is a horizontal scroll view, scrolls to the right.
|
||||
*/
|
||||
- (void)scrollToEnd:(BOOL)animated;
|
||||
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated;
|
||||
|
||||
- (void)addScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0-master
|
||||
VERSION_NAME=0.41.0-rc.1
|
||||
GROUP=com.facebook.react
|
||||
|
||||
POM_NAME=ReactNative
|
||||
|
||||
+9
@@ -80,6 +80,15 @@ public class RecyclerViewBackedScrollViewManager extends
|
||||
scrollView.scrollTo(data.mDestX, data.mDestY, data.mAnimated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollToEnd(
|
||||
RecyclerViewBackedScrollView scrollView,
|
||||
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
|
||||
// Not implemented.
|
||||
// RecyclerViewBackedScrollView is deprecated and will be removed.
|
||||
// People should use a standard ScrollView or ListView instead.
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable
|
||||
Map getExportedCustomDirectEventTypeConstants() {
|
||||
|
||||
+14
@@ -117,6 +117,20 @@ public class ReactHorizontalScrollViewManager
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollToEnd(
|
||||
ReactHorizontalScrollView scrollView,
|
||||
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
|
||||
// ScrollView always has one child - the scrollable area
|
||||
int right =
|
||||
scrollView.getChildAt(0).getWidth() + scrollView.getPaddingRight();
|
||||
if (data.mAnimated) {
|
||||
scrollView.smoothScrollTo(right, scrollView.getScrollY());
|
||||
} else {
|
||||
scrollView.scrollTo(right, scrollView.getScrollY());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When set, fills the rest of the scrollview with a color to avoid setting a background and
|
||||
* creating unnecessary overdraw.
|
||||
|
||||
+19
-1
@@ -25,9 +25,11 @@ import com.facebook.react.common.MapBuilder;
|
||||
public class ReactScrollViewCommandHelper {
|
||||
|
||||
public static final int COMMAND_SCROLL_TO = 1;
|
||||
public static final int COMMAND_SCROLL_TO_END = 2;
|
||||
|
||||
public interface ScrollCommandHandler<T> {
|
||||
void scrollTo(T scrollView, ScrollToCommandData data);
|
||||
void scrollToEnd(T scrollView, ScrollToEndCommandData data);
|
||||
}
|
||||
|
||||
public static class ScrollToCommandData {
|
||||
@@ -42,10 +44,21 @@ public class ReactScrollViewCommandHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ScrollToEndCommandData {
|
||||
|
||||
public final boolean mAnimated;
|
||||
|
||||
ScrollToEndCommandData(boolean animated) {
|
||||
mAnimated = animated;
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String,Integer> getCommandsMap() {
|
||||
return MapBuilder.of(
|
||||
"scrollTo",
|
||||
COMMAND_SCROLL_TO);
|
||||
COMMAND_SCROLL_TO,
|
||||
"scrollToEnd",
|
||||
COMMAND_SCROLL_TO_END);
|
||||
}
|
||||
|
||||
public static <T> void receiveCommand(
|
||||
@@ -64,6 +77,11 @@ public class ReactScrollViewCommandHelper {
|
||||
viewManager.scrollTo(scrollView, new ScrollToCommandData(destX, destY, animated));
|
||||
return;
|
||||
}
|
||||
case COMMAND_SCROLL_TO_END: {
|
||||
boolean animated = args.getBoolean(0);
|
||||
viewManager.scrollToEnd(scrollView, new ScrollToEndCommandData(animated));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Unsupported command %d received by %s.",
|
||||
|
||||
+14
@@ -131,6 +131,20 @@ public class ReactScrollViewManager
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollToEnd(
|
||||
ReactScrollView scrollView,
|
||||
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
|
||||
// ScrollView always has one child - the scrollable area
|
||||
int bottom =
|
||||
scrollView.getChildAt(0).getHeight() + scrollView.getPaddingBottom();
|
||||
if (data.mAnimated) {
|
||||
scrollView.smoothScrollTo(scrollView.getScrollX(), bottom);
|
||||
} else {
|
||||
scrollView.scrollTo(scrollView.getScrollX(), bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map getExportedCustomDirectEventTypeConstants() {
|
||||
return createExportedCustomDirectEventTypeConstants();
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.41.0-rc.1",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
@@ -209,4 +209,4 @@
|
||||
"shelljs": "0.6.0",
|
||||
"sinon": "^2.0.0-pre.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user