mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
2015-02-30 update:
- [ReactNative] Fix indentation | Ben Alpert - [ReactKit] Bring back ability to jump to syntax error from redbox | Alex Kotliarskyi - [ReactKit] Update pthread.h import path to be (more?) correct | Ben Alpert - Simplified event handling | Nick Lockwood - [ReactNative] more readme - xcode error help | Spencer Ahrens
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
@implementation RCTNavItemManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[RCTNavItem alloc] initWithFrame:CGRectZero];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class RCTJavaScriptEventDispatcher;
|
||||
@class RCTEventDispatcher;
|
||||
|
||||
@interface RCTNavigator : UIView <UINavigationControllerDelegate>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
@property (nonatomic, assign) NSInteger requestedTopOfStack;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
|
||||
eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
/**
|
||||
* Schedules a JavaScript navigation and prevents `UIKit` from navigating until
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTEventExtractor.h"
|
||||
#import "RCTJavaScriptEventDispatcher.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTNavItem.h"
|
||||
#import "RCTUtils.h"
|
||||
@@ -138,7 +137,7 @@ NSInteger kNeverProgressed = -10000;
|
||||
*/
|
||||
- (instancetype)initWithScrollCallback:(dispatch_block_t)callback
|
||||
{
|
||||
if (self = [super init]) {
|
||||
if ((self = [super init])) {
|
||||
_scrollCallback = callback;
|
||||
}
|
||||
return self;
|
||||
@@ -193,7 +192,7 @@ NSInteger kNeverProgressed = -10000;
|
||||
|
||||
@interface RCTNavigator() <RCTWrapperViewControllerNavigationListener>
|
||||
{
|
||||
RCTJavaScriptEventDispatcher *_eventDispatcher;
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
NSInteger _numberOfViewControllerMovesToIgnore;
|
||||
}
|
||||
|
||||
@@ -267,7 +266,7 @@ NSInteger kNeverProgressed = -10000;
|
||||
@implementation RCTNavigator
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
@@ -311,16 +310,12 @@ NSInteger kNeverProgressed = -10000;
|
||||
if (nextProgress == _mostRecentProgress) {
|
||||
return;
|
||||
}
|
||||
NSDictionary *nativeEventObj = @{
|
||||
@"fromIndex": @(_currentlyTransitioningFrom),
|
||||
@"toIndex": @(_currentlyTransitioningTo),
|
||||
@"progress": @(nextProgress),
|
||||
@"target": self.reactTag ?: @0,
|
||||
};
|
||||
_mostRecentProgress = nextProgress;
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:self.reactTag
|
||||
type:RCTEventNavigationProgress
|
||||
nativeEventObj:nativeEventObj]];
|
||||
[_eventDispatcher sendRawEventWithType:@"topNavigationProgress"
|
||||
body:@{@"fromIndex": @(_currentlyTransitioningFrom),
|
||||
@"toIndex": @(_currentlyTransitioningTo),
|
||||
@"progress": @(nextProgress),
|
||||
@"target": self.reactTag}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,21 +438,17 @@ NSInteger kNeverProgressed = -10000;
|
||||
|
||||
- (void)handleTopOfStackChanged
|
||||
{
|
||||
NSDictionary *nativeEventObj = @{
|
||||
@"target":self.reactTag ?: @0,
|
||||
@"stackLength":@(_navigationController.viewControllers.count)
|
||||
};
|
||||
NSArray *eventArgs = [RCTEventExtractor eventArgs:self.reactTag
|
||||
type:RCTEventNavigateBack
|
||||
nativeEventObj:nativeEventObj];
|
||||
[_eventDispatcher sendEventWithArgs:eventArgs];
|
||||
[_eventDispatcher sendRawEventWithType:@"topNavigateBack"
|
||||
body:@{@"target":self.reactTag,
|
||||
@"stackLength":@(_navigationController.viewControllers.count)}];
|
||||
}
|
||||
|
||||
- (void)dispatchFakeScrollEvent
|
||||
{
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
|
||||
type:RCTEventScroll
|
||||
nativeEventObj:[RCTEventExtractor fakeScrollEventObjectFor:[self reactTag]]]];
|
||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
|
||||
reactTag:self.reactTag
|
||||
scrollView:nil
|
||||
userData:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@implementation RCTNavigatorManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[RCTNavigator alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
@implementation RCTNetworkImageViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
RCTNetworkImageView *view = [[RCTNetworkImageView alloc] initWithFrame:CGRectZero imageDownloader:[RCTImageDownloader sharedInstance]];
|
||||
view.contentMode = UIViewContentModeScaleAspectFill;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
@implementation RCTRawTextManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[UIView alloc] init];
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@protocol UIScrollViewDelegate;
|
||||
|
||||
@class RCTJavaScriptEventDispatcher;
|
||||
@class RCTEventDispatcher;
|
||||
|
||||
@interface RCTScrollView : RCTView <UIScrollViewDelegate, RCTScrollableProtocol, RCTAutoInsetsProtocol>
|
||||
|
||||
@@ -32,6 +32,6 @@
|
||||
@property (nonatomic, assign) BOOL centerContent;
|
||||
@property (nonatomic, copy) NSArray *stickyHeaderIndices;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
@end
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTEventExtractor.h"
|
||||
#import "RCTJavaScriptEventDispatcher.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTScrollDispatcher.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
@@ -249,24 +247,20 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTScrollView ()
|
||||
@implementation RCTScrollView
|
||||
{
|
||||
RCTJavaScriptEventDispatcher *_eventDispatcher;
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
BOOL _contentSizeManuallySet;
|
||||
RCTScrollDispatcher *_scrollDispatcher;
|
||||
RCTCustomScrollView *_scrollView;
|
||||
UIView *_contentView;
|
||||
NSTimeInterval _lastScrollDispatchTime;
|
||||
NSMutableArray *_cachedChildFrames;
|
||||
BOOL _allowNextScrollNoMatterWhat;
|
||||
}
|
||||
|
||||
@property (nonatomic, readwrite, assign) BOOL didThrottleMomentumScrollEvent;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTScrollView
|
||||
|
||||
@synthesize nativeMainScrollDelegate = _nativeMainScrollDelegate;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
|
||||
@@ -274,9 +268,12 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||
_scrollView = [[RCTCustomScrollView alloc] initWithFrame:CGRectZero];
|
||||
_scrollView.delegate = self;
|
||||
_scrollView.delaysContentTouches = NO;
|
||||
_scrollDispatcher = [[RCTScrollDispatcher alloc] initWithEventDispatcher:eventDispatcher];
|
||||
_automaticallyAdjustContentInsets = YES;
|
||||
_contentInset = UIEdgeInsetsZero;
|
||||
|
||||
_throttleScrollCallbackMS = 0;
|
||||
_lastScrollDispatchTime = CACurrentMediaTime();
|
||||
_cachedChildFrames = [[NSMutableArray alloc] init];
|
||||
|
||||
[self addSubview:_scrollView];
|
||||
}
|
||||
@@ -371,90 +368,120 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||
[_scrollView zoomToRect:rect animated:animated];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate methods
|
||||
#pragma mark - ScrollView delegate
|
||||
|
||||
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
|
||||
{
|
||||
[_scrollDispatcher scrollViewDidEndScrollingAnimation:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewDidEndScrollingAnimation:scrollView];
|
||||
}
|
||||
#define RCT_SCROLL_EVENT_HANDLER(delegateMethod, eventName) \
|
||||
- (void)delegateMethod:(UIScrollView *)scrollView \
|
||||
{ \
|
||||
[_eventDispatcher sendScrollEventWithType:eventName reactTag:self.reactTag scrollView:scrollView userData:nil]; \
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \
|
||||
[_nativeMainScrollDelegate delegateMethod:scrollView]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define RCT_FORWARD_SCROLL_EVENT(call) \
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \
|
||||
[_nativeMainScrollDelegate call]; \
|
||||
}
|
||||
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndScrollingAnimation, RCTScrollEventTypeEndDeceleration)
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewWillBeginDecelerating, RCTScrollEventTypeStartDeceleration)
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndDecelerating, RCTScrollEventTypeEndDeceleration)
|
||||
RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove)
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
[_scrollDispatcher scrollViewDidScroll:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewDidScroll:scrollView];
|
||||
}
|
||||
}
|
||||
NSTimeInterval now = CACurrentMediaTime();
|
||||
NSTimeInterval throttleScrollCallbackSeconds = _throttleScrollCallbackMS / 1000.0;
|
||||
|
||||
/**
|
||||
* TODO: this logic looks wrong, and it may be because it is. Currently, if _throttleScrollCallbackMS
|
||||
* is set to zero (the default), the "didScroll" event is only sent once per scroll, instead of repeatedly
|
||||
* while scrolling as expected. However, if you "fix" that bug, ScrollView will generate repeated
|
||||
* warnings, and behave strangely (ListView works fine however), so don't fix it unless you fix that too!
|
||||
*/
|
||||
if (_allowNextScrollNoMatterWhat ||
|
||||
(_throttleScrollCallbackMS != 0 && throttleScrollCallbackSeconds < (now - _lastScrollDispatchTime))) {
|
||||
|
||||
// Calculate changed frames
|
||||
NSMutableArray *updatedChildFrames = [[NSMutableArray alloc] init];
|
||||
[[_contentView reactSubviews] enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
|
||||
|
||||
// Check if new or changed
|
||||
CGRect newFrame = subview.frame;
|
||||
BOOL frameChanged = NO;
|
||||
if (_cachedChildFrames.count <= idx) {
|
||||
frameChanged = YES;
|
||||
[_cachedChildFrames addObject:[NSValue valueWithCGRect:newFrame]];
|
||||
} else if (!CGRectEqualToRect(newFrame, [_cachedChildFrames[idx] CGRectValue])) {
|
||||
frameChanged = YES;
|
||||
_cachedChildFrames[idx] = [NSValue valueWithCGRect:newFrame];
|
||||
}
|
||||
|
||||
// Create JS frame object
|
||||
if (frameChanged) {
|
||||
[updatedChildFrames addObject: @{
|
||||
@"index": @(idx),
|
||||
@"x": @(newFrame.origin.x),
|
||||
@"y": @(newFrame.origin.y),
|
||||
@"width": @(newFrame.size.width),
|
||||
@"height": @(newFrame.size.height),
|
||||
}];
|
||||
}
|
||||
|
||||
}];
|
||||
|
||||
// If there are new frames, add them to event data
|
||||
NSDictionary *userData = nil;
|
||||
if (updatedChildFrames.count > 0) {
|
||||
userData = @{@"updatedChildFrames": updatedChildFrames};
|
||||
}
|
||||
|
||||
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
|
||||
{
|
||||
[_scrollDispatcher scrollViewWillBeginDecelerating:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewWillBeginDecelerating:scrollView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
|
||||
{
|
||||
[_scrollDispatcher scrollViewDidEndDecelerating:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewDidEndDecelerating:scrollView];
|
||||
// Dispatch event
|
||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
|
||||
reactTag:self.reactTag
|
||||
scrollView:scrollView
|
||||
userData:userData];
|
||||
// Update dispatch time
|
||||
_lastScrollDispatchTime = now;
|
||||
_allowNextScrollNoMatterWhat = NO;
|
||||
}
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewDidScroll:scrollView);
|
||||
}
|
||||
|
||||
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
|
||||
{
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewWillBeginDragging:scrollView];
|
||||
}
|
||||
[_scrollDispatcher scrollViewWillBeginDragging:_scrollView reactTag:[self reactTag]];
|
||||
_allowNextScrollNoMatterWhat = YES; // Ensure next scroll event is recorded, regardless of throttle
|
||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeStart reactTag:self.reactTag scrollView:scrollView userData:nil];
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewWillBeginDragging:scrollView);
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
|
||||
{
|
||||
[_scrollDispatcher scrollViewWillEndDragging:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
|
||||
}
|
||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil];
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset);
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
|
||||
{
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
|
||||
{
|
||||
[_scrollDispatcher scrollViewDidScroll:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidZoom:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewDidZoom:scrollView];
|
||||
}
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewDidEndDragging:scrollView willDecelerate:decelerate);
|
||||
}
|
||||
|
||||
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
|
||||
{
|
||||
[_scrollDispatcher scrollViewWillBeginDragging:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewWillBeginZooming:scrollView withView:view];
|
||||
}
|
||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeStart reactTag:self.reactTag scrollView:scrollView userData:nil];
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewWillBeginZooming:scrollView withView:view);
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
|
||||
{
|
||||
[_scrollDispatcher scrollViewWillEndDragging:_scrollView reactTag:[self reactTag]];
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) {
|
||||
[_nativeMainScrollDelegate scrollViewDidEndZooming:scrollView withView:view atScale:scale];
|
||||
}
|
||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil];
|
||||
RCT_FORWARD_SCROLL_EVENT(scrollViewDidEndZooming:scrollView withView:view atScale:scale);
|
||||
}
|
||||
|
||||
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
|
||||
{
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) {
|
||||
if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) {
|
||||
return [_nativeMainScrollDelegate scrollViewShouldScrollToTop:scrollView];
|
||||
}
|
||||
return YES;
|
||||
@@ -467,11 +494,6 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
- (void)setThrottleScrollCallbackMS:(NSUInteger)ms
|
||||
{
|
||||
_scrollDispatcher.throttleScrollCallbackMS = ms;
|
||||
}
|
||||
|
||||
- (CGSize)_calculateViewportSize
|
||||
{
|
||||
CGSize viewportSize = self.bounds.size;
|
||||
@@ -527,27 +549,24 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
||||
{
|
||||
if (_contentSizeManuallySet) {
|
||||
_scrollView.contentSize = _contentSize;
|
||||
} else if (!_contentView) {
|
||||
_scrollView.contentSize = CGSizeZero;
|
||||
} else {
|
||||
if (!_contentView) {
|
||||
_scrollView.contentSize = CGSizeZero;
|
||||
} else {
|
||||
CGSize singleSubviewSize = _contentView.frame.size;
|
||||
CGPoint singleSubviewPosition = _contentView.frame.origin;
|
||||
CGSize fittedSize = CGSizeMake(
|
||||
singleSubviewSize.width + singleSubviewPosition.x,
|
||||
singleSubviewSize.height + singleSubviewPosition.y
|
||||
);
|
||||
if (!CGSizeEqualToSize(_scrollView.contentSize, fittedSize)) {
|
||||
// When contentSize is set manually, ScrollView internals will reset contentOffset to 0,0. Since
|
||||
// we potentially set contentSize whenever anything in the ScrollView updates, we workaround this
|
||||
// issue by manually adjusting contentOffset whenever this happens
|
||||
CGPoint newOffset = [self calculateOffsetForContentSize:fittedSize];
|
||||
_scrollView.contentSize = fittedSize;
|
||||
_scrollView.contentOffset = newOffset;
|
||||
}
|
||||
// when react makes changes to our
|
||||
[_scrollView dockClosestSectionHeader];
|
||||
CGSize singleSubviewSize = _contentView.frame.size;
|
||||
CGPoint singleSubviewPosition = _contentView.frame.origin;
|
||||
CGSize fittedSize = {
|
||||
singleSubviewSize.width + singleSubviewPosition.x,
|
||||
singleSubviewSize.height + singleSubviewPosition.y
|
||||
};
|
||||
if (!CGSizeEqualToSize(_scrollView.contentSize, fittedSize)) {
|
||||
// When contentSize is set manually, ScrollView internals will reset contentOffset to 0,0. Since
|
||||
// we potentially set contentSize whenever anything in the ScrollView updates, we workaround this
|
||||
// issue by manually adjusting contentOffset whenever this happens
|
||||
CGPoint newOffset = [self calculateOffsetForContentSize:fittedSize];
|
||||
_scrollView.contentSize = fittedSize;
|
||||
_scrollView.contentOffset = newOffset;
|
||||
}
|
||||
[_scrollView dockClosestSectionHeader];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
@implementation RCTScrollViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[RCTScrollView alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
|
||||
}
|
||||
@@ -33,8 +33,8 @@ RCT_EXPORT_VIEW_PROPERTY(stickyHeaderIndices);
|
||||
RCT_EXPORT_VIEW_PROPERTY(throttleScrollCallbackMS);
|
||||
RCT_EXPORT_VIEW_PROPERTY(zoomScale);
|
||||
RCT_EXPORT_VIEW_PROPERTY(contentInset);
|
||||
RCT_REMAP_VIEW_PROPERTY(scrollIndicatorInsets, scrollView.scrollIndicatorInsets);
|
||||
RCT_REMAP_VIEW_PROPERTY(contentOffset, scrollView.contentOffse);
|
||||
RCT_EXPORT_VIEW_PROPERTY(scrollIndicatorInsets);
|
||||
RCT_EXPORT_VIEW_PROPERTY(contentOffset);
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
|
||||
@@ -183,17 +183,17 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||
node->layout.should_update = false;
|
||||
_layoutLifecycle = RCTLayoutLifecycleComputed;
|
||||
|
||||
CGPoint absoluteTopLeft = (CGPoint){
|
||||
CGPoint absoluteTopLeft = {
|
||||
RCTRoundPixelValue(absolutePosition.x + node->layout.position[CSS_LEFT]),
|
||||
RCTRoundPixelValue(absolutePosition.y + node->layout.position[CSS_TOP])
|
||||
};
|
||||
|
||||
CGPoint absoluteBottomRight = (CGPoint){
|
||||
CGPoint absoluteBottomRight = {
|
||||
RCTRoundPixelValue(absolutePosition.x + node->layout.position[CSS_LEFT] + node->layout.dimensions[CSS_WIDTH]),
|
||||
RCTRoundPixelValue(absolutePosition.y + node->layout.position[CSS_TOP] + node->layout.dimensions[CSS_HEIGHT])
|
||||
};
|
||||
|
||||
CGRect frame = (CGRect){
|
||||
CGRect frame = {
|
||||
RCTRoundPixelValue(node->layout.position[CSS_LEFT]),
|
||||
RCTRoundPixelValue(node->layout.position[CSS_TOP]),
|
||||
RCTRoundPixelValue(absoluteBottomRight.x - absoluteTopLeft.x),
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
@implementation RCTStaticImageManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[RCTStaticImage alloc] init];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class RCTJavaScriptEventDispatcher;
|
||||
@class RCTEventDispatcher;
|
||||
|
||||
@interface RCTTextField : UITextField
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
@property (nonatomic, assign) BOOL autoCorrect;
|
||||
@property (nonatomic, assign) UIEdgeInsets paddingEdgeInsets; // TODO: contentInset
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
#import "RCTTextField.h"
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTEventExtractor.h"
|
||||
#import "RCTJavaScriptEventDispatcher.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
@implementation RCTTextField
|
||||
{
|
||||
RCTJavaScriptEventDispatcher *_eventDispatcher;
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
NSMutableArray *_reactSubviews;
|
||||
BOOL _jsRequestingFirstResponder;
|
||||
}
|
||||
@@ -20,33 +19,41 @@
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
|
||||
_eventDispatcher = eventDispatcher;
|
||||
[self addTarget:self action:@selector(_textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
|
||||
[self addTarget:self action:@selector(_textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin];
|
||||
[self addTarget:self action:@selector(_textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];
|
||||
[self addTarget:self action:@selector(_textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit];
|
||||
_reactSubviews = [[NSMutableArray alloc] init];
|
||||
self.returnKeyType = UIReturnKeyDone;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray *)reactSubviews
|
||||
{
|
||||
// TODO: do we support subviews of textfield in React?
|
||||
// In any case, we should have a better approach than manually
|
||||
// maintaining array in each view subclass like this
|
||||
return _reactSubviews;
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
{
|
||||
// TODO: this is a bit broken - if the TextView inserts any of
|
||||
// it's own views below or between React's, the indices won't match
|
||||
[_reactSubviews removeObject:subview];
|
||||
[subview removeFromSuperview];
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
|
||||
{
|
||||
// TODO: this is a bit broken - if the TextView inserts any of
|
||||
// it's own views below or between React's, the indices won't match
|
||||
[_reactSubviews insertObject:view atIndex:atIndex];
|
||||
[super insertSubview:view atIndex:atIndex];
|
||||
}
|
||||
@@ -56,7 +63,6 @@
|
||||
if (_caretHidden) {
|
||||
return CGRectZero;
|
||||
}
|
||||
|
||||
return [super caretRectForPosition:position];
|
||||
}
|
||||
|
||||
@@ -81,72 +87,45 @@
|
||||
return self.autocorrectionType == UITextAutocorrectionTypeYes;
|
||||
}
|
||||
|
||||
- (void)_textFieldDidChange
|
||||
{
|
||||
[self handleTextChange];
|
||||
#define RCT_TEXT_EVENT_HANDLER(delegateMethod, eventName) \
|
||||
- (void)delegateMethod \
|
||||
{ \
|
||||
[_eventDispatcher sendTextEventWithType:eventName \
|
||||
reactTag:self.reactTag \
|
||||
text:self.text]; \
|
||||
}
|
||||
|
||||
- (void)_textFieldEndEditing
|
||||
{
|
||||
NSDictionary *event = @{@"text": self.text, @"target": self.reactTag};
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
|
||||
type:RCTEventTextFieldEndEditing
|
||||
nativeEventObj:event]];
|
||||
}
|
||||
RCT_TEXT_EVENT_HANDLER(_textFieldDidChange, RCTTextEventTypeChange)
|
||||
RCT_TEXT_EVENT_HANDLER(_textFieldBeginEditing, RCTTextEventTypeFocus)
|
||||
RCT_TEXT_EVENT_HANDLER(_textFieldEndEditing, RCTTextEventTypeEnd)
|
||||
RCT_TEXT_EVENT_HANDLER(_textFieldSubmitEditing, RCTTextEventTypeSubmit)
|
||||
|
||||
- (void)_textFieldSubmitEditing
|
||||
{
|
||||
NSDictionary *event = @{@"text": self.text, @"target": self.reactTag};
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
|
||||
type:RCTEventTextFieldSubmitEditing
|
||||
nativeEventObj:event]];
|
||||
}
|
||||
// TODO: we should support shouldChangeTextInRect (see UITextFieldDelegate)
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
_jsRequestingFirstResponder = YES;
|
||||
BOOL wasPreviouslyResponder = [self isFirstResponder];
|
||||
BOOL ret = [super becomeFirstResponder];
|
||||
BOOL isTransitioningResponder = !wasPreviouslyResponder && ret;
|
||||
if (isTransitioningResponder) {
|
||||
[self handleTextFieldDidFocus];
|
||||
}
|
||||
_jsRequestingFirstResponder = YES; // TODO: is this still needed?
|
||||
BOOL result = [super becomeFirstResponder];
|
||||
_jsRequestingFirstResponder = NO;
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
[self handleTextFieldWillBlur];
|
||||
return [super resignFirstResponder];
|
||||
BOOL result = [super resignFirstResponder];
|
||||
if (result)
|
||||
{
|
||||
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
|
||||
reactTag:self.reactTag
|
||||
text:self.text];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Prevent native from becoming first responder
|
||||
// Prevent native from becoming first responder (TODO: why?)
|
||||
- (BOOL)canBecomeFirstResponder
|
||||
{
|
||||
return _jsRequestingFirstResponder;
|
||||
}
|
||||
|
||||
- (void)handleTextChange
|
||||
{
|
||||
NSDictionary *event = @{@"text": self.text, @"target": self.reactTag};
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
|
||||
type:RCTEventChange
|
||||
nativeEventObj:event]];
|
||||
}
|
||||
|
||||
- (void)handleTextFieldDidFocus
|
||||
{
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
|
||||
type:RCTEventTextFieldDidFocus
|
||||
nativeEventObj:@{@"target":self.reactTag}]];
|
||||
}
|
||||
|
||||
- (void)handleTextFieldWillBlur
|
||||
{
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
|
||||
type:RCTEventTextFieldWillBlur
|
||||
nativeEventObj:@{@"target":self.reactTag}]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@implementation RCTTextFieldManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[RCTTextField alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
@implementation RCTTextManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
UILabel *label = [[UILabel alloc] init];
|
||||
label.numberOfLines = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
@implementation RCTUIActivityIndicatorViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
@implementation RCTUIViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[UIView alloc] init];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
@implementation RCTViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
return [[RCTView alloc] init];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class RCTJavaScriptEventDispatcher;
|
||||
@class RCTEventDispatcher;
|
||||
@class RCTNavItem;
|
||||
@class RCTWrapperViewController;
|
||||
|
||||
@@ -15,8 +15,8 @@ didMoveToNavigationController:(UINavigationController *)navigationController;
|
||||
|
||||
@interface RCTWrapperViewController : UIViewController
|
||||
|
||||
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
@property (nonatomic, readwrite, weak) id<RCTWrapperViewControllerNavigationListener> navigationListener;
|
||||
@property (nonatomic, strong, readwrite) RCTNavItem *navItem;
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
#import "RCTWrapperViewController.h"
|
||||
|
||||
#import "RCTEventExtractor.h"
|
||||
#import "RCTJavaScriptEventDispatcher.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTNavItem.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
@@ -11,7 +10,7 @@
|
||||
@implementation RCTWrapperViewController
|
||||
{
|
||||
UIView *_contentView;
|
||||
RCTJavaScriptEventDispatcher *_eventDispatcher;
|
||||
RCTEventDispatcher *_eventDispatcher;
|
||||
CGFloat _previousTopLayout;
|
||||
CGFloat _previousBottomLayout;
|
||||
}
|
||||
@@ -21,9 +20,9 @@
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if (self = [super initWithNibName:nil bundle:nil]) {
|
||||
if ((self = [super initWithNibName:nil bundle:nil])) {
|
||||
_contentView = contentView;
|
||||
_eventDispatcher = eventDispatcher;
|
||||
self.automaticallyAdjustsScrollViewInsets = NO;
|
||||
@@ -31,9 +30,9 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if (self = [self initWithContentView:navItem eventDispatcher:eventDispatcher]) {
|
||||
if ((self = [self initWithContentView:navItem eventDispatcher:eventDispatcher])) {
|
||||
_navItem = navItem;
|
||||
}
|
||||
return self;
|
||||
@@ -57,7 +56,7 @@
|
||||
[[UIBarButtonItem alloc] initWithTitle:_navItem.rightButtonTitle
|
||||
style:UIBarButtonItemStyleDone
|
||||
target:self
|
||||
action:@selector(_onRightButtonTapped:)];
|
||||
action:@selector(rightButtonTapped)];
|
||||
}
|
||||
|
||||
if (_navItem.backButtonTitle.length > 0) {
|
||||
@@ -95,20 +94,9 @@
|
||||
[self.view addSubview:_contentView];
|
||||
}
|
||||
|
||||
- (void)_onRightButtonTapped:(id)sender
|
||||
- (void)rightButtonTapped
|
||||
{
|
||||
RCTAssert(_navItem != nil, @"");
|
||||
[self handleNavRightButtonTapped];
|
||||
}
|
||||
|
||||
- (void)handleNavRightButtonTapped
|
||||
{
|
||||
NSDictionary *nativeEvent = @{
|
||||
@"target":_navItem.reactTag
|
||||
};
|
||||
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[_navItem reactTag]
|
||||
type:RCTEventNavRightButtonTap
|
||||
nativeEventObj:nativeEvent]];
|
||||
[_eventDispatcher sendRawEventWithType:@"topNavRightButtonTap" body:@{@"target":_navItem.reactTag}];
|
||||
}
|
||||
|
||||
- (void)didMoveToParentViewController:(UIViewController *)parent
|
||||
|
||||
Reference in New Issue
Block a user