Skip to content

Commit 6af6a83

Browse files
animaonlineRoman AlifanovTitozzz
authored
feat(ios): Added support for scrollview indicatorStyle (#3743)
* added support for light scroll indicators on iOS * rename prop, and cleaned * Update RNCWebViewManager.java --------- Co-authored-by: Roman Alifanov <roman@bbc.no> Co-authored-by: Thibault Malbranche <malbranche.thibault@gmail.com> Co-authored-by: Thibault Malbranche <thibault@brigad.co>
1 parent 159e207 commit 6af6a83

File tree

8 files changed

+86
-21
lines changed

8 files changed

+86
-21
lines changed

android/src/newarch/com/reactnativecommunity/webview/RNCWebViewManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,9 @@ public void setPullToRefreshEnabled(RNCWebViewWrapper view, boolean value) {}
395395
@Override
396396
public void setRefreshControlLightMode(RNCWebViewWrapper view, boolean value) {}
397397

398+
@Override
399+
public void setIndicatorStyle(RNCWebViewWrapper view, @Nullable String value) {}
400+
398401
@Override
399402
public void setScrollEnabled(RNCWebViewWrapper view, boolean value) {}
400403

apple/RNCWebView.mm

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ - (instancetype)initWithFrame:(CGRect)frame
7171
if (self = [super initWithFrame:frame]) {
7272
static const auto defaultProps = std::make_shared<const RNCWebViewProps>();
7373
_props = defaultProps;
74-
74+
7575
_view = [[RNCWebViewImpl alloc] init];
76-
76+
7777
_view.onShouldStartLoadWithRequest = [self](NSDictionary* dictionary) {
7878
if (_eventEmitter) {
7979
auto webViewEventEmitter = std::static_pointer_cast<RNCWebViewEventEmitter const>(_eventEmitter);
@@ -191,7 +191,7 @@ - (instancetype)initWithFrame:(CGRect)frame
191191
.selectedText = std::string([[dictionary valueForKey:@"selectedText"] UTF8String]),
192192
.key = std::string([[dictionary valueForKey:@"key"] UTF8String]),
193193
.label = std::string([[dictionary valueForKey:@"label"] UTF8String])
194-
194+
195195
};
196196
webViewEventEmitter->onCustomMenuSelection(data);
197197
}
@@ -312,7 +312,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
312312
REMAP_WEBVIEW_PROP(showsHorizontalScrollIndicator)
313313
REMAP_WEBVIEW_PROP(showsVerticalScrollIndicator)
314314
REMAP_WEBVIEW_PROP(keyboardDisplayRequiresUserAction)
315-
315+
316316
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */
317317
REMAP_WEBVIEW_PROP(automaticallyAdjustContentInsets)
318318
#endif
@@ -398,7 +398,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
398398
for (const auto &menuItem: newViewProps.suppressMenuItems) {
399399
[suppressMenuItems addObject: RCTNSStringFromString(menuItem)];
400400
}
401-
401+
402402
[_view setSuppressMenuItems:suppressMenuItems];
403403
}
404404
if (oldViewProps.hasOnFileDownload != newViewProps.hasOnFileDownload) {
@@ -410,10 +410,10 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
410410
.downloadUrl = std::string([[dictionary valueForKey:@"downloadUrl"] UTF8String])
411411
};
412412
webViewEventEmitter->onFileDownload(data);
413-
}
413+
}
414414
};
415415
} else {
416-
_view.onFileDownload = nil;
416+
_view.onFileDownload = nil;
417417
}
418418
}
419419
if (oldViewProps.hasOnOpenWindowEvent != newViewProps.hasOnOpenWindowEvent) {
@@ -459,7 +459,16 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
459459
}
460460
}
461461
#endif
462-
462+
if (oldViewProps.indicatorStyle != newViewProps.indicatorStyle) {
463+
if (newViewProps.indicatorStyle == RNCWebViewIndicatorStyle::Black) {
464+
[_view setIndicatorStyle:@"black"];
465+
} else if (newViewProps.indicatorStyle == RNCWebViewIndicatorStyle::White) {
466+
[_view setIndicatorStyle:@"white"];
467+
} else {
468+
[_view setIndicatorStyle:@"default"];
469+
}
470+
}
471+
463472
NSMutableDictionary* source = [[NSMutableDictionary alloc] init];
464473
if (!newViewProps.newSource.uri.empty()) {
465474
[source setValue:RCTNSStringFromString(newViewProps.newSource.uri) forKey:@"uri"];
@@ -484,7 +493,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
484493
[source setValue:RCTNSStringFromString(newViewProps.newSource.method) forKey:@"method"];
485494
}
486495
[_view setSource:source];
487-
496+
488497
[super updateProps:props oldProps:oldProps];
489498
}
490499

apple/RNCWebViewImpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *)request
102102
@property (nonatomic, assign) BOOL allowsLinkPreview;
103103
@property (nonatomic, assign) BOOL showsHorizontalScrollIndicator;
104104
@property (nonatomic, assign) BOOL showsVerticalScrollIndicator;
105+
@property (nonatomic, copy) NSString * _Nullable indicatorStyle;
105106
@property (nonatomic, assign) BOOL directionalLockEnabled;
106107
@property (nonatomic, assign) BOOL ignoreSilentHardwareSwitch;
107108
@property (nonatomic, copy) NSString * _Nullable allowingReadAccessToURL;

apple/RNCWebViewImpl.m

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ - (NSString *)stringFromAction:(SEL) action {
7474
@"toggleUnderline:": @"underline",
7575
@"_share:": @"share",
7676
};
77-
77+
7878
return map[sel] ?: sel;
7979
}
8080

@@ -86,7 +86,7 @@ - (BOOL)canPerformAction:(SEL)action
8686
return NO;
8787
}
8888
}
89-
89+
9090
if (!self.menuItems) {
9191
return [super canPerformAction:action withSender:sender];
9292
}
@@ -276,7 +276,7 @@ - (void)startLongPress:(UILongPressGestureRecognizer *)pressSender
276276

277277
UIMenuController *menuController = [UIMenuController sharedMenuController];
278278
NSMutableArray *menuControllerItems = [NSMutableArray arrayWithCapacity:self.menuItems.count];
279-
279+
280280
for(NSDictionary *menuItem in self.menuItems) {
281281
NSString *menuItemLabel = [RCTConvert NSString:menuItem[@"label"]];
282282
NSString *menuItemKey = [RCTConvert NSString:menuItem[@"key"]];
@@ -535,6 +535,15 @@ - (void)didMoveToWindow
535535
_webView.scrollView.bounces = _pullToRefreshEnabled || _bounces;
536536
_webView.scrollView.showsHorizontalScrollIndicator = _showsHorizontalScrollIndicator;
537537
_webView.scrollView.showsVerticalScrollIndicator = _showsVerticalScrollIndicator;
538+
539+
if ([_indicatorStyle isEqualToString:@"black"]) {
540+
_webView.scrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack;
541+
} else if ([_indicatorStyle isEqualToString:@"white"]) {
542+
_webView.scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
543+
} else {
544+
_webView.scrollView.indicatorStyle = UIScrollViewIndicatorStyleDefault;
545+
}
546+
538547
_webView.scrollView.directionalLockEnabled = _directionalLockEnabled;
539548
#endif // !TARGET_OS_OSX
540549
_webView.allowsLinkPreview = _allowsLinkPreview;
@@ -852,7 +861,7 @@ - (void)visitSource
852861
[self syncCookiesToWebView:^{
853862
// Add observer to sync cookies from webview to sharedHTTPCookieStorage
854863
[webView.configuration.websiteDataStore.httpCookieStore addObserver:self];
855-
864+
856865
// Because of the way React works, as pages redirect, we actually end up
857866
// passing the redirect urls back here, so we ignore them if trying to load
858867
// the same url. We'll expose a call to 'reload' to allow a user to load
@@ -1084,6 +1093,19 @@ - (void)setShowsVerticalScrollIndicator:(BOOL)showsVerticalScrollIndicator
10841093
_showsVerticalScrollIndicator = showsVerticalScrollIndicator;
10851094
_webView.scrollView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
10861095
}
1096+
1097+
- (void)setIndicatorStyle:(NSString *)indicatorStyle
1098+
{
1099+
_indicatorStyle = indicatorStyle;
1100+
1101+
if ([indicatorStyle isEqualToString:@"black"]) {
1102+
_webView.scrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack;
1103+
} else if ([indicatorStyle isEqualToString:@"white"]) {
1104+
_webView.scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
1105+
} else {
1106+
_webView.scrollView.indicatorStyle = UIScrollViewIndicatorStyleDefault;
1107+
}
1108+
}
10871109
#endif // !TARGET_OS_OSX
10881110

10891111
- (void)postMessage:(NSString *)message
@@ -1399,7 +1421,7 @@ - (void) webView:(WKWebView *)webView
13991421
}
14001422

14011423
/**
1402-
* Called when the web views content process is terminated.
1424+
* Called when the web view's content process is terminated.
14031425
* @see https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455639-webviewwebcontentprocessdidtermi?language=objc
14041426
*/
14051427
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView

apple/RNCWebViewManager.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ - (RNCView *)view
167167
view.showsVerticalScrollIndicator = json == nil ? true : [RCTConvert BOOL: json];
168168
}
169169

170+
RCT_CUSTOM_VIEW_PROPERTY(indicatorStyle, NSString, RNCWebViewImpl) {
171+
view.indicatorStyle = [RCTConvert NSString: json];
172+
}
173+
170174
RCT_CUSTOM_VIEW_PROPERTY(keyboardDisplayRequiresUserAction, BOOL, RNCWebViewImpl) {
171175
view.keyboardDisplayRequiresUserAction = json == nil ? true : [RCTConvert BOOL: json];
172176
}

docs/Reference.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ This document lays out the current public properties and methods for the React N
5353
- [`contentInsetAdjustmentBehavior`](Reference.md#contentInsetAdjustmentBehavior)
5454
- [`contentMode`](Reference.md#contentMode)
5555
- [`dataDetectorTypes`](Reference.md#datadetectortypes)
56+
- [`indicatorStyle`](Reference.md#indicatorStyle)
5657
- [`scrollEnabled`](Reference.md#scrollenabled)
5758
- [`nestedScrollEnabled`](Reference.md#nestedscrollenabled)
5859
- [`setBuiltInZoomControls`](Reference.md#setBuiltInZoomControls)
@@ -1149,6 +1150,16 @@ Boolean value that determines whether scrolling is enabled in the `WebView`. The
11491150

11501151
---
11511152

1153+
### `indicatorStyle`[](#props-index)
1154+
1155+
The colorstyle of the scroll indicator. The default value is `default`.
1156+
1157+
| Type | Required | Platform |
1158+
| ------ | -------- | -------- |
1159+
| string | No | iOS |
1160+
1161+
---
1162+
11521163
### `nestedScrollEnabled`[](#props-index)
11531164

11541165
Boolean value that determines whether scrolling is possible in the `WebView` when used inside a `ScrollView` on Android. The default value is `false`.

src/RNCWebViewNativeComponent.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ export interface NativeProps extends ViewProps {
281281
onShouldStartLoadWithRequest: DirectEventHandler<ShouldStartLoadRequestEvent>;
282282
showsHorizontalScrollIndicator?: WithDefault<boolean, true>;
283283
showsVerticalScrollIndicator?: WithDefault<boolean, true>;
284+
indicatorStyle?: WithDefault<'default' | 'black' | 'white', 'default'>;
284285
newSource: Readonly<{
285286
uri?: string;
286287
method?: string;

src/WebViewTypes.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ export type CacheMode =
182182

183183
export type AndroidLayerType = 'none' | 'software' | 'hardware';
184184

185+
export type IndicatorStyleType = 'default' | 'black' | 'white';
186+
185187
export interface WebViewSourceUri {
186188
/**
187189
* The URI to load in the `WebView`. Can be a local or remote file.
@@ -424,7 +426,7 @@ export interface IOSWebViewProps extends WebViewSharedProps {
424426

425427
/**
426428
* If the value of this property is true, the scroll view stops on multiples
427-
* of the scroll views bounds when the user scrolls.
429+
* of the scroll view's bounds when the user scrolls.
428430
* The default value is false.
429431
* @platform ios
430432
*/
@@ -660,14 +662,26 @@ export interface IOSWebViewProps extends WebViewSharedProps {
660662
pullToRefreshEnabled?: boolean;
661663

662664
/**
663-
* Boolean value that determines whether a pull to refresh gesture is
664-
* available in the `WebView`. The default value is `false`.
665-
* If `true`, sets `bounces` automatically to `true`
665+
* Boolean value that determines whether the refresh control color is white or not.
666+
* The default value is `false`, meaning the refresh control color will be the default.
666667
* @platform ios
667668
*
668669
*/
669670
refreshControlLightMode?: boolean;
670671

672+
/**
673+
* Determines the style of the scroll indicators. This property works the same
674+
* as `indicatorStyle` on React Native's ScrollView.
675+
* The default value is `'default'`.
676+
*
677+
* Possible values:
678+
* - `'default'` - Default style (dark on light backgrounds, light on dark backgrounds)
679+
* - `'black'` - Black scroll indicators
680+
* - `'white'` - White scroll indicators
681+
* @platform ios
682+
*/
683+
indicatorStyle?: IndicatorStyleType;
684+
671685
/**
672686
* Function that is invoked when the client needs to download a file.
673687
*
@@ -689,9 +703,9 @@ export interface IOSWebViewProps extends WebViewSharedProps {
689703
/**
690704
* A Boolean value which, when set to `true`, indicates to WebKit that a WKWebView
691705
* will only navigate to app-bound domains. Once set, any attempt to navigate away
692-
* from an app-bound domain will fail with the error App-bound domain failure.
706+
* from an app-bound domain will fail with the error "App-bound domain failure."
693707
*
694-
* Applications can specify up to 10 app-bound domains using a new
708+
* Applications can specify up to 10 "app-bound" domains using a new
695709
* Info.plist key `WKAppBoundDomains`.
696710
* @platform ios
697711
*/
@@ -786,7 +800,7 @@ export interface MacOSWebViewProps extends WebViewSharedProps {
786800

787801
/**
788802
* If the value of this property is true, the scroll view stops on multiples
789-
* of the scroll views bounds when the user scrolls.
803+
* of the scroll view's bounds when the user scrolls.
790804
* The default value is false.
791805
* @platform macos
792806
*/

0 commit comments

Comments
 (0)