MAUI正式版发布半年了,Net 7也发布了,再次学习MAUI跨平台开发。UI类型选择Blazor,因为Html的生态圈比Xaml好太多了,能用Html解决的,就不要用Xaml。Blazor既可以开发网页客户端,又可以开发移动客户端,一个技术栈可以涵盖前后端,多平台,做小型工具软件不错。
开发环境Win10,Visual Studio 17.5.0 Preview 1.0,安卓模拟器Pixle 5 - API 30(Android 11.0 - API 30)。
新建项目
新建MAUI Blazor项目,选择位置D:\Software\gitee\mauiblazorapp。
选择Net 7.0框架。目标平台仅保留安卓和Windows。
D:\Software\gitee\mauiblazorapp\MaBlaApp\MaBlaApp.csproj
<TargetFrameworks>net7.0-android</TargetFrameworks>
<!--<TargetFrameworks>net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>-->
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
Shell布局
MAUI Blazor项目是网站布局,但是手机APP最常见的布局还是微信这种,Xamarin Forms项目可以直接选择Shell模板,MAUI Xaml项目也可以,但是MAUI Blazor项目不行,这真是一大遗憾。
幸好微软提供了一个移动APP布局的DEMO,这个项目是专门为了展示MAUI跨平台开发特性而设计的,有XAML和Blazor两个版本。
https://github.com/microsoft/dotnet-podcasts
打开其中的MAUI Blazor项目。
D:\Software\Test\dotnet-podcasts-main\src\MobileBlazor\mauiapp\NetPodsMauiBlazor.csproj
参照着DEMO的MainLayout.razor和css文件修改。对于不熟悉Html和css的.Net开发者而言,也是非常头大的工作。希望MAUI Blazor也能提供Shell布局的模板。
D:\Software\Test\dotnet-podcasts-main\src\Web\Pages\Shared\MainLayout.razor
D:\Software\Test\dotnet-podcasts-main\src\Web\Pages\Shared\MainLayout.razor.css
官网DEMO采用grid布局实现了Shell布局效果。这个其实可以参考Xaml的Grid布局或者StackLayout布局去理解,把一个窗口横着分几块,每一块里边再竖着分几块。手机小尺寸页面的情况下,横向分4块。PC大尺寸页面的情况下,横向分3块。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
.page { background-color: var(--c-neutral-grey1); display: grid; grid-template-areas: "header" "main-view" "player-bar" "nav-bar"; grid-template-columns: 1fr; grid-template-rows: 56px 1fr auto auto; position: relative; height: 100%; width: 100%; } @media screen and (min-width: 992px) { .page { grid-template-areas: "header main-view" "nav-bar main-view" "player-bar player-bar"; grid-template-columns: auto 1fr; grid-template-rows: 142px 1fr auto; } |
我写的DEMO很简单,手机小尺寸页面的情况下,横向分2块。PC大尺寸页面的情况下,横向分1块,相比dotnet-podcasts项目没有header和player-bar播放栏。简而言之,就只有nav-bar导航栏和main-view主视图,小尺寸页面上下排列,大尺寸页面左右排列。
D:\Software\gitee\mauiblazorapp\MaBlaApp\Shared\MainLayout.razor.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
.page { background-color: var(--c-neutral-grey1); display: grid; grid-template-areas: "main-view" "nav-bar"; grid-template-columns: 1fr; grid-template-rows: 1fr auto; position: relative; height: 100%; width: 100%; } @media screen and (min-width: 992px) { .page { grid-template-areas: "nav-bar main-view"; grid-template-columns: auto 1fr; grid-template-rows: 1fr; } |
然后再借鉴dotnet-podcasts项目的菜单样式。
D:\Software\Test\dotnet-podcasts-main\src\Web\Pages\Shared\NavMenu.razor
D:\Software\Test\dotnet-podcasts-main\src\Web\Pages\Shared\NavMenu.razor.css
1 2 3 4 |
.navbarApp__wrapper { display: grid; grid-template-columns: repeat(5, 1fr); } |
我写的DEMO减少为3个按钮
1 2 3 4 |
.navbarApp__wrapper { display: grid; grid-template-columns: repeat(3, 1fr); } |
3个按钮就是Blazor项目模板自带的
D:\Software\gitee\mauiblazorapp\MaBlaApp\Shared\NavMenu.razor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<div class="navbarApp"> <nav class="navbarApp__wrapper"> <div class="navbarApp-item"> <NavLink class="navbarApp-link" href="" Match="NavLinkMatch.All"> <span class="navbarApp-linkIcon oi oi-home" aria-hidden="true"></span> <span class="navbarApp-linkLabel">Home</span> </NavLink> </div> <div class="navbarApp-item"> <NavLink class="navbarApp-link" href="counter"> <span class="navbarApp-linkIcon oi oi-plus" aria-hidden="true"></span> <span class="navbarApp-linkLabel">Counter</span> </NavLink> </div> <div class="navbarApp-item"> <NavLink class="navbarApp-link" href="fetchdata"> <span class="navbarApp-linkIcon oi oi-list-rich" aria-hidden="true"></span> <span class="navbarApp-linkLabel">Fetch data</span> </NavLink> </div> </nav> </div> @code { } |
把dotnet-podcasts项目的字体也搬过来
D:\Software\Test\dotnet-podcasts-main\src\Web\Components\wwwroot\css\fonts
放在wwwroot\css\fonts
D:\Software\gitee\mauiblazorapp\MaBlaApp\wwwroot\css\fonts
照搬dotnet-podcasts项目的字体、颜色定义
D:\Software\Test\dotnet-podcasts-main\src\Web\Components\wwwroot\css\styles.css
放在app.css里边
D:\Software\gitee\mauiblazorapp\MaBlaApp\wwwroot\css\app.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
@font-face { font-display: swap; font-family: "Segoe UI Light"; font-style: normal; font-weight: 100; src: url("fonts/SegoeUILight.woff") format("woff"); } @font-face { font-display: swap; font-family: "Segoe UI Semilight"; font-style: normal; font-weight: 300; src: url("fonts/SegoeUISemilight.woff") format("woff"); } @font-face { font-display: swap; font-family: "Segoe UI"; font-style: normal; font-weight: 400; src: url("fonts/SegoeUI.woff") format("woff"); } @font-face { font-display: swap; font-family: "Segoe UI Semibold"; font-style: normal; font-weight: 600; src: url("fonts/SegoeUISemibold.woff") format("woff"); } @font-face { font-display: swap; font-family: "Segoe UI Bold"; font-style: normal; font-weight: 700; src: url("fonts/SegoeUIBold.woff") format("woff"); } body { --c-primary: #c00cc0; --c-primary-dark: #8b0995; --c-primary-light: #dd0eb3; --c-primary-xlight: #fcf2f7; --c-primary-xxlight: #fcf2f4; --c-secondary: #e10890; --c-neutral-black: #000000; --c-neutral-dark: #1f1f1f; --c-neutral-grey1: #faf9f8; --c-neutral-grey2: #f3f2f1; --c-neutral-grey3: #edebe9; --c-neutral-grey4: #d2d0ce; --c-neutral-grey5: #c8c6c4; --c-neutral-grey6: #a19f9d; --c-neutral-grey7: #605e5c; --c-neutral-grey8: #3b3a39; --c-neutral-grey9: #323130; --c-neutral-white: #ffffff; --c-neutral-white-featured: #ffffff; --c-neutral-white-complementary: #ffffff; --c-player-range: #605e5c; --c-waves-image: #f3f2f1; --c-searchbar: transparent; --c-switch: #605e5c; --c-switch-dark: #1f1f1f; --c-category: #f3f2f1; --gradient-primary-color: #c00cc0; --gradient-secondary-color: #e10890; --gradient-final: radial-gradient( 101.22% 790.99% at 0% 3.41%, #c00cc0 0%, #e10890 100% ); --gradient-splash: linear-gradient(114.18deg, #bf26f5 0%, #e2068c 100%); --ff-light: "Segoe UI Light"; --ff-semilight: "Segoe UI Semilight"; --ff-regular: "Segoe UI"; --ff-semibold: "Segoe UI Semibold"; --ff-bold: "Segoe UI Bold"; --headlines-h1-fs: 90px; --headlines-h1-lh: 96px; --headlines-h2-fs: 64px; --headlines-h2-lh: 72px; --headlines-h3-fs: 48px; --headlines-h3-lh: 56px; --headlines-h4-fs: 36px; --headlines-h4-lh: 44px; --headlines-h5-fs: 32px; --headlines-h5-lh: 40px; --headlines-h6-fs: 24px; --headlines-h6-lh: 36px; --subheadings-s1-fs: 36px; --subheadings-s1-lh: 44px; --subheadings-s2-fs: 32px; --subheadings-s2-lh: 42px; --subheadings-s3-fs: 24px; --subheadings-s3-lh: 40px; --subheadings-s4-fs: 22px; --subheadings-s4-lh: 32px; --subheadings-s5-fs: 20px; --subheadings-s5-lh: 30px; --subheadings-s6-fs: 18px; --subheadings-s6-lh: 28px; --text-xxl-fs: 24px; --text-xxl-lh: 32px; --text-xl-fs: 20px; --text-xl-lh: 30px; --text-l-fs: 18px; --text-l-lh: 28px; --text-m-fs: 16px; --text-m-lh: 24px; --text-s-fs: 14px; --text-s-lh: 22px; --text-xs-fs: 12px; --text-xs-lh: 18px; --link-xl-fs: 20px; --link-xl-lh: 30px; --link-l-fs: 18px; --link-l-lh: 28px; --link-m-fs: 16px; --link-m-lh: 24px; --link-s-fs: 14px; --link-s-lh: 22px; --input-fs: 15px; --input-lh: 24px; --box-shadow-s: 0 1px 4px rgba(0, 0, 0, 0.15), 0 1px 1px rgba(0, 0, 0, 0.05); --box-shadow-m: 0 6px 12px rgba(0, 0, 0, 0.1), 0 1px 4px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.05); --box-shadow-l: 0 10px 24px rgba(0, 0, 0, 0.08), 0 12px 16px rgba(0, 0, 0, 0.08), 0 4px 8px rgba(0, 0, 0, 0.03); --box-shadow-xl: 0 30px 48px rgba(0, 0, 0, 0.16), 0 8px 30px rgba(0, 0, 0, 0.14), 0 8px 10px rgba(0, 0, 0, 0.1), 0 4px 12px -10px rgba(0, 0, 0, 0.5); } html, body, #app, .page { height: 100%; } |
测试效果
在Windows平台跑一下,宽屏,竖屏效果都对了
DEMO代码地址:https://gitee.com/woodsun/mauiblazorapp
来源地址:https://www.cnblogs.com/sunnytrudeau/tag/MAUI/