capacitor-extended-dialog 0.0.10 → 0.0.11
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 +37 -0
- package/android/src/main/java/com/albermonte/extendeddialog/DialogStyleOptions.java +15 -1
- package/android/src/main/java/com/albermonte/extendeddialog/ExtendedDialog.java +31 -0
- package/android/src/main/java/com/albermonte/extendeddialog/ExtendedDialogPlugin.java +39 -0
- package/android/src/main/java/com/albermonte/extendeddialog/SheetBottomDialogFragment.java +170 -39
- package/dist/docs.json +97 -0
- package/dist/esm/definitions.d.ts +61 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +3 -1
- package/dist/esm/web.js +91 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +91 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +91 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/ExtendedDialogPlugin/ExtendedDialog.swift +40 -2
- package/ios/Sources/ExtendedDialogPlugin/ExtendedDialogPlugin.swift +33 -2
- package/ios/Sources/ExtendedDialogPlugin/FullScreenDialogViewController.swift +182 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ npx cap sync
|
|
|
19
19
|
* [`singleSelect(...)`](#singleselect)
|
|
20
20
|
* [`multiSelect(...)`](#multiselect)
|
|
21
21
|
* [`sheet(...)`](#sheet)
|
|
22
|
+
* [`messageSheet(...)`](#messagesheet)
|
|
22
23
|
* [Interfaces](#interfaces)
|
|
23
24
|
* [Type Aliases](#type-aliases)
|
|
24
25
|
|
|
@@ -129,6 +130,23 @@ Show a sheet dialog with a header, title, and structured data rows.
|
|
|
129
130
|
--------------------
|
|
130
131
|
|
|
131
132
|
|
|
133
|
+
### messageSheet(...)
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
messageSheet(options: MessageSheetOptions) => any
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Show a message sheet dialog with an optional header logo, title, and message.
|
|
140
|
+
|
|
141
|
+
| Param | Type | Description |
|
|
142
|
+
| ------------- | ------------------------------------------------------------------- | -------------------------------------- |
|
|
143
|
+
| **`options`** | <code><a href="#messagesheetoptions">MessageSheetOptions</a></code> | - Message sheet configuration options. |
|
|
144
|
+
|
|
145
|
+
**Returns:** <code>any</code>
|
|
146
|
+
|
|
147
|
+
--------------------
|
|
148
|
+
|
|
149
|
+
|
|
132
150
|
### Interfaces
|
|
133
151
|
|
|
134
152
|
|
|
@@ -245,6 +263,25 @@ Show a sheet dialog with a header, title, and structured data rows.
|
|
|
245
263
|
| **`confirmed`** | <code>boolean</code> | True if confirmed, false if cancelled |
|
|
246
264
|
|
|
247
265
|
|
|
266
|
+
#### MessageSheetOptions
|
|
267
|
+
|
|
268
|
+
| Prop | Type | Description |
|
|
269
|
+
| ------------------------ | ------------------------------------------------- | -------------------------------------------------------- |
|
|
270
|
+
| **`headerLogo`** | <code>string</code> | Header logo - supports base64 data URL or HTTP/HTTPS URL |
|
|
271
|
+
| **`title`** | <code>string</code> | Sheet title |
|
|
272
|
+
| **`message`** | <code>string</code> | Message body displayed in the sheet |
|
|
273
|
+
| **`confirmButtonTitle`** | <code>string</code> | Confirm button title |
|
|
274
|
+
| **`cancelButtonTitle`** | <code>string</code> | Cancel button title |
|
|
275
|
+
| **`mode`** | <code><a href="#dialogmode">DialogMode</a></code> | Dialog mode |
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
#### MessageSheetResult
|
|
279
|
+
|
|
280
|
+
| Prop | Type | Description |
|
|
281
|
+
| --------------- | -------------------- | ------------------------------------- |
|
|
282
|
+
| **`confirmed`** | <code>boolean</code> | True if confirmed, false if cancelled |
|
|
283
|
+
|
|
284
|
+
|
|
248
285
|
### Type Aliases
|
|
249
286
|
|
|
250
287
|
|
|
@@ -17,6 +17,7 @@ public class DialogStyleOptions {
|
|
|
17
17
|
private static final String KEY_MESSAGE_FONT_SIZE = "messageFontSize";
|
|
18
18
|
private static final String KEY_BUTTON_FONT_SIZE = "buttonFontSize";
|
|
19
19
|
private static final String KEY_CONTENT_BUTTON_SPACING = "contentButtonSpacing";
|
|
20
|
+
private static final String KEY_HEADER_LOGO_CORNER_RADIUS = "headerLogoCornerRadius";
|
|
20
21
|
|
|
21
22
|
private Integer buttonColor;
|
|
22
23
|
private Integer cancelButtonColor;
|
|
@@ -27,6 +28,7 @@ public class DialogStyleOptions {
|
|
|
27
28
|
private Float messageFontSize;
|
|
28
29
|
private Float buttonFontSize;
|
|
29
30
|
private Float contentButtonSpacing;
|
|
31
|
+
private Float headerLogoCornerRadius;
|
|
30
32
|
|
|
31
33
|
public DialogStyleOptions() {}
|
|
32
34
|
|
|
@@ -121,6 +123,15 @@ public class DialogStyleOptions {
|
|
|
121
123
|
this.contentButtonSpacing = parseSpacing(size);
|
|
122
124
|
}
|
|
123
125
|
|
|
126
|
+
public Float getHeaderLogoCornerRadius() {
|
|
127
|
+
return headerLogoCornerRadius;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public void setHeaderLogoCornerRadius(Double radius) {
|
|
131
|
+
// Allow any value: positive for custom radius, 0 for square, -1 for circle
|
|
132
|
+
this.headerLogoCornerRadius = radius != null ? radius.floatValue() : null;
|
|
133
|
+
}
|
|
134
|
+
|
|
124
135
|
public boolean hasStyles() {
|
|
125
136
|
return (
|
|
126
137
|
buttonColor != null ||
|
|
@@ -131,7 +142,8 @@ public class DialogStyleOptions {
|
|
|
131
142
|
titleFontSize != null ||
|
|
132
143
|
messageFontSize != null ||
|
|
133
144
|
buttonFontSize != null ||
|
|
134
|
-
contentButtonSpacing != null
|
|
145
|
+
contentButtonSpacing != null ||
|
|
146
|
+
headerLogoCornerRadius != null
|
|
135
147
|
);
|
|
136
148
|
}
|
|
137
149
|
|
|
@@ -145,6 +157,7 @@ public class DialogStyleOptions {
|
|
|
145
157
|
if (messageFontSize != null) bundle.putFloat(KEY_MESSAGE_FONT_SIZE, messageFontSize);
|
|
146
158
|
if (buttonFontSize != null) bundle.putFloat(KEY_BUTTON_FONT_SIZE, buttonFontSize);
|
|
147
159
|
if (contentButtonSpacing != null) bundle.putFloat(KEY_CONTENT_BUTTON_SPACING, contentButtonSpacing);
|
|
160
|
+
if (headerLogoCornerRadius != null) bundle.putFloat(KEY_HEADER_LOGO_CORNER_RADIUS, headerLogoCornerRadius);
|
|
148
161
|
}
|
|
149
162
|
|
|
150
163
|
public static DialogStyleOptions readFromBundle(Bundle bundle) {
|
|
@@ -158,6 +171,7 @@ public class DialogStyleOptions {
|
|
|
158
171
|
options.messageFontSize = bundle.containsKey(KEY_MESSAGE_FONT_SIZE) ? bundle.getFloat(KEY_MESSAGE_FONT_SIZE) : null;
|
|
159
172
|
options.buttonFontSize = bundle.containsKey(KEY_BUTTON_FONT_SIZE) ? bundle.getFloat(KEY_BUTTON_FONT_SIZE) : null;
|
|
160
173
|
options.contentButtonSpacing = bundle.containsKey(KEY_CONTENT_BUTTON_SPACING) ? bundle.getFloat(KEY_CONTENT_BUTTON_SPACING) : null;
|
|
174
|
+
options.headerLogoCornerRadius = bundle.containsKey(KEY_HEADER_LOGO_CORNER_RADIUS) ? bundle.getFloat(KEY_HEADER_LOGO_CORNER_RADIUS) : null;
|
|
161
175
|
return options;
|
|
162
176
|
}
|
|
163
177
|
}
|
|
@@ -771,4 +771,35 @@ public class ExtendedDialog {
|
|
|
771
771
|
fragment.show(fragmentActivity.getSupportFragmentManager(), "bottom_sheet");
|
|
772
772
|
});
|
|
773
773
|
}
|
|
774
|
+
|
|
775
|
+
public void showMessageSheet(
|
|
776
|
+
Activity activity,
|
|
777
|
+
String title,
|
|
778
|
+
String message,
|
|
779
|
+
String headerLogo,
|
|
780
|
+
String confirmButtonTitle,
|
|
781
|
+
String cancelButtonTitle,
|
|
782
|
+
boolean fullscreen,
|
|
783
|
+
DialogStyleOptions styleOptions,
|
|
784
|
+
SheetCallback callback
|
|
785
|
+
) {
|
|
786
|
+
if (!(activity instanceof FragmentActivity)) {
|
|
787
|
+
callback.onResult(false);
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
FragmentActivity fragmentActivity = (FragmentActivity) activity;
|
|
791
|
+
fragmentActivity.runOnUiThread(() -> {
|
|
792
|
+
SheetBottomDialogFragment fragment = SheetBottomDialogFragment.newMessageInstance(
|
|
793
|
+
title,
|
|
794
|
+
headerLogo,
|
|
795
|
+
message,
|
|
796
|
+
confirmButtonTitle != null ? confirmButtonTitle : "Confirm",
|
|
797
|
+
cancelButtonTitle != null ? cancelButtonTitle : "Cancel",
|
|
798
|
+
fullscreen,
|
|
799
|
+
styleOptions
|
|
800
|
+
);
|
|
801
|
+
fragment.setSheetCallback(callback);
|
|
802
|
+
fragment.show(fragmentActivity.getSupportFragmentManager(), "message_sheet");
|
|
803
|
+
});
|
|
804
|
+
}
|
|
774
805
|
}
|
|
@@ -26,6 +26,7 @@ public class ExtendedDialogPlugin extends Plugin {
|
|
|
26
26
|
styleOptions.setMessageFontSize(call.getDouble("messageFontSize"));
|
|
27
27
|
styleOptions.setButtonFontSize(call.getDouble("buttonFontSize"));
|
|
28
28
|
styleOptions.setContentButtonSpacing(call.getDouble("contentButtonSpacing"));
|
|
29
|
+
styleOptions.setHeaderLogoCornerRadius(call.getDouble("headerLogoCornerRadius"));
|
|
29
30
|
return styleOptions;
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -250,4 +251,42 @@ public class ExtendedDialogPlugin extends Plugin {
|
|
|
250
251
|
call.reject("Invalid rows format");
|
|
251
252
|
}
|
|
252
253
|
}
|
|
254
|
+
|
|
255
|
+
@PluginMethod
|
|
256
|
+
public void messageSheet(PluginCall call) {
|
|
257
|
+
String title = call.getString("title");
|
|
258
|
+
String message = call.getString("message");
|
|
259
|
+
String headerLogo = call.getString("headerLogo");
|
|
260
|
+
String confirmButtonTitle = call.getString("confirmButtonTitle");
|
|
261
|
+
String cancelButtonTitle = call.getString("cancelButtonTitle");
|
|
262
|
+
String mode = call.getString("mode", "basic");
|
|
263
|
+
boolean fullscreen = "fullscreen".equals(mode);
|
|
264
|
+
DialogStyleOptions styleOptions = extractStyleOptions(call);
|
|
265
|
+
|
|
266
|
+
if (title == null) {
|
|
267
|
+
call.reject("title is required");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (message == null) {
|
|
272
|
+
call.reject("message is required");
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
implementation.showMessageSheet(
|
|
277
|
+
getActivity(),
|
|
278
|
+
title,
|
|
279
|
+
message,
|
|
280
|
+
headerLogo,
|
|
281
|
+
confirmButtonTitle,
|
|
282
|
+
cancelButtonTitle,
|
|
283
|
+
fullscreen,
|
|
284
|
+
styleOptions,
|
|
285
|
+
(confirmed) -> {
|
|
286
|
+
JSObject result = new JSObject();
|
|
287
|
+
result.put("confirmed", confirmed);
|
|
288
|
+
call.resolve(result);
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
}
|
|
253
292
|
}
|
|
@@ -42,13 +42,19 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
42
42
|
private static final String ARG_TITLE = "title";
|
|
43
43
|
private static final String ARG_HEADER_LOGO = "headerLogo";
|
|
44
44
|
private static final String ARG_ROWS = "rows";
|
|
45
|
+
private static final String ARG_MESSAGE = "message";
|
|
45
46
|
private static final String ARG_CONFIRM_BUTTON = "confirmButton";
|
|
46
47
|
private static final String ARG_CANCEL_BUTTON = "cancelButton";
|
|
47
48
|
private static final String ARG_FULLSCREEN = "fullscreen";
|
|
49
|
+
private static final String ARG_IS_MESSAGE_SHEET = "isMessageSheet";
|
|
48
50
|
|
|
49
51
|
private ExtendedDialog.SheetCallback sheetCallback;
|
|
50
52
|
private boolean dismissed = false;
|
|
51
53
|
private Context themedContext;
|
|
54
|
+
private ScrollView scrollView;
|
|
55
|
+
private LinearLayout headerLayout;
|
|
56
|
+
private LinearLayout bodyLayout;
|
|
57
|
+
private LinearLayout buttonContainer;
|
|
52
58
|
|
|
53
59
|
public static SheetBottomDialogFragment newInstance(
|
|
54
60
|
String title,
|
|
@@ -67,6 +73,32 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
67
73
|
args.putString(ARG_CONFIRM_BUTTON, confirmButton);
|
|
68
74
|
args.putString(ARG_CANCEL_BUTTON, cancelButton);
|
|
69
75
|
args.putBoolean(ARG_FULLSCREEN, fullscreen);
|
|
76
|
+
args.putBoolean(ARG_IS_MESSAGE_SHEET, false);
|
|
77
|
+
if (styleOptions != null) {
|
|
78
|
+
styleOptions.writeToBundle(args);
|
|
79
|
+
}
|
|
80
|
+
fragment.setArguments(args);
|
|
81
|
+
return fragment;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public static SheetBottomDialogFragment newMessageInstance(
|
|
85
|
+
String title,
|
|
86
|
+
String headerLogo,
|
|
87
|
+
String message,
|
|
88
|
+
String confirmButton,
|
|
89
|
+
String cancelButton,
|
|
90
|
+
boolean fullscreen,
|
|
91
|
+
DialogStyleOptions styleOptions
|
|
92
|
+
) {
|
|
93
|
+
SheetBottomDialogFragment fragment = new SheetBottomDialogFragment();
|
|
94
|
+
Bundle args = new Bundle();
|
|
95
|
+
args.putString(ARG_TITLE, title);
|
|
96
|
+
args.putString(ARG_HEADER_LOGO, headerLogo);
|
|
97
|
+
args.putString(ARG_MESSAGE, message);
|
|
98
|
+
args.putString(ARG_CONFIRM_BUTTON, confirmButton);
|
|
99
|
+
args.putString(ARG_CANCEL_BUTTON, cancelButton);
|
|
100
|
+
args.putBoolean(ARG_FULLSCREEN, fullscreen);
|
|
101
|
+
args.putBoolean(ARG_IS_MESSAGE_SHEET, true);
|
|
70
102
|
if (styleOptions != null) {
|
|
71
103
|
styleOptions.writeToBundle(args);
|
|
72
104
|
}
|
|
@@ -104,9 +136,11 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
104
136
|
String title = args.getString(ARG_TITLE, "");
|
|
105
137
|
String headerLogo = args.getString(ARG_HEADER_LOGO);
|
|
106
138
|
String rowsJson = args.getString(ARG_ROWS);
|
|
139
|
+
String message = args.getString(ARG_MESSAGE, "");
|
|
107
140
|
String confirmButton = args.getString(ARG_CONFIRM_BUTTON, "Confirm");
|
|
108
141
|
String cancelButton = args.getString(ARG_CANCEL_BUTTON, "Cancel");
|
|
109
142
|
boolean fullscreen = args.getBoolean(ARG_FULLSCREEN, false);
|
|
143
|
+
boolean isMessageSheet = args.getBoolean(ARG_IS_MESSAGE_SHEET, false);
|
|
110
144
|
DialogStyleOptions styleOptions = DialogStyleOptions.readFromBundle(args);
|
|
111
145
|
|
|
112
146
|
Context ctx = getThemedContext();
|
|
@@ -149,15 +183,13 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
149
183
|
root.addView(dragHandle);
|
|
150
184
|
}
|
|
151
185
|
|
|
152
|
-
// ScrollView for content
|
|
153
|
-
ScrollView scrollView = new ScrollView(ctx);
|
|
154
|
-
scrollView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
|
|
155
|
-
|
|
156
|
-
LinearLayout contentLayout = new LinearLayout(ctx);
|
|
157
|
-
contentLayout.setOrientation(LinearLayout.VERTICAL);
|
|
158
186
|
int horizontalPadding = (int) (24 * density);
|
|
159
187
|
int verticalPadding = (int) (16 * density);
|
|
160
|
-
|
|
188
|
+
|
|
189
|
+
// Header (logo + title) - not scrollable
|
|
190
|
+
headerLayout = new LinearLayout(ctx);
|
|
191
|
+
headerLayout.setOrientation(LinearLayout.VERTICAL);
|
|
192
|
+
headerLayout.setPadding(horizontalPadding, verticalPadding, horizontalPadding, (int) (8 * density));
|
|
161
193
|
|
|
162
194
|
// Header logo
|
|
163
195
|
if (headerLogo != null && !headerLogo.isEmpty()) {
|
|
@@ -167,7 +199,28 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
167
199
|
logoParams.gravity = Gravity.CENTER_HORIZONTAL;
|
|
168
200
|
logoParams.bottomMargin = (int) (12 * density);
|
|
169
201
|
logoView.setLayoutParams(logoParams);
|
|
170
|
-
|
|
202
|
+
|
|
203
|
+
// Apply corner radius (default 8dp, -1 for circle)
|
|
204
|
+
Float cornerRadius = styleOptions.getHeaderLogoCornerRadius();
|
|
205
|
+
float radiusDp = cornerRadius != null ? cornerRadius : 8f;
|
|
206
|
+
float radiusPx;
|
|
207
|
+
if (radiusDp < 0) {
|
|
208
|
+
// -1 means full circle: radius = half of logo size
|
|
209
|
+
radiusPx = logoSize / 2f;
|
|
210
|
+
} else {
|
|
211
|
+
radiusPx = radiusDp * density;
|
|
212
|
+
}
|
|
213
|
+
if (radiusPx > 0) {
|
|
214
|
+
logoView.setClipToOutline(true);
|
|
215
|
+
logoView.setOutlineProvider(new android.view.ViewOutlineProvider() {
|
|
216
|
+
@Override
|
|
217
|
+
public void getOutline(android.view.View view, android.graphics.Outline outline) {
|
|
218
|
+
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), radiusPx);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
headerLayout.addView(logoView);
|
|
171
224
|
loadImageAsync(logoView, headerLogo);
|
|
172
225
|
}
|
|
173
226
|
|
|
@@ -192,56 +245,80 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
192
245
|
);
|
|
193
246
|
titleParams.bottomMargin = (int) (20 * density);
|
|
194
247
|
titleView.setLayoutParams(titleParams);
|
|
195
|
-
|
|
248
|
+
headerLayout.addView(titleView);
|
|
249
|
+
}
|
|
250
|
+
root.addView(headerLayout);
|
|
251
|
+
|
|
252
|
+
// ScrollView for body content (rows/message only)
|
|
253
|
+
scrollView = new ScrollView(ctx);
|
|
254
|
+
scrollView.setFillViewport(true);
|
|
255
|
+
scrollView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
256
|
+
|
|
257
|
+
bodyLayout = new LinearLayout(ctx);
|
|
258
|
+
bodyLayout.setOrientation(LinearLayout.VERTICAL);
|
|
259
|
+
bodyLayout.setPadding(horizontalPadding, 0, horizontalPadding, verticalPadding);
|
|
260
|
+
|
|
261
|
+
// Message (for message sheet)
|
|
262
|
+
if (isMessageSheet && message != null && !message.isEmpty()) {
|
|
263
|
+
LinearLayout messageContainer = new LinearLayout(ctx);
|
|
264
|
+
messageContainer.setOrientation(LinearLayout.VERTICAL);
|
|
265
|
+
int messagePadding = (int) (16 * density);
|
|
266
|
+
messageContainer.setPadding(messagePadding, messagePadding, messagePadding, messagePadding);
|
|
267
|
+
|
|
268
|
+
ShapeAppearanceModel messageShape = ShapeAppearanceModel.builder()
|
|
269
|
+
.setAllCornerSizes(12 * density)
|
|
270
|
+
.build();
|
|
271
|
+
MaterialShapeDrawable messageBackground = new MaterialShapeDrawable(messageShape);
|
|
272
|
+
int surfaceVariant = MaterialColors.getColor(ctx, com.google.android.material.R.attr.colorSurfaceVariant, 0xFFE7E0EC);
|
|
273
|
+
messageBackground.setFillColor(ColorStateList.valueOf(surfaceVariant));
|
|
274
|
+
messageContainer.setBackground(messageBackground);
|
|
275
|
+
|
|
276
|
+
TextView messageView = new TextView(ctx);
|
|
277
|
+
messageView.setText(message);
|
|
278
|
+
messageView.setLineSpacing(0, 1.2f);
|
|
279
|
+
TextViewCompat.setTextAppearance(messageView, com.google.android.material.R.style.TextAppearance_Material3_BodyLarge);
|
|
280
|
+
if (styleOptions.getMessageColor() != null) {
|
|
281
|
+
messageView.setTextColor(styleOptions.getMessageColor());
|
|
282
|
+
} else {
|
|
283
|
+
int onSurfaceVariantColor = MaterialColors.getColor(ctx, android.R.attr.textColorSecondary, 0xFF49454F);
|
|
284
|
+
messageView.setTextColor(onSurfaceVariantColor);
|
|
285
|
+
}
|
|
286
|
+
if (styleOptions.getMessageFontSize() != null) {
|
|
287
|
+
messageView.setTextSize(TypedValue.COMPLEX_UNIT_SP, styleOptions.getMessageFontSize());
|
|
288
|
+
}
|
|
289
|
+
messageContainer.addView(messageView);
|
|
290
|
+
|
|
291
|
+
LinearLayout.LayoutParams messageParams = new LinearLayout.LayoutParams(
|
|
292
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
293
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
294
|
+
);
|
|
295
|
+
messageParams.bottomMargin = (int) (24 * density);
|
|
296
|
+
messageContainer.setLayoutParams(messageParams);
|
|
297
|
+
bodyLayout.addView(messageContainer);
|
|
196
298
|
}
|
|
197
299
|
|
|
198
300
|
// Rows
|
|
199
|
-
if (rowsJson != null) {
|
|
301
|
+
if (!isMessageSheet && rowsJson != null) {
|
|
200
302
|
try {
|
|
201
303
|
JSONArray rows = new JSONArray(rowsJson);
|
|
202
304
|
for (int i = 0; i < rows.length(); i++) {
|
|
203
305
|
JSONObject row = rows.getJSONObject(i);
|
|
204
306
|
LinearLayout rowLayout = createSheetRow(ctx, row, styleOptions, density, i < rows.length() - 1);
|
|
205
|
-
|
|
307
|
+
bodyLayout.addView(rowLayout);
|
|
206
308
|
}
|
|
207
309
|
} catch (JSONException e) {
|
|
208
310
|
// Handle error
|
|
209
311
|
}
|
|
210
312
|
}
|
|
211
313
|
|
|
212
|
-
scrollView.addView(
|
|
314
|
+
scrollView.addView(bodyLayout);
|
|
213
315
|
root.addView(scrollView);
|
|
214
316
|
|
|
215
|
-
// Count rows for minimum height calculation
|
|
216
|
-
int rowCount = 0;
|
|
217
|
-
if (rowsJson != null) {
|
|
218
|
-
try {
|
|
219
|
-
JSONArray countRows = new JSONArray(rowsJson);
|
|
220
|
-
rowCount = countRows.length();
|
|
221
|
-
} catch (JSONException e) {
|
|
222
|
-
// ignore
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
317
|
// Button container pinned at bottom
|
|
227
|
-
|
|
318
|
+
buttonContainer = new LinearLayout(ctx);
|
|
228
319
|
buttonContainer.setOrientation(LinearLayout.VERTICAL);
|
|
229
320
|
float topSpacing = styleOptions.getContentButtonSpacing() != null ? styleOptions.getContentButtonSpacing() : 12f;
|
|
230
321
|
|
|
231
|
-
// For sheets with ≤4 rows and no explicit spacing, add extra spacing to reach ~50% screen height
|
|
232
|
-
if (rowCount <= 4 && styleOptions.getContentButtonSpacing() == null) {
|
|
233
|
-
int screenHeight = getResources().getDisplayMetrics().heightPixels;
|
|
234
|
-
float targetHeight = screenHeight * 0.5f;
|
|
235
|
-
// Estimate current content height: header + title + rows + buttons
|
|
236
|
-
float estimatedContent = (16 + 8 + 48 + 12 + 20) * density; // drag handle + logo area + title + margins
|
|
237
|
-
estimatedContent += rowCount * 56 * density; // ~56dp per row
|
|
238
|
-
estimatedContent += (48 + 12 + 48 + 4) * density; // buttons + padding
|
|
239
|
-
estimatedContent += topSpacing * density;
|
|
240
|
-
if (targetHeight > estimatedContent) {
|
|
241
|
-
topSpacing += (targetHeight - estimatedContent) / density;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
322
|
buttonContainer.setPadding(horizontalPadding, (int) (topSpacing * density), horizontalPadding, (int) (4 * density));
|
|
246
323
|
|
|
247
324
|
int primaryColor = MaterialColors.getColor(ctx, android.R.attr.colorPrimary, 0xFF6750A4);
|
|
@@ -337,9 +414,63 @@ public class SheetBottomDialogFragment extends BottomSheetDialogFragment {
|
|
|
337
414
|
// Prevent dragging down in fullscreen mode
|
|
338
415
|
behavior.setDraggable(false);
|
|
339
416
|
} else {
|
|
417
|
+
// Dynamic height based on content (min 50%, max 80%), drag down to close
|
|
418
|
+
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
|
|
419
|
+
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
|
420
|
+
bottomSheet.setLayoutParams(layoutParams);
|
|
421
|
+
|
|
340
422
|
behavior.setFitToContents(true);
|
|
341
|
-
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
|
342
423
|
behavior.setSkipCollapsed(true);
|
|
424
|
+
behavior.setHideable(true);
|
|
425
|
+
behavior.setDraggable(true);
|
|
426
|
+
|
|
427
|
+
bottomSheet.post(() -> {
|
|
428
|
+
int screenHeight = getResources().getDisplayMetrics().heightPixels;
|
|
429
|
+
int width = bottomSheet.getWidth() > 0
|
|
430
|
+
? bottomSheet.getWidth()
|
|
431
|
+
: getResources().getDisplayMetrics().widthPixels;
|
|
432
|
+
|
|
433
|
+
int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
|
|
434
|
+
int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
|
435
|
+
|
|
436
|
+
int headerHeight = 0;
|
|
437
|
+
if (headerLayout != null) {
|
|
438
|
+
headerLayout.measure(widthSpec, heightSpec);
|
|
439
|
+
headerHeight = headerLayout.getMeasuredHeight();
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
int bodyHeight = 0;
|
|
443
|
+
if (bodyLayout != null) {
|
|
444
|
+
bodyLayout.measure(widthSpec, heightSpec);
|
|
445
|
+
bodyHeight = bodyLayout.getMeasuredHeight();
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
int buttonHeight = 0;
|
|
449
|
+
if (buttonContainer != null) {
|
|
450
|
+
buttonContainer.measure(widthSpec, heightSpec);
|
|
451
|
+
buttonHeight = buttonContainer.getMeasuredHeight();
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
int minHeight = (int) (screenHeight * 0.5f);
|
|
455
|
+
int maxHeight = (int) (screenHeight * 0.8f);
|
|
456
|
+
int desiredHeight = headerHeight + bodyHeight + buttonHeight;
|
|
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
|
+
}
|
|
466
|
+
|
|
467
|
+
ViewGroup.LayoutParams sheetParams = bottomSheet.getLayoutParams();
|
|
468
|
+
sheetParams.height = desiredHeight;
|
|
469
|
+
bottomSheet.setLayoutParams(sheetParams);
|
|
470
|
+
|
|
471
|
+
behavior.setPeekHeight(desiredHeight);
|
|
472
|
+
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
|
473
|
+
});
|
|
343
474
|
}
|
|
344
475
|
});
|
|
345
476
|
}
|
package/dist/docs.json
CHANGED
|
@@ -167,6 +167,34 @@
|
|
|
167
167
|
"SheetResult"
|
|
168
168
|
],
|
|
169
169
|
"slug": "sheet"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "messageSheet",
|
|
173
|
+
"signature": "(options: MessageSheetOptions) => any",
|
|
174
|
+
"parameters": [
|
|
175
|
+
{
|
|
176
|
+
"name": "options",
|
|
177
|
+
"docs": "- Message sheet configuration options.",
|
|
178
|
+
"type": "MessageSheetOptions"
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
"returns": "any",
|
|
182
|
+
"tags": [
|
|
183
|
+
{
|
|
184
|
+
"name": "param",
|
|
185
|
+
"text": "options - Message sheet configuration options."
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "returns",
|
|
189
|
+
"text": "Whether the user confirmed or cancelled the sheet."
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
"docs": "Show a message sheet dialog with an optional header logo, title, and message.",
|
|
193
|
+
"complexTypes": [
|
|
194
|
+
"MessageSheetOptions",
|
|
195
|
+
"MessageSheetResult"
|
|
196
|
+
],
|
|
197
|
+
"slug": "messagesheet"
|
|
170
198
|
}
|
|
171
199
|
],
|
|
172
200
|
"properties": []
|
|
@@ -591,6 +619,75 @@
|
|
|
591
619
|
"type": "boolean"
|
|
592
620
|
}
|
|
593
621
|
]
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
"name": "MessageSheetOptions",
|
|
625
|
+
"slug": "messagesheetoptions",
|
|
626
|
+
"docs": "",
|
|
627
|
+
"tags": [],
|
|
628
|
+
"methods": [],
|
|
629
|
+
"properties": [
|
|
630
|
+
{
|
|
631
|
+
"name": "headerLogo",
|
|
632
|
+
"tags": [],
|
|
633
|
+
"docs": "Header logo - supports base64 data URL or HTTP/HTTPS URL",
|
|
634
|
+
"complexTypes": [],
|
|
635
|
+
"type": "string | undefined"
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
"name": "title",
|
|
639
|
+
"tags": [],
|
|
640
|
+
"docs": "Sheet title",
|
|
641
|
+
"complexTypes": [],
|
|
642
|
+
"type": "string"
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
"name": "message",
|
|
646
|
+
"tags": [],
|
|
647
|
+
"docs": "Message body displayed in the sheet",
|
|
648
|
+
"complexTypes": [],
|
|
649
|
+
"type": "string"
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
"name": "confirmButtonTitle",
|
|
653
|
+
"tags": [],
|
|
654
|
+
"docs": "Confirm button title",
|
|
655
|
+
"complexTypes": [],
|
|
656
|
+
"type": "string | undefined"
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
"name": "cancelButtonTitle",
|
|
660
|
+
"tags": [],
|
|
661
|
+
"docs": "Cancel button title",
|
|
662
|
+
"complexTypes": [],
|
|
663
|
+
"type": "string | undefined"
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
"name": "mode",
|
|
667
|
+
"tags": [],
|
|
668
|
+
"docs": "Dialog mode",
|
|
669
|
+
"complexTypes": [
|
|
670
|
+
"DialogMode"
|
|
671
|
+
],
|
|
672
|
+
"type": "DialogMode"
|
|
673
|
+
}
|
|
674
|
+
]
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
"name": "MessageSheetResult",
|
|
678
|
+
"slug": "messagesheetresult",
|
|
679
|
+
"docs": "",
|
|
680
|
+
"tags": [],
|
|
681
|
+
"methods": [],
|
|
682
|
+
"properties": [
|
|
683
|
+
{
|
|
684
|
+
"name": "confirmed",
|
|
685
|
+
"tags": [],
|
|
686
|
+
"docs": "True if confirmed, false if cancelled",
|
|
687
|
+
"complexTypes": [],
|
|
688
|
+
"type": "boolean"
|
|
689
|
+
}
|
|
690
|
+
]
|
|
594
691
|
}
|
|
595
692
|
],
|
|
596
693
|
"enums": [],
|
|
@@ -60,6 +60,42 @@ export interface DialogStyleOptions {
|
|
|
60
60
|
* });
|
|
61
61
|
*/
|
|
62
62
|
contentButtonSpacing?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Corner radius for the header logo in sheet dialogs (in dp/pt/px).
|
|
65
|
+
* - Positive number: specific radius (e.g., 12)
|
|
66
|
+
* - 0: square corners (no rounding)
|
|
67
|
+
* - -1: full circle (radius = half of logo size)
|
|
68
|
+
*
|
|
69
|
+
* @default 8
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* // Custom rounded corners (12px)
|
|
73
|
+
* await ExtendedDialog.sheet({
|
|
74
|
+
* title: 'Settings',
|
|
75
|
+
* headerLogo: 'https://example.com/logo.png',
|
|
76
|
+
* headerLogoCornerRadius: 12,
|
|
77
|
+
* rows: [],
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Full circle logo
|
|
82
|
+
* await ExtendedDialog.sheet({
|
|
83
|
+
* title: 'Profile',
|
|
84
|
+
* headerLogo: 'https://example.com/avatar.png',
|
|
85
|
+
* headerLogoCornerRadius: -1,
|
|
86
|
+
* rows: [],
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* // Square logo (no rounding)
|
|
91
|
+
* await ExtendedDialog.sheet({
|
|
92
|
+
* title: 'Document',
|
|
93
|
+
* headerLogo: 'https://example.com/icon.png',
|
|
94
|
+
* headerLogoCornerRadius: 0,
|
|
95
|
+
* rows: [],
|
|
96
|
+
* });
|
|
97
|
+
*/
|
|
98
|
+
headerLogoCornerRadius?: number;
|
|
63
99
|
}
|
|
64
100
|
export interface BaseDialogOptions extends DialogStyleOptions {
|
|
65
101
|
/**
|
|
@@ -243,10 +279,28 @@ export interface SheetOptions extends DialogStyleOptions {
|
|
|
243
279
|
/** Dialog mode */
|
|
244
280
|
mode?: DialogMode;
|
|
245
281
|
}
|
|
282
|
+
export interface MessageSheetOptions extends DialogStyleOptions {
|
|
283
|
+
/** Header logo - supports base64 data URL or HTTP/HTTPS URL */
|
|
284
|
+
headerLogo?: string;
|
|
285
|
+
/** Sheet title */
|
|
286
|
+
title: string;
|
|
287
|
+
/** Message body displayed in the sheet */
|
|
288
|
+
message: string;
|
|
289
|
+
/** Confirm button title */
|
|
290
|
+
confirmButtonTitle?: string;
|
|
291
|
+
/** Cancel button title */
|
|
292
|
+
cancelButtonTitle?: string;
|
|
293
|
+
/** Dialog mode */
|
|
294
|
+
mode?: DialogMode;
|
|
295
|
+
}
|
|
246
296
|
export interface SheetResult {
|
|
247
297
|
/** True if confirmed, false if cancelled */
|
|
248
298
|
confirmed: boolean;
|
|
249
299
|
}
|
|
300
|
+
export interface MessageSheetResult {
|
|
301
|
+
/** True if confirmed, false if cancelled */
|
|
302
|
+
confirmed: boolean;
|
|
303
|
+
}
|
|
250
304
|
export interface ExtendedDialogPlugin {
|
|
251
305
|
/**
|
|
252
306
|
* Show an alert dialog with a single dismiss button.
|
|
@@ -289,4 +343,11 @@ export interface ExtendedDialogPlugin {
|
|
|
289
343
|
* @returns Whether the user confirmed or cancelled the sheet.
|
|
290
344
|
*/
|
|
291
345
|
sheet(options: SheetOptions): Promise<SheetResult>;
|
|
346
|
+
/**
|
|
347
|
+
* Show a message sheet dialog with an optional header logo, title, and message.
|
|
348
|
+
*
|
|
349
|
+
* @param options - Message sheet configuration options.
|
|
350
|
+
* @returns Whether the user confirmed or cancelled the sheet.
|
|
351
|
+
*/
|
|
352
|
+
messageSheet(options: MessageSheetOptions): Promise<MessageSheetResult>;
|
|
292
353
|
}
|