MAUI Android 自定义弹窗
MAUI Android 自定义弹窗
MAUI在Android平台自定义弹窗教程。
一、定义一个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 }
二、在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 }
三、在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>
四、在页面上使用这个弹窗
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 });
参考GitHub URL:https://github.com/zuimengaitianya/GLBMaui,喜欢的给个star。后续将继续完善iOS平台代码。