capacitor-extended-dialog 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -9,6 +9,13 @@ npm install capacitor-extended-dialog
|
|
|
9
9
|
npx cap sync
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
+
## Android sheet behavior
|
|
13
|
+
|
|
14
|
+
- In `mode: 'basic'`, native Android sheets open between 50% and 80% of screen height.
|
|
15
|
+
- Dragging up continuously increases available body space while keeping header content at the top and actions pinned to the bottom.
|
|
16
|
+
- If sheet content exceeds the 80% initial cap, the body area becomes internally scrollable.
|
|
17
|
+
- In `mode: 'fullscreen'`, the same top-content/bottom-actions layout is preserved with a scrollable body area for overflow.
|
|
18
|
+
|
|
12
19
|
## API
|
|
13
20
|
|
|
14
21
|
<docgen-index>
|
|
@@ -21,6 +21,9 @@ import android.widget.ScrollView;
|
|
|
21
21
|
import android.widget.TextView;
|
|
22
22
|
import androidx.annotation.NonNull;
|
|
23
23
|
import androidx.annotation.Nullable;
|
|
24
|
+
import androidx.core.graphics.Insets;
|
|
25
|
+
import androidx.core.view.ViewCompat;
|
|
26
|
+
import androidx.core.view.WindowInsetsCompat;
|
|
24
27
|
import androidx.core.widget.TextViewCompat;
|
|
25
28
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
|
26
29
|
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
|
@@ -51,10 +54,17 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
51
54
|
private ExtendedDialog.SheetCallback sheetCallback;
|
|
52
55
|
private boolean dismissed = false;
|
|
53
56
|
private Context themedContext;
|
|
57
|
+
private LinearLayout rootLayout;
|
|
54
58
|
private ScrollView scrollView;
|
|
55
59
|
private LinearLayout headerLayout;
|
|
56
60
|
private LinearLayout bodyLayout;
|
|
57
61
|
private LinearLayout buttonContainer;
|
|
62
|
+
private int buttonHorizontalPaddingPx;
|
|
63
|
+
private int buttonTopPaddingPx;
|
|
64
|
+
private int buttonBottomBasePaddingPx;
|
|
65
|
+
private int buttonBottomInsetsPx;
|
|
66
|
+
private int buttonExpandedExtraPaddingPx;
|
|
67
|
+
private boolean applyExpandedButtonOffset;
|
|
58
68
|
|
|
59
69
|
public static SheetBottomDialogFragment newInstance(
|
|
60
70
|
String title,
|
|
@@ -145,10 +155,13 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
145
155
|
|
|
146
156
|
Context ctx = getThemedContext();
|
|
147
157
|
float density = getResources().getDisplayMetrics().density;
|
|
158
|
+
int screenHeight = getResources().getDisplayMetrics().heightPixels;
|
|
159
|
+
int initialRootHeight = fullscreen ? screenHeight : (int) (screenHeight * 0.5f);
|
|
148
160
|
|
|
149
161
|
// Root layout
|
|
150
|
-
|
|
151
|
-
|
|
162
|
+
rootLayout = new LinearLayout(ctx);
|
|
163
|
+
rootLayout.setOrientation(LinearLayout.VERTICAL);
|
|
164
|
+
rootLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, initialRootHeight));
|
|
152
165
|
|
|
153
166
|
// Apply background color
|
|
154
167
|
if (styleOptions.getBackgroundColor() != null) {
|
|
@@ -161,7 +174,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
161
174
|
.build();
|
|
162
175
|
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeModel);
|
|
163
176
|
shapeDrawable.setFillColor(ColorStateList.valueOf(styleOptions.getBackgroundColor()));
|
|
164
|
-
|
|
177
|
+
rootLayout.setBackground(shapeDrawable);
|
|
165
178
|
}
|
|
166
179
|
|
|
167
180
|
// Drag handle (only shown in basic/non-fullscreen mode)
|
|
@@ -180,7 +193,7 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
180
193
|
handleDrawable.setCornerRadius(handleHeight / 2f);
|
|
181
194
|
handleDrawable.setColor(outlineVariantColor);
|
|
182
195
|
dragHandle.setBackground(handleDrawable);
|
|
183
|
-
|
|
196
|
+
rootLayout.addView(dragHandle);
|
|
184
197
|
}
|
|
185
198
|
|
|
186
199
|
int horizontalPadding = (int) (24 * density);
|
|
@@ -247,12 +260,13 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
247
260
|
titleView.setLayoutParams(titleParams);
|
|
248
261
|
headerLayout.addView(titleView);
|
|
249
262
|
}
|
|
250
|
-
|
|
263
|
+
rootLayout.addView(headerLayout);
|
|
251
264
|
|
|
252
265
|
// ScrollView for body content (rows/message only)
|
|
253
266
|
scrollView = new ScrollView(ctx);
|
|
254
267
|
scrollView.setFillViewport(true);
|
|
255
|
-
scrollView.setLayoutParams(new LinearLayout.LayoutParams(
|
|
268
|
+
scrollView.setLayoutParams(new LinearLayout.LayoutParams(
|
|
269
|
+
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
|
|
256
270
|
|
|
257
271
|
bodyLayout = new LinearLayout(ctx);
|
|
258
272
|
bodyLayout.setOrientation(LinearLayout.VERTICAL);
|
|
@@ -312,14 +326,35 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
312
326
|
}
|
|
313
327
|
|
|
314
328
|
scrollView.addView(bodyLayout);
|
|
315
|
-
|
|
329
|
+
rootLayout.addView(scrollView);
|
|
316
330
|
|
|
317
331
|
// Button container pinned at bottom
|
|
318
332
|
buttonContainer = new LinearLayout(ctx);
|
|
319
333
|
buttonContainer.setOrientation(LinearLayout.VERTICAL);
|
|
320
334
|
float topSpacing = styleOptions.getContentButtonSpacing() != null ? styleOptions.getContentButtonSpacing() : 12f;
|
|
321
|
-
|
|
322
|
-
|
|
335
|
+
int buttonTopPadding = (int) (topSpacing * density);
|
|
336
|
+
int baseBottomPadding = (int) ((fullscreen ? 4f : 12f) * density);
|
|
337
|
+
int nonFullscreenExtraBottomPadding = fullscreen ? 0 : (int) (4 * density);
|
|
338
|
+
int bottomPaddingWithoutInsets = baseBottomPadding + nonFullscreenExtraBottomPadding;
|
|
339
|
+
|
|
340
|
+
buttonHorizontalPaddingPx = horizontalPadding;
|
|
341
|
+
buttonTopPaddingPx = buttonTopPadding;
|
|
342
|
+
buttonBottomBasePaddingPx = bottomPaddingWithoutInsets;
|
|
343
|
+
buttonBottomInsetsPx = 0;
|
|
344
|
+
buttonExpandedExtraPaddingPx = (int) (48 * density);
|
|
345
|
+
applyExpandedButtonOffset = fullscreen;
|
|
346
|
+
|
|
347
|
+
applyButtonContainerPadding();
|
|
348
|
+
|
|
349
|
+
ViewCompat.setOnApplyWindowInsetsListener(buttonContainer, (viewWithInsets, windowInsets) -> {
|
|
350
|
+
Insets systemBarInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
|
|
351
|
+
Insets gestureInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures());
|
|
352
|
+
Insets tappableInsets = windowInsets.getInsets(WindowInsetsCompat.Type.tappableElement());
|
|
353
|
+
buttonBottomInsetsPx = Math.max(systemBarInsets.bottom, Math.max(gestureInsets.bottom, tappableInsets.bottom));
|
|
354
|
+
applyButtonContainerPadding();
|
|
355
|
+
return windowInsets;
|
|
356
|
+
});
|
|
357
|
+
ViewCompat.requestApplyInsets(buttonContainer);
|
|
323
358
|
|
|
324
359
|
int primaryColor = MaterialColors.getColor(ctx, android.R.attr.colorPrimary, 0xFF6750A4);
|
|
325
360
|
|
|
@@ -380,9 +415,9 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
380
415
|
cancelBtn.setLayoutParams(cancelParams);
|
|
381
416
|
buttonContainer.addView(cancelBtn);
|
|
382
417
|
|
|
383
|
-
|
|
418
|
+
rootLayout.addView(buttonContainer);
|
|
384
419
|
|
|
385
|
-
return
|
|
420
|
+
return rootLayout;
|
|
386
421
|
}
|
|
387
422
|
|
|
388
423
|
@Override
|
|
@@ -413,17 +448,53 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
413
448
|
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
|
414
449
|
// Prevent dragging down in fullscreen mode
|
|
415
450
|
behavior.setDraggable(false);
|
|
451
|
+
setExpandedButtonOffset(true);
|
|
452
|
+
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
|
|
453
|
+
@Override
|
|
454
|
+
public void onStateChanged(@NonNull View sheet, int newState) {
|
|
455
|
+
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
|
456
|
+
setExpandedButtonOffset(true);
|
|
457
|
+
setRootHeight(getVisibleSheetHeight(sheet));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
@Override
|
|
462
|
+
public void onSlide(@NonNull View sheet, float slideOffset) {
|
|
463
|
+
setExpandedButtonOffset(true);
|
|
464
|
+
setRootHeight(getVisibleSheetHeight(sheet));
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
bottomSheet.post(() -> setRootHeight(getVisibleSheetHeight(bottomSheet)));
|
|
416
468
|
} else {
|
|
417
|
-
//
|
|
469
|
+
// Multi-stop bottom sheet: drag up to fullscreen, drag down to dismiss
|
|
418
470
|
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
|
|
419
471
|
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
420
472
|
bottomSheet.setLayoutParams(layoutParams);
|
|
421
473
|
|
|
422
|
-
behavior.setFitToContents(
|
|
474
|
+
behavior.setFitToContents(false);
|
|
423
475
|
behavior.setSkipCollapsed(true);
|
|
424
476
|
behavior.setHideable(true);
|
|
425
477
|
behavior.setDraggable(true);
|
|
426
478
|
|
|
479
|
+
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
|
|
480
|
+
@Override
|
|
481
|
+
public void onStateChanged(@NonNull View sheet, int newState) {
|
|
482
|
+
if (
|
|
483
|
+
newState == BottomSheetBehavior.STATE_HALF_EXPANDED ||
|
|
484
|
+
newState == BottomSheetBehavior.STATE_EXPANDED
|
|
485
|
+
) {
|
|
486
|
+
setExpandedButtonOffset(newState == BottomSheetBehavior.STATE_EXPANDED);
|
|
487
|
+
setRootHeight(getVisibleSheetHeight(sheet));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
@Override
|
|
492
|
+
public void onSlide(@NonNull View sheet, float slideOffset) {
|
|
493
|
+
setExpandedButtonOffset(slideOffset >= 0.9f);
|
|
494
|
+
setRootHeight(getVisibleSheetHeight(sheet));
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
427
498
|
bottomSheet.post(() -> {
|
|
428
499
|
int screenHeight = getResources().getDisplayMetrics().heightPixels;
|
|
429
500
|
int width = bottomSheet.getWidth() > 0
|
|
@@ -445,36 +516,90 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
445
516
|
bodyHeight = bodyLayout.getMeasuredHeight();
|
|
446
517
|
}
|
|
447
518
|
|
|
448
|
-
int
|
|
519
|
+
int btnHeight = 0;
|
|
449
520
|
if (buttonContainer != null) {
|
|
450
521
|
buttonContainer.measure(widthSpec, heightSpec);
|
|
451
|
-
|
|
522
|
+
btnHeight = buttonContainer.getMeasuredHeight();
|
|
452
523
|
}
|
|
453
524
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
int
|
|
457
|
-
desiredHeight = Math.max(desiredHeight, minHeight);
|
|
458
|
-
desiredHeight = Math.min(desiredHeight, maxHeight);
|
|
459
|
-
|
|
460
|
-
if (scrollView != null) {
|
|
461
|
-
ViewGroup.LayoutParams scrollParams = scrollView.getLayoutParams();
|
|
462
|
-
int scrollHeight = Math.max(0, desiredHeight - headerHeight - buttonHeight);
|
|
463
|
-
scrollParams.height = scrollHeight;
|
|
464
|
-
scrollView.setLayoutParams(scrollParams);
|
|
465
|
-
}
|
|
525
|
+
// Add drag handle height (~28dp)
|
|
526
|
+
float density = getResources().getDisplayMetrics().density;
|
|
527
|
+
int dragHandleHeight = (int) (28 * density);
|
|
466
528
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
529
|
+
int contentRequiredHeight = headerHeight + bodyHeight + btnHeight + dragHandleHeight;
|
|
530
|
+
int desiredHeight = clampInitialSheetHeight(screenHeight, contentRequiredHeight);
|
|
531
|
+
float ratio = calculateHalfExpandedRatio(screenHeight, desiredHeight);
|
|
470
532
|
|
|
533
|
+
setRootHeight(desiredHeight);
|
|
534
|
+
behavior.setHalfExpandedRatio(ratio);
|
|
471
535
|
behavior.setPeekHeight(desiredHeight);
|
|
472
|
-
behavior.setState(BottomSheetBehavior.
|
|
536
|
+
behavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
|
|
537
|
+
bottomSheet.post(() -> setRootHeight(getVisibleSheetHeight(bottomSheet)));
|
|
473
538
|
});
|
|
474
539
|
}
|
|
475
540
|
});
|
|
476
541
|
}
|
|
477
542
|
|
|
543
|
+
static int clampInitialSheetHeight(int screenHeight, int contentRequiredHeight) {
|
|
544
|
+
int minHeight = (int) (screenHeight * 0.5f);
|
|
545
|
+
int maxHeight = (int) (screenHeight * 0.8f);
|
|
546
|
+
int clampedToMin = Math.max(contentRequiredHeight, minHeight);
|
|
547
|
+
return Math.min(clampedToMin, maxHeight);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
static float calculateHalfExpandedRatio(int screenHeight, int desiredHeight) {
|
|
551
|
+
if (screenHeight <= 0) {
|
|
552
|
+
return 0.5f;
|
|
553
|
+
}
|
|
554
|
+
float ratio = (float) desiredHeight / screenHeight;
|
|
555
|
+
return Math.max(0.5f, Math.min(ratio, 0.8f));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private int getVisibleSheetHeight(@NonNull View sheet) {
|
|
559
|
+
View parent = sheet.getParent() instanceof View ? (View) sheet.getParent() : null;
|
|
560
|
+
int parentHeight = parent != null ? parent.getHeight() : getResources().getDisplayMetrics().heightPixels;
|
|
561
|
+
int visibleHeight = parentHeight - sheet.getTop();
|
|
562
|
+
int nonNegativeHeight = Math.max(0, visibleHeight);
|
|
563
|
+
// Clamp to parent bounds to avoid overshoot during spring/drag transitions.
|
|
564
|
+
return Math.min(parentHeight, nonNegativeHeight);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
private void setRootHeight(int targetHeight) {
|
|
568
|
+
if (rootLayout == null || targetHeight <= 0) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
ViewGroup.LayoutParams params = rootLayout.getLayoutParams();
|
|
572
|
+
if (params == null) {
|
|
573
|
+
params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, targetHeight);
|
|
574
|
+
} else if (params.height == targetHeight) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
params.height = targetHeight;
|
|
578
|
+
rootLayout.setLayoutParams(params);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
private void setExpandedButtonOffset(boolean enabled) {
|
|
582
|
+
if (applyExpandedButtonOffset == enabled) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
applyExpandedButtonOffset = enabled;
|
|
586
|
+
applyButtonContainerPadding();
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
private void applyButtonContainerPadding() {
|
|
590
|
+
if (buttonContainer == null) {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
int expandedExtraBottomPadding = applyExpandedButtonOffset ? buttonExpandedExtraPaddingPx : 0;
|
|
594
|
+
int resolvedBottomPadding = buttonBottomBasePaddingPx + buttonBottomInsetsPx + expandedExtraBottomPadding;
|
|
595
|
+
buttonContainer.setPadding(
|
|
596
|
+
buttonHorizontalPaddingPx,
|
|
597
|
+
buttonTopPaddingPx,
|
|
598
|
+
buttonHorizontalPaddingPx,
|
|
599
|
+
resolvedBottomPadding
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
478
603
|
private LinearLayout createSheetRow(
|
|
479
604
|
Context context,
|
|
480
605
|
JSONObject row,
|
package/package.json
CHANGED