Fix RCTScrollContentView layout with fixed size (#453)
This commit is contained in:
Родитель
c5458a7575
Коммит
374cef84e2
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RCTScrollContentLocalData : NSObject
|
||||
|
||||
@property (nonatomic, assign) CGFloat horizontalScrollerHeight;
|
||||
@property (nonatomic, assign) CGFloat verticalScrollerWidth;
|
||||
|
||||
- (instancetype)initWithVerticalScroller:(nullable NSScroller *)verticalScroller
|
||||
horizontalScroller:(nullable NSScroller *)horizontalScroller;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTScrollContentLocalData.h"
|
||||
|
||||
@implementation RCTScrollContentLocalData
|
||||
|
||||
- (instancetype)initWithVerticalScroller:(NSScroller *)verticalScroller
|
||||
horizontalScroller:(NSScroller *)horizontalScroller
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_verticalScrollerWidth = NSWidth([verticalScroller frame]);
|
||||
_horizontalScrollerHeight = NSHeight([horizontalScroller frame]);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -9,10 +9,28 @@
|
|||
|
||||
#import <yoga/Yoga.h>
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
#import "RCTScrollContentLocalData.h"
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTScrollContentShadowView
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
- (void)setLocalData:(RCTScrollContentLocalData *)localData
|
||||
{
|
||||
RCTAssert(
|
||||
[localData isKindOfClass:[RCTScrollContentLocalData class]],
|
||||
@"Local data object for `RCTScrollContentView` must be `RCTScrollContentLocalData` instance.");
|
||||
|
||||
super.marginEnd = (YGValue){localData.verticalScrollerWidth, YGUnitPoint};
|
||||
super.marginBottom = (YGValue){localData.horizontalScrollerHeight, YGUnitPoint};
|
||||
|
||||
[self didSetProps:@[@"marginEnd", @"marginBottom"]];
|
||||
}
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
- (void)layoutWithMetrics:(RCTLayoutMetrics)layoutMetrics
|
||||
layoutContext:(RCTLayoutContext)layoutContext
|
||||
{
|
||||
|
|
|
@ -10,9 +10,20 @@
|
|||
#import <React/RCTAssert.h>
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
#import <React/RCTUIManager.h>
|
||||
#import "RCTScrollContentLocalData.h"
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
#import "RCTScrollView.h"
|
||||
|
||||
@implementation RCTScrollContentView
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
{
|
||||
BOOL _hasHorizontalScroller;
|
||||
BOOL _hasVerticalScroller;
|
||||
}
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
- (void)reactSetFrame:(CGRect)frame
|
||||
{
|
||||
|
@ -21,25 +32,6 @@
|
|||
#else // [TODO(macOS ISS#2323203)
|
||||
// macOS also has a NSClipView in its hierarchy
|
||||
RCTScrollView *scrollView = (RCTScrollView *)self.superview.superview.superview;
|
||||
|
||||
if (scrollView != nil) {
|
||||
// On macOS scroll indicators may float over the content view like they do in iOS
|
||||
// or depending on system preferences they may be outside of the content view
|
||||
// which means the clip view will be smaller than the scroll view itself.
|
||||
// In such cases the content view layout must shrink accordingly otherwise
|
||||
// the contents will overflow causing the scroll indicators to appear unnecessarily.
|
||||
NSScrollView *platformScrollView = scrollView.scrollView;
|
||||
if (platformScrollView.scrollerStyle == NSScrollerStyleLegacy) {
|
||||
NSScroller *verticalScroller = platformScrollView.verticalScroller;
|
||||
if (!verticalScroller.isHidden) {
|
||||
frame.size.width -= verticalScroller.frame.size.width;
|
||||
}
|
||||
NSScroller *horizontalScroller = platformScrollView.horizontalScroller;
|
||||
if (!horizontalScroller.isHidden) {
|
||||
frame.size.height -= horizontalScroller.frame.size.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
|
||||
[super reactSetFrame:frame];
|
||||
|
@ -52,6 +44,32 @@
|
|||
@"Unexpected view hierarchy of RCTScrollView component.");
|
||||
|
||||
[scrollView updateContentOffsetIfNeeded];
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
// On macOS scroll indicators may float over the content view like they do in iOS
|
||||
// or depending on system preferences they may be outside of the content view
|
||||
// which means the clip view will be smaller than the scroll view itself.
|
||||
// In such cases the content view layout must shrink accordingly otherwise
|
||||
// the contents will overflow causing the scroll indicators to appear unnecessarily.
|
||||
NSScrollView *platformScrollView = [scrollView scrollView];
|
||||
if ([platformScrollView scrollerStyle] == NSScrollerStyleLegacy) {
|
||||
const BOOL nextHasHorizontalScroller = [platformScrollView hasHorizontalScroller];
|
||||
const BOOL nextHasVerticalScroller = [platformScrollView hasVerticalScroller];
|
||||
|
||||
if (_hasHorizontalScroller != nextHasHorizontalScroller ||
|
||||
_hasVerticalScroller != nextHasVerticalScroller) {
|
||||
|
||||
_hasHorizontalScroller = nextHasHorizontalScroller;
|
||||
_hasVerticalScroller = nextHasVerticalScroller;
|
||||
|
||||
RCTScrollContentLocalData *localData =
|
||||
[[RCTScrollContentLocalData alloc]
|
||||
initWithVerticalScroller:[platformScrollView verticalScroller]
|
||||
horizontalScroller:[platformScrollView horizontalScroller]];
|
||||
[[[scrollView bridge] uiManager] setLocalData:localData forView:self];
|
||||
}
|
||||
}
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, readonly) RCTBridge *bridge;
|
||||
|
||||
/**
|
||||
* The `RCTScrollView` may have at most one single subview. This will ensure
|
||||
* that the scroll view's `contentSize` will be efficiently set to the size of
|
||||
|
|
|
@ -187,7 +187,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
self.scrollEnabled = YES;
|
||||
self.hasHorizontalScroller = YES;
|
||||
self.hasVerticalScroller = YES;
|
||||
self.autohidesScrollers = YES;
|
||||
self.panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCustomPan:)];
|
||||
#else // ]TODO(macOS ISS#2323203)
|
||||
[self.panGestureRecognizer addTarget:self action:@selector(handleCustomPan:)];
|
||||
|
@ -566,6 +565,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
}
|
||||
}
|
||||
|
||||
- (RCTBridge *)bridge
|
||||
{
|
||||
return [_eventDispatcher bridge];
|
||||
}
|
||||
|
||||
- (RCTUIView *)contentView // TODO(macOS ISS#3536887)
|
||||
{
|
||||
return _scrollView.documentView;
|
||||
|
@ -751,6 +755,11 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
|
|||
[self react_updateClippedSubviewsWithClipRect:clipRect relativeToView:clipView];
|
||||
_lastClippedToRect = bounds;
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
[[self scrollView] setHasHorizontalScroller:[self isHorizontal:_scrollView]];
|
||||
[[self scrollView] setHasVerticalScroller:[self isVertical:_scrollView]];
|
||||
#endif // ]TODO(macOS ISS#2323203)
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS ISS#2323203)
|
||||
|
@ -808,6 +817,13 @@ static inline void RCTApplyTransformationAccordingLayoutDirection(RCTPlatformVie
|
|||
return scrollView.contentSize.width > self.frame.size.width;
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX // [TODO(macOS Candidate ISS#2710739)
|
||||
- (BOOL)isVertical:(RCTCustomScrollView *)scrollView
|
||||
{
|
||||
return scrollView.contentSize.height > self.frame.size.height;
|
||||
}
|
||||
#endif // ]TODO(macOS Candidate ISS#2710739)
|
||||
|
||||
- (void)scrollToOffset:(CGPoint)offset
|
||||
{
|
||||
[self scrollToOffset:offset animated:YES];
|
||||
|
|
Загрузка…
Ссылка в новой задаче