Skip to content

Commit ce00152

Browse files
committed
feat: BottomSheet iOS add onChangeState function
1 parent 14612cf commit ce00152

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

src/bottomsheet/bottomsheet-common.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ export interface ShownBottomSheetData extends EventData {
1414
closeCallback?: Function;
1515
}
1616

17+
export enum StateBottomSheet {
18+
CLOSED = -1,
19+
COLLAPSED = 0,
20+
EXPANDED = 1,
21+
DRAGGING = 2
22+
}
23+
24+
export type onChangeStateBottomSheet = (stateBottomSheet: StateBottomSheet, slideOffset?: number) => void;
25+
1726
export const shownInBottomSheetEvent = 'shownInBottomSheet';
1827
export const showingInBottomSheetEvent = 'showingInBottomSheet';
1928

@@ -33,6 +42,7 @@ export interface BottomSheetOptions {
3342
skipCollapsedState?: boolean; // optional Android parameter to skip midway state when view is greater than 50%. Default is false
3443
peekHeight?: number; // optional parameter to set the collapsed sheet height. To work on iOS you need to set trackingScrollView.
3544
ignoreKeyboardHeight: boolean; //(iOS only) A Boolean value that controls whether the height of the keyboard should affect the bottom sheet's frame when the keyboard shows on the screen. (Default: true)
45+
onChangeState?: onChangeStateBottomSheet; // One works to be called on the scroll of the sheet. Parameters: state (CLOSED, DRAGGING, DRAGGING, COLLAPSED) and slideOffset is the new offset of this bottom sheet within [-1,1] range. Offset increases as this bottom sheet is moving upward. From 0 to 1 the sheet is between collapsed and expanded states and from -1 to 0 it is between hidden and collapsed states.
3646
}
3747

3848
export abstract class ViewWithBottomSheetBase extends View {
@@ -42,6 +52,9 @@ export abstract class ViewWithBottomSheetBase extends View {
4252
// used when the bottomSheet is dismissed
4353
public _onDismissBottomSheetCallback: Function;
4454

55+
// used when the bottomSheet change state
56+
public _onChangeStateBottomSheetCallback: onChangeStateBottomSheet;
57+
4558
_bottomSheetFragment: any; // com.google.android.material.bottomsheet.BottomSheetDialogFragment
4659
protected abstract _hideNativeBottomSheet(parent, whenClosedCallback);
4760
protected _bottomSheetContext: any;
@@ -111,6 +124,14 @@ export abstract class ViewWithBottomSheetBase extends View {
111124
};
112125
this._hideNativeBottomSheet(parent, whenClosedCallback);
113126
};
127+
128+
if (options.onChangeState && typeof options.onChangeState === 'function') {
129+
this._onChangeStateBottomSheetCallback = (stateBottomSheet: StateBottomSheet, slideOffset: number) => {
130+
// only called if not already called by _closeBottomSheetCallback
131+
options.onChangeState(stateBottomSheet, slideOffset);
132+
};
133+
}
134+
114135
this._bottomSheetContext.closeCallback = this._closeBottomSheetCallback;
115136
}
116137
protected _raiseShowingBottomSheetEvent() {
@@ -148,4 +169,4 @@ export abstract class ViewWithBottomSheetBase extends View {
148169
return view;
149170
}
150171
}
151-
}
172+
}

src/bottomsheet/bottomsheet.ios.ts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { Application, IOSHelper, Page, Screen, Trace, Utils, View, fromObject } from '@nativescript/core';
2-
import { iOSNativeHelper } from '@nativescript/core/utils';
3-
import { iosIgnoreSafeAreaProperty } from '@nativescript/core/ui/core/view/view-common';
42
import { applyMixins } from '@nativescript-community/ui-material-core';
53
import { BottomSheetOptions } from './bottomsheet';
6-
import { ViewWithBottomSheetBase } from './bottomsheet-common';
4+
import { StateBottomSheet, ViewWithBottomSheetBase } from './bottomsheet-common';
75

86
export { ViewWithBottomSheetBase } from './bottomsheet-common';
97

@@ -24,7 +22,33 @@ class MDCBottomSheetControllerDelegateImpl extends NSObject {
2422

2523
return delegate;
2624
}
27-
25+
bottomSheetControllerDidChangeYOffsetYOffset(controller: MDCBottomSheetController, yOffset: number) {
26+
const owner = this._owner.get();
27+
if (owner && owner._onChangeStateBottomSheetCallback) {
28+
const presentationController = controller.presentationController as MDCBottomSheetPresentationController;
29+
const heightScreen = Screen.mainScreen.heightDIPs;
30+
const heightCollapsedSheet = presentationController.preferredSheetHeight || controller.preferredContentSize.height;
31+
const window = UIApplication.sharedApplication.windows.firstObject;
32+
const topPadding = window.safeAreaInsets.top;
33+
const bottomPadding = window.safeAreaInsets.bottom;
34+
35+
const isStateCollapsed = heightScreen - yOffset - bottomPadding === heightCollapsedSheet;
36+
const isExpanded = yOffset === topPadding;
37+
if (!isStateCollapsed && !isExpanded) {
38+
//normalized = (value - min) / (max - min);
39+
let normalized = 0;
40+
if (yOffset + bottomPadding > heightScreen - heightCollapsedSheet) {
41+
normalized = ((heightScreen - yOffset - bottomPadding) - 0) / (heightCollapsedSheet - 0) - 1;
42+
} else {
43+
normalized = ((heightScreen - yOffset) - heightCollapsedSheet) / (heightScreen - heightCollapsedSheet);
44+
}
45+
owner._onChangeStateBottomSheetCallback(StateBottomSheet.DRAGGING, normalized);
46+
} else {
47+
const state = isStateCollapsed ? StateBottomSheet.COLLAPSED : StateBottomSheet.EXPANDED;
48+
owner._onChangeStateBottomSheetCallback(state, state);
49+
}
50+
}
51+
}
2852
bottomSheetControllerDidDismissBottomSheet(controller: MDCBottomSheetController) {
2953
// called when clicked on background
3054
const owner = this._owner.get();
@@ -37,14 +61,25 @@ class MDCBottomSheetControllerDelegateImpl extends NSObject {
3761
}
3862
bottomSheetControllerStateChangedState(controller: MDCBottomSheetController, state: MDCSheetState) {
3963
// called when swiped
64+
const owner = this._owner.get();
4065
if (state === MDCSheetState.Closed) {
41-
const owner = this._owner.get();
4266
if (owner) {
4367
owner._onDismissBottomSheetCallback && owner._onDismissBottomSheetCallback();
68+
if (owner._onChangeStateBottomSheetCallback) {
69+
owner._onChangeStateBottomSheetCallback(StateBottomSheet.CLOSED, StateBottomSheet.CLOSED);
70+
}
4471
if (owner && owner.isLoaded) {
4572
owner.callUnloaded();
4673
}
4774
}
75+
} else {
76+
if (owner && owner._onChangeStateBottomSheetCallback) {
77+
if (state === MDCSheetState.Extended) {
78+
owner._onChangeStateBottomSheetCallback(StateBottomSheet.EXPANDED, StateBottomSheet.EXPANDED);
79+
} else {
80+
owner._onChangeStateBottomSheetCallback(StateBottomSheet.COLLAPSED, StateBottomSheet.COLLAPSED);
81+
}
82+
}
4883
}
4984
}
5085
}
@@ -471,4 +506,4 @@ export function install() {
471506
mixinInstalled = true;
472507
overrideBottomSheet();
473508
}
474-
}
509+
}

0 commit comments

Comments
 (0)