MAUI Android 自定义弹窗
MAUI在Android平台自定义弹窗教程。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmL4cDO1MTN2IzMtgTMyYDM2MzMxkjM4AjMyAjMtcTN0QTO38CX4AjMyAjMvw1N1QDN5czLcd2bsJ2Lc12bj5ycn9Gbi52YuIjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
一、定义一个DialogCustomer.cs
1 public partial class DialogCustomer
2 {
3 public partial Task<bool> CustomerAlertAsync(string title, string subTitle, string confirmMsg = "OK", string cancelMsg = "", string subTitle2 = "", string img = "", string textAlignment = "Center", int imgWidth = 0, int imgHeight = 0);
4 }
View Code
二、在Platforms/Android下定义一个DialogCustorer.cs
1 public partial class DialogCustomer
2 {
3 public partial Task<bool> CustomerAlertAsync(string title, string subTitle, string confirmMsg = "OK", string cancelMsg = "", string subTitle2 = "", string img = "", string textAlignment = "Center", int imgWidth = 0, int imgHeight = 0)
4 {
5 try
6 {
7 var tcs = new TaskCompletionSource<bool>();
8 var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
9 var density = mainDisplayInfo.Density;
10
11 //Activity activity = (Activity)Android.App.Application.Context;
12 //Android.App.Application.Context
13 Activity activity = (Activity)MainActivity.Instance;
14 Display display = activity.WindowManager.DefaultDisplay;
15
16 // 获取Dialog布局
17 Android.Views.View view = LayoutInflater.From(activity).Inflate(Resource.Layout.customerConfirmAlert, null);
18
19 // 获取自定义Dialog布局中的控件
20 var layDialogWrap = view.FindViewById<LinearLayout>(Resource.Id.custom_confirmdialog_wrap);
21
22 Dialog myDialog = new Dialog(activity, Resource.Style.AlertDialogStyle);
23 //设置点击Dialog外部任意区域不能关闭Dialog
24 myDialog.SetCanceledOnTouchOutside(false);
25 //设置自定义弹出框内容
26 myDialog.SetContentView(view);
27
28 if (Device.Idiom == TargetIdiom.Tablet)
29 {
30 layDialogWrap.LayoutParameters = new FrameLayout.LayoutParams((int)(activity.WindowManager.DefaultDisplay.Width * 0.64), ViewGroup.LayoutParams.WrapContent);
31 }
32 else
33 {
34 layDialogWrap.LayoutParameters = new FrameLayout.LayoutParams((int)(activity.WindowManager.DefaultDisplay.Width * 0.94), ViewGroup.LayoutParams.WrapContent);
35 }
36
37 var btnClose = view.FindViewById<Android.Widget.Button>(Resource.Id.custom_confirmdialog_close);
38 btnClose.SetTextColor(GetBlackBtnBackgroundColor());
39 btnClose.Click += (s, e) =>
40 {
41 myDialog.Dismiss();
42 tcs.SetResult(false);
43 };
44
45 //弹出框标题
46 var tvTitle = view.FindViewById<TextView>(Resource.Id.custom_confirmdialog_title);
47 //SetAndroidTextViewFontFamily(tvTitle, true);
48 tvTitle.Text = title;
49 if (string.IsNullOrEmpty(title))
50 {
51 tvTitle.Visibility = ViewStates.Gone;
52 }
53
54 //弹出框副标题
55 var tvSubtitle2 = view.FindViewById<TextView>(Resource.Id.custom_confirmdialog_subtitle2);
56 //SetAndroidTextViewFontFamily(tvSubtitle2, false);
57 tvSubtitle2.Text = subTitle2;
58 if (string.IsNullOrEmpty(subTitle2))
59 {
60 tvSubtitle2.Visibility = ViewStates.Gone;
61 }
62 switch (textAlignment)
63 {
64 case "Left":
65 tvSubtitle2.TextAlignment = Android.Views.TextAlignment.TextStart;
66 tvSubtitle2.Gravity = GravityFlags.Left;
67 break;
68 case "Right":
69 tvSubtitle2.TextAlignment = Android.Views.TextAlignment.TextEnd;
70 tvSubtitle2.Gravity = GravityFlags.Right;
71 break;
72 default:
73 tvSubtitle2.TextAlignment = Android.Views.TextAlignment.Center;
74 break;
75 }
76
77 var imgView = view.FindViewById<ImageView>(Resource.Id.custom_confirmdialog_img);
78 if (string.IsNullOrEmpty(img))
79 {
80 imgView.Visibility = ViewStates.Gone;
81 }
82 else
83 {
84 setimg(activity, imgView, img);
85 if (imgWidth > 0 && imgHeight > 0)
86 {
87 var imgX = (display.Width - 16 * (int)density - imgWidth * (int)density) / 2;
88 if (Device.Idiom == TargetIdiom.Tablet)
89 {
90 imgX = (int)((display.Width * 0.64) - 16 * (int)density - imgWidth * (int)density) / 2;
91 }
92
93 imgView.LayoutParameters = new LinearLayout.LayoutParams(imgWidth * (int)density, imgHeight * (int)density);
94 var imagelp = (LinearLayout.LayoutParams)imgView.LayoutParameters;
95 imagelp.SetMargins(imgX, 0, 22, 24 * (int)density);
96 }
97
98 //imgView.SetImageBitmap(imgBitmap);
99 //imgView.SetImageResource(Resource.Drawable.GW_close_eye);
100 //imgView.SetImageURI(Android.Net.Uri.FromFile(new Java.IO.File(img)));
101 }
102
103 //弹出框副标题
104 var tvSubtitle = view.FindViewById<TextView>(Resource.Id.custom_confirmdialog_subtitle);
105 //SetAndroidTextViewFontFamily(tvSubtitle, false);
106 tvSubtitle.Text = subTitle;
107 if (string.IsNullOrEmpty(subTitle))
108 {
109 tvSubtitle.Visibility = ViewStates.Gone;
110 }
111 switch (textAlignment)
112 {
113 case "Left":
114 tvSubtitle.TextAlignment = Android.Views.TextAlignment.TextStart;
115 tvSubtitle.Gravity = GravityFlags.Left;
116 break;
117 case "Right":
118 tvSubtitle.TextAlignment = Android.Views.TextAlignment.TextEnd;
119 tvSubtitle.Gravity = GravityFlags.Right;
120 break;
121 default:
122 tvSubtitle.TextAlignment = Android.Views.TextAlignment.Center;
123 break;
124 }
125
126
127 //display.Height-
128 var tvScrollView = view.FindViewById<MaxHeightScrollView>(Resource.Id.custom_confirmdialog_scroll);
129 tvScrollView.maxHeight = display.Height - (tvTitle.LineHeight + 300) * 2;
130
131 //确定按钮
132 var btnOk = view.FindViewById<Android.Widget.Button>(Resource.Id.custom_confirmdialog_okbtn);
133 SetBlackBtnBg(btnOk);
134 btnOk.Text = confirmMsg == "OK" ? AppLanguage.OK : confirmMsg;
135 btnOk.Click += (s, e) =>
136 {
137 myDialog.Dismiss();
138 tcs.SetResult(true);
139 };
140
141 //取消按键
142 var btnCancel = (Android.Widget.Button)view.FindViewById(Resource.Id.custom_confirmdialog_canclebtn);
143 SetWhiteBtnBg(btnCancel);
144 btnCancel.Text = cancelMsg;
145 btnCancel.Click += (s, e) =>
146 {
147 myDialog.Dismiss();
148 tcs.SetResult(false);
149 };
150
151 var btnComfirm = view.FindViewById<Android.Widget.Button>(Resource.Id.custom_confirmdialog_comfirmbtn);
152 SetBlackBtnBg(btnComfirm);
153 btnComfirm.Text = confirmMsg == "OK" ? AppLanguage.OK : confirmMsg;
154 btnComfirm.Click += (s, e) =>
155 {
156 myDialog.Dismiss();
157 tcs.SetResult(true);
158 };
159
160 if (string.IsNullOrEmpty(cancelMsg))
161 {
162 btnOk.Visibility = ViewStates.Visible;
163 btnCancel.Visibility = ViewStates.Gone;
164 btnComfirm.Visibility = ViewStates.Gone;
165 }
166 else
167 {
168 btnOk.Visibility = ViewStates.Gone;
169 btnCancel.Visibility = ViewStates.Visible;
170 btnComfirm.Visibility = ViewStates.Visible;
171 }
172
173 //显示弹出框
174 myDialog.Show();
175
176 return tcs.Task;
177 }
178 catch (Exception ex)
179 {
180 return null;
181 }
182 }
183
184 private async void setimg(Activity activity, ImageView imageView, string imgUrl)
185 {
186 FileImageSource fileImageSource = (FileImageSource)ImageSource.FromFile(imgUrl);
187 var imgBitmap = await ImageHelper.GetBitmapFromImageSourceAsync(fileImageSource, activity);
188 imageView.SetImageBitmap(imgBitmap);
189 }
190
191 private void SetAndroidTextViewFontFamily(Android.Widget.TextView textView, bool isBlod = false, AlertElementFontStyle alertElementFontStyle = AlertElementFontStyle.Normol)
192 {
193 //var context = Android.App.Application.Context;
194 var context = MainActivity.Instance;
195 AssetManager assetManager = context.Assets;
196 Typeface face = null;
197 if (isBlod)
198 {
199 face = Typeface.CreateFromAsset(assetManager, "SFProDisplay-Bold.ttf");
200 }
201 else
202 {
203 face = Typeface.CreateFromAsset(assetManager, "SFProDisplay-Regular.ttf");
204 switch (alertElementFontStyle)
205 {
206 case AlertElementFontStyle.Normol:
207 face = Typeface.CreateFromAsset(assetManager, "SFProDisplay-Regular.ttf");
208 break;
209 case AlertElementFontStyle.Bold:
210 face = Typeface.CreateFromAsset(assetManager, "SFProDisplay-Bold.ttf");
211 break;
212 case AlertElementFontStyle.Italic:
213 face = Typeface.Create(Typeface.SansSerif, TypefaceStyle.Italic);
214 break;
215 default:
216 break;
217 }
218 }
219 textView.Typeface = face;
220 }
221
222 private void SetAndroidButtonFontFamily(Android.Widget.Button button, bool isBlod = false)
223 {
224 //var context = Android.App.Application.Context;
225 var context = MainActivity.Instance;
226 AssetManager assetManager = context.Assets;
227 Typeface face = null;
228 if (isBlod)
229 {
230 face = Typeface.CreateFromAsset(assetManager, "SFProDisplay-Bold.ttf");
231 }
232 else
233 {
234 face = Typeface.CreateFromAsset(assetManager, "SFProDisplay-Regular.ttf");
235 }
236 button.Typeface = face;
237 }
238
239 //private SpannableString GetHigHLightSpannableString(PartColorText[] partColorTexts, string text)
240 //{
241 // var spannableString = new SpannableString(text);
242 // foreach (var partColorText in partColorTexts)
243 // {
244 // //1. Method1
245 // //Java.Util.Regex.Pattern pattern = Java.Util.Regex.Pattern.Compile(partColorText.AlertText);
246 // //Matcher matcher = pattern.Matcher(text);
247 // //while (matcher.Find())
248 // //{
249 // // Android.Text.Style.ForegroundColorSpan span = new Android.Text.Style.ForegroundColorSpan(Xamarin.Forms.Color.FromHex(partColorText.AlertColor).ToAndroid());
250 // // spannableString.SetSpan(span, matcher.Start() - 0, matcher.End() + 0, SpanTypes.ExclusiveExclusive);
251 // //}
252 // //1. Method2
253 // var span = new Android.Text.Style.ForegroundColorSpan(Xamarin.Forms.Color.FromHex(partColorText.AlertColor).ToAndroid());
254 // spannableString.SetSpan(span, partColorText.Index, partColorText.Index + partColorText.AlertText.Length, SpanTypes.ExclusiveExclusive);
255 // }
256 // return spannableString;
257 //}
258
259 private Android.Graphics.Color GetBlackBtnBackgroundColor()
260 {
261
262 return Android.Graphics.Color.Rgb(254, 254, 254);
263 }
264
265 private void SetBlackBtnBg(Android.Widget.Button button)
266 {
267
268 //button.SetBackgroundResource(Resource.Drawable.setbar_black_btn_bg);
269 //button.SetBackgroundColor(GetBlackBtnBackgroundColor());
270 }
271
272 private void SetWhiteBtnBg(Android.Widget.Button button)
273 {
274
275 //button.SetBackgroundResource(Resource.Drawable.setbar_white_btn_bg);
276 //button.SetBackgroundColor(GetBlackBtnBackgroundColor());
277 }
278
279 private Android.Widget.Button CreateBlackBtn(Activity activity)
280 {
281
282 return (Android.Widget.Button)LayoutInflater.From(activity).Inflate(Resource.Layout.customerButtonBlack, null);
283
284 }
285
286 private Android.Widget.Button CreateWhiteBtn(Activity activity)
287 {
288 return (Android.Widget.Button)LayoutInflater.From(activity).Inflate(Resource.Layout.customerButtonWhite, null);
289 }
290
291 }
292
293 public static class ImageHelper
294 {
295 public static IImageSourceHandler GetHandler(this ImageSource source)
296 {
297 //Image source handler to return
298 IImageSourceHandler returnValue = null;
299 //check the specific source type and return the correct image source handler
300 if (source is UriImageSource)
301 {
302 returnValue = new ImageLoaderSourceHandler();
303 }
304 else if (source is FileImageSource)
305 {
306 returnValue = new FileImageSourceHandler();
307 }
308 else if (source is StreamImageSource)
309 {
310 returnValue = new StreamImagesourceHandler();
311 }
312 return returnValue;
313 }
314
315 public static async Task<Bitmap> GetBitmapFromImageSourceAsync(ImageSource source, Context context)
316 {
317 var handler = GetHandler(source);
318 var returnValue = (Bitmap)null;
319 returnValue = await handler.LoadImageAsync(source, context);
320 return returnValue;
321 }
322 }
323
324 public class BrandColorHelper
325 {
326
327 public const string POWERWORKS = "POWERWORKS";
328 public const string GREENWORKS = "GREENWORKS";
329 public const string CRAMER = "CRAMER";
330 public const string ZTR = "ZTR";
331 public const string DEVELOPER = "DEVELOPER";
332
333 public static string GetBrand()
334 {
335 #if GREENWORKS
336 return GREENWORKS;
337 #elif POWERWORKS
338 return POWERWORKS;
339 #elif CRAMER
340 return CRAMER;
341 #elif ZTR
342 return ZTR;
343 #else //DEVELOPER
344 return DEVELOPER;
345 #endif
346 }
347 }
348
349 public class MaxHeightScrollView : Android.Widget.ScrollView
350 {
351 public int maxHeight;
352 protected Context _context;
353 public MaxHeightScrollView(Context context) : base(context)
354 {
355 //base(context, null);
356 }
357 public MaxHeightScrollView(Context context, Android.Util.IAttributeSet attrs) : base(context, attrs)
358 {
359 _context = context;
360 //base.(context, attrs, defStyleAttr);
361 initialize(context, attrs);
362 }
363 public MaxHeightScrollView(Context context, Android.Util.IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
364 {
365 _context = context;
366 //base.(context, attrs, defStyleAttr);
367 initialize(context, attrs);
368 }
369
370 private void initialize(Context context, Android.Util.IAttributeSet attrs)
371 {
372 Android.Content.Res.TypedArray typedArray = context.ObtainStyledAttributes(attrs, Resource.Styleable.MaxHeightScrollView);
373 maxHeight = typedArray.GetLayoutDimension(Resource.Styleable.MaxHeightScrollView_maxHeight, maxHeight);
374 typedArray.Recycle();
375 }
376
377 protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
378 {
379 try
380 {
381 //Display display = ((Activity)_context).WindowManager.DefaultDisplay;
382 //heightMeasureSpec = display.Height - 200;
383
384 heightMeasureSpec = MeasureSpec.MakeMeasureSpec(maxHeight, MeasureSpecMode.AtMost);
385 }
386 catch (Exception ex)
387 {
388
389 }
390 base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
391 }
392
393 }
View Code
三、在Platforms/Android/Resources/layout下添加一个customerConfirmAlert.xml
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:id="@+id/custom_confirmdialog_wrap"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 android:orientation="vertical"
6 android:layout_width="match_parent"
7 android:layout_height="wrap_content"
8 android:background="@drawable/setbar_warp_bg">
9 <LinearLayout
10 android:layout_width="match_parent"
11 android:layout_height="50dp"
12 android:orientation="horizontal">
13 <View
14 android:layout_width="wrap_content"
15 android:layout_height="50dp"
16 android:layout_weight="1"/>
17 <Button
18 android:id="@+id/custom_confirmdialog_close"
19 android:layout_width="22dp"
20 android:layout_height="22dp"
21 android:layout_weight="0"
22 android:layout_marginTop="20dp"
23 android:layout_marginRight="16dp"
24 android:background="@drawable/gw_alert_close"/>
25 </LinearLayout>
26 <TextView
27 android:id="@+id/custom_confirmdialog_title"
28 android:layout_width="match_parent"
29 android:layout_height="wrap_content"
30 android:layout_marginTop="20dp"
31 android:layout_marginBottom="32dp"
32 android:layout_margin="22dp"
33 android:gravity="center"
34 android:textSize="24sp"
35 android:textColor="@color/black"
36 android:textStyle="bold"
37 android:text="@string/pin_title"/>
38 <GLBMaui.DenpendencyServices.MaxHeightScrollView
39 android:id="@+id/custom_confirmdialog_scroll"
40 android:layout_width="match_parent"
41 android:layout_height="wrap_content"
42 android:fillViewport ="true"
43 android:overScrollMode="never"
44 android:scrollbars="vertical"
45 app:maxHeight="300dp"
46 >
47 <LinearLayout
48 android:layout_width="match_parent"
49 android:layout_height="wrap_content"
50 android:orientation="vertical">
51 <TextView
52 android:id="@+id/custom_confirmdialog_subtitle2"
53 android:layout_width="match_parent"
54 android:layout_height="wrap_content"
55 android:layout_marginLeft="12dp"
56 android:layout_marginRight="12dp"
57 android:layout_marginTop="0dp"
58 android:layout_marginBottom="2dp"
59 android:gravity="center"
60 android:textSize="16sp"
61 android:textColor="@color/black"
62 android:text="@string/pin_subtitle"/>
63 <ImageView
64 android:id="@+id/custom_confirmdialog_img"
65 android:layout_width="wrap_content"
66 android:layout_height="wrap_content"
67 android:layout_marginBottom="24dp"
68 android:layout_gravity="center"
69 android:contentDescription=""
70 android:src="@drawable/gw_open_eye"/>
71 <TextView
72 android:id="@+id/custom_confirmdialog_subtitle"
73 android:layout_width="match_parent"
74 android:layout_height="wrap_content"
75 android:layout_marginLeft="12dp"
76 android:layout_marginRight="12dp"
77 android:layout_marginTop="0dp"
78 android:layout_marginBottom="34dp"
79 android:gravity="center"
80 android:textSize="16sp"
81 android:textColor="@color/black"
82 android:text="@string/pin_tips"/>
83 </LinearLayout>
84 </GLBMaui.DenpendencyServices.MaxHeightScrollView>
85
86 <Button
87 android:id="@+id/custom_confirmdialog_okbtn"
88 android:layout_width="match_parent"
89 android:layout_height="match_parent"
90 android:height="55dp"
91 android:layout_marginRight="12dp"
92 android:layout_marginLeft="12dp"
93 android:layout_marginBottom="24dp"
94 android:gravity="center"
95 android:background="@drawable/setbar_black_btn_bg"
96 android:textColor="@android:color/white"
97 android:textSize="16sp"
98 android:textStyle="normal"
99 />
100 <LinearLayout
101 android:layout_width="match_parent"
102 android:layout_height="match_parent"
103 android:orientation="horizontal">
104 <Button
105 android:id="@+id/custom_confirmdialog_canclebtn"
106 android:layout_width="wrap_content"
107 android:layout_height="match_parent"
108 android:layout_weight="1"
109 android:height="55dp"
110 android:layout_marginRight="6dp"
111 android:layout_marginLeft="12dp"
112 android:layout_marginBottom="24dp"
113 android:gravity="center"
114 android:background="@drawable/setbar_white_btn_bg"
115 android:backgroundTint="#FFFFFF"
116 android:textColor="@color/color_btn_black"
117 android:textSize="16sp"
118 android:textStyle="normal"
119 />
120 <Button
121 android:id="@+id/custom_confirmdialog_comfirmbtn"
122 android:layout_width="wrap_content"
123 android:layout_height="match_parent"
124 android:layout_weight="1"
125 android:height="55dp"
126 android:layout_marginRight="12dp"
127 android:layout_marginLeft="6dp"
128 android:layout_marginBottom="24dp"
129 android:gravity="center"
130 android:background="@drawable/setbar_black_btn_bg"
131 android:textColor="@android:color/white"
132 android:textSize="16sp"
133 android:textStyle="normal"
134 />
135 </LinearLayout>
136
137
138 </LinearLayout>
View Code
四、在页面上使用这个弹窗
1 MainThread.BeginInvokeOnMainThread(async () =>
2 {
3 var res = await new DialogCustomer().CustomerAlertAsync("title", "在 .NET 多平台应用 UI (.NET MAUI) 不提供任何用于访问特定平台 API 的 API 的情况下,可以编写自己的代码来访问所需的平台 API。 这需要了解 Apple 的 iOS 和 MacCatalyst API、 Google 的 Android API 和 Microsoft 的 Windows 应用 SDK API。在 .NET 多平台应用 UI (.NET MAUI) 不提供任何用于访问特定平台 API 的 API 的情况下,可以编写自己的代码来访问所需的平台 API。 这需要了解 Apple 的 iOS 和 MacCatalyst API、 Google 的 Android API 和 Microsoft 的 Windows 应用 SDK API。在 .NET 多平台应用 UI (.NET MAUI) 不提供任何用于访问特定平台 API 的 API 的情况下,可以编写自己的代码来访问所需的平台 API。 这需要了解 Apple 的 iOS 和 MacCatalyst API、 Google 的 Android API 和 Microsoft 的 Windows 应用 SDK API。", confirmMsg: "OK", cancelMsg: "cancel", img: "accept.png");
4 });
View Code
参考GitHub URL:https://github.com/zuimengaitianya/GLBMaui,喜欢的给个star。后续将继续完善iOS平台代码。