Alphabitz — 项目 A

Alphabitz — 项目 A

Alphabitz 系列的第一个条目将是一个简单的算术应用程序,它通过非常简单的 UI 执行各种单位转换。这就像计算器应用程序的想法,但有更多在任何项目中有用的真实世界场景。与本系列中的每个应用程序一样,本教程的目标是跨多个平台创建相同的应用程序,以用作您自己项目的起点。

笔记: 本教程假设您对声明性 UI 语法和 MVVM 设计模式有一些基本的了解。如果这是您的第一次应用程序开发之旅,您可能想查看一些关于 Swift、SwiftUI、Kotlin、Jetpack Compose 和 Svelte 的入门级教程和文章 雷·温德利希 或者 堆栈溢出 .

所有项目的所有源代码都可以在这里下载: 算术

研究阶段

我喜欢将我的研究分为两个不同的部分,后端/数据部分和前端/ui 部分。在这个阶段,我正在做更多的高级方法来查看我需要什么或者我将如何使用可以在每个平台上共享的某些部分。对于这个项目,我提出了以下研究项目:

  1. 对于后端逻辑,我想确保我使用的类别在所有三个平台上都可用。查看一些可用的框架或内置库,我发现以下 6 个可以使用的常见类别: 长度,温度,⚖️质量,体积,☁️压力和⚡能量 .
  2. 对于前端,我需要设置一些基本组件(颜色、字体和图标),这些组件将为每个应用程序提供相似的外观和“感觉”,同时仍然遵循每个平台的最佳实践。为了简单起见,我将使用每个平台的默认值(因此 iOS 上的 SF Font/Symbols、Android 上的 Roboto/Material 和 Web 上的 Serif/FontAwesome)。对于实际的 UI,我将使用一个简单的 UI,主屏幕将每个选项显示为卡片,而转换屏幕仅包含一个输入字段和转换结果列表。

这种类型的研究帮助我了解每个项目的实际可行性以及在每个平台上需要付出什么努力。研究阶段通常是想出应用程序名称的好时机,为此我解决了这个问题 算术 .

项目设置

在开始设计之前,我将在线和离线设置我的项目文件夹。我会用 GitHub 为了托管我的项目,所以我在本地创建了一个初始项目文件夹,添加一个简单的 README 文件以开始并在线同步文件夹。我对这些类型的项目使用以下文件夹结构,因为我也可以同步 在工作时为每个文件夹创建时间跟踪器。

 -- 算术  
 ---- 自述文件  
 -  -  安卓  
 -  -  设计  
 ---- IOS  
 ---- 网络

设计阶段

我有点遵循 原子设计 过程与敏捷开发实践相结合,迭代每个阶段,直到我得到一个我满意的产品。对于设计过程,我将从保真度最低的设计类型(线框)开始,然后靠近高保真类型的设计(原型),直到我有足够的项目开始开发。我目前正在使用 草图 对于我的大部分设计工作。

低保真(线框)

由于我是移动优先类型的开发人员,我的设计也从移动端开始。我也更熟悉 iOS 端,所以我将从 iOS 应用程序线框开始,然后将其用作其他应用程序的蓝图。线框真的很简单,只有两个屏幕;类别视图(主屏幕)和转换器视图(辅助屏幕)。对于类别视图,我认为将类别显示为类似卡片的项目将使我能够为每个类别使用相似的颜色和图标,从而使应用程序具有更统一的外观。对于转换器视图,再次保持简单,它可以是用于输入值的文本字段,然后是显示不同转换值的表。对于网络,我知道这可能会有所改变,因为只有一个值的表格在大屏幕上会有很多空白空间。现在线框已经完成,所以我可以继续为设计添加更多细节。

Wireframe

中保真(样机)

为了使设计与每个平台上可用的内容保持一致,我喜欢从每个平台的默认 UI 工具包开始,然后在需要的地方添加/调整设计。同样,从 iOS 开始,我从中获取当前的 iOS Sketch 库 这里 并从添加导航屏幕开始,这将为我提供我的类别和转换器视图模板所有设置。我删除了一些带有 SF 符号图标的卡片形状以了解类别并稍微修改表格视图以查看转换结果的外观。

iOS Mock up

这也让我有机会开始将一些颜色与每个类别相关联,我可以在每个平台上复制这些颜色,以使应用程序具有更统一的外观。

然后我跳到 Android 端并获取当前的 Material Design 模板 这里 并做与 iOS 设计相同的事情。这一次有一些不同,比如卡片是如何使用材料设计指南显示的,但它是一个相当快的过程来获得与 iOS 应用程序相同的 UI 布局。

Android mock up

Web App 需要的最后一个线框,由于我采用了这种移动优先的方法,我知道我希望它具有与类别项的卡片类似的布局。这个区域对我来说还是有点新,但我知道我会使用 TailwindCSS 作为颜色,所以我可以使用 这个 颜色和图标的草图库。我将为小型和大型布局创建一些简单的占位符,并且模型都已完成。

Web mock up

设计交接

一旦我在模型中有足够的“设计”项目可以用来开始编码,我将用一些有时被忽略的小额外内容来结束设计过程。首先是应用程序图标,如果您现在有足够的能力创建它,那么为不同的应用程序生成所有资产是个好主意。我没有为这些项目做任何超级花哨的事情,所有图标都将包含一个简单的图标 符号图标 图书馆和我公司品牌的颜色。有各种各样的应用程序和工具包可用于生成应用程序图标,因此无需列出去哪里执行此操作,我建议确保您为每个平台生成正确类型的资产(我喜欢使用模板从 应用像素

  1. iOS 在资产目录中使用各种尺寸,一些工具会生成所有尺寸或仅生成几个尺寸,您必须找到/匹配不同的尺寸(因为有些与其他尺寸相同,只是名称不同)
  2. Android 使用自适应图标,因此对于不同的设备类型它可以是动态的。大多数工具会生成这两个层,并且使用 Android Studio 中的 Asset Studio 允许您将层分配给 App Icon。
  3. Web 将需要一个网站图标,以及移动浏览器所需的图像。同样,大多数工具都会为您生成所有这些尺寸,只需确保在准备好时将它们添加到正确的文件夹中。

发展阶段

与设计阶段类似,我将使用原子设计与敏捷开发相结合来迭代每个应用程序的开发。我还将从 iOS 应用程序开始,再次因为它是我的强项,并且可以作为其他应用程序的蓝图。

iOS 应用程序

最低要求:Xcode 13 和 Swift 5

设置项目相当简单,这里无需赘述,只需确保选择 迅速 SwiftUI 作为语言和框架选项。在项目结构中,我还取消选中 iPad 框,现在这将是 iPhone 唯一类型的项目。我经常使用模拟器进行测试,所以虽然没有提到,但我建议经常构建以验证更改是否在设备上运行,而不仅仅是预览窗口。

打开项目后,我要做的第一件事就是设置预览窗口以显示应用程序的明暗模式。这可以通过对 预览提供者 在您的 SwiftUI 视图上使用 为每个 循环并添加 .preferredColorScheme() 修饰符。

Code snippet using a For Each loop with each ColorScheme and the Preferred Color Scheme modifier to create preview windows for light and dark windows

iOS Light & Dark mode previews

SwiftUI 使编写代码变得容易,就像我设计的那样,添加一个最少的线框,然后从那里修改。要从类别视图屏幕开始,我知道我需要一个网格,所以开始我使用 LazyVGrid 带占位符 文本 view 查看每个类别的名称。这 LazyVGrid 使用一个 网格项 设置每列的大小和 为每个 循环使设置重复元素变得超级容易。

Code Snippet and Preview Example of the Category Screen with just a basic setup. The Code Snippet uses a For Each loop to show just a Text view with just a sample string of each category.

iOS Wireframe for Category View

我喜欢尽可能使用 Enum,它使代码更易于阅读,并有助于使单元测试更易于编写。我可以设置我的枚举类来提供每个类别将使用的图像和颜色。 iOS 也有一个用于单位测量的内置库,因此我可以在我的枚举类中包含这些库,以确保每个类别都有适合转换屏幕的单位。我也会使用 SFSafeSymbols 使用 Swift 包管理器打包,因为这个包也使得添加 SF 符号更容易 。

Code Snippet for setting up Enum class for Category Items in Swift.

iOS setup for Category Enum

这里需要注意的是,枚举不能用于 为每个 在 SwiftUI 端循环,它需要是 可识别 这在枚举上是不允许的。为了解决这个问题,我们只需要设置一个可以在 SwiftUI 端使用的类,并将枚举作为初始化器。

Code Snippet for the Category Item that can be used with SwiftUI components.

iOS Category Item for SwiftUI use

所有项目() 函数对我们的 SwiftUI 视图很有用,所以现在我们需要做的就是对线框进行一些小调整,并且我们已经设置了所有类别,其中包含将它们显示为卡片所需的 UI 组件。

Code Snippet for main Category Screen updated to use the Category Enum class.

iOS Category Screen updated with Category Enum class

创建卡片相当简单,使用 堆栈 因为基础组件将确保所有东西都垂直堆叠。对于卡片的顶部,我想显示图标和可用选项的数量,以便这些项目将被包裹在 堆栈 为了使整个视图看起来像一张卡片,我使用了以下组合 。覆盖 。背景 修饰符 圆角矩形 这为我提供了再次更新主视图以现在使用卡片视图而不是文本视图所需的一切。

Code Snippet for iOS Card View layout

iOS Category Card View

使用此设置,只需在主视图上更改一行即可交换 文本视图 与新 类别卡片视图 就是这样,主视图几乎是设置。还有一些需要做的事情,例如将主视图包装在 导航视图 并添加一个 导航链接 到卡片视图以在被点击后转换到转换器视图。

Code Snippet of the Category View updated to use the new Card View in place of the Text View.

iOS Category View updated to use the Card View

现在是时候设置转换器视图了,这就是所有艰苦工作都将发生的地方。为了使 UI 在 SwiftUI 中响应,我需要使用 可观察对象 可以使用 发表 当基于输入值更新转换后的值时触发更新的变量。使用 。下沉 处理程序还将允许我在更新输入字段时执行转换代码,以便用户在键入时看到转换后的值,而无需按回车键。至于实际的转换逻辑,这个过程是通过几个步骤来处理的;首先使用所选单位获取值,然后过滤转换选项列表以排除所选单位,最后使用内置 。转换成: ) Dimension 类中的方法,该方法将创建转换后的值列表。

Code Snippet for Converter View Model in Swift

iOS Converter View Model

现在只需要连接 发表 转换器视图上的 UI 变量,设置输入字段以仅接受数字并设置一个列表视图,以显示转换后的结果。该列表还允许您点击任何选项并切换到该单元。要制作转换后的结果列表,需要添加一个 .onTapGesture() 修饰符并添加一个 .contentShape(矩形()) 使整行响应点击。

Code Snippet for Converter View layout in SwiftUI with Preview example

iOS Converter View with Preview

至此,应用程序已经基本完成,但在结束 iOS 应用程序之前,还需要执行一个步骤,即单元测试‍。对我来说,我喜欢让 ViewModel 获得尽可能多的覆盖范围,因为这是应用程序的大部分逻辑发生的地方。按照与之前相同的过程,我将从测试较小的函数开始,然后进行迭代以确保所有类别项都有类似的测试。现在我将只使用默认值 XCTestCase 对于 Swift 和一些简单的 XCTAssertEqual XCTAssertFalse 语句以获得我需要的结果。

Unit Test example in Swift

iOS Unit Tests

现在 iOS 项目已经完成,在构建应用程序的发布版本之前,让我们深入了解 Android 版本。

On to the next one

安卓应用

最低要求:Android Studio 2021 (Chipmunk) 和 Kotlin 1.5。在撰写本文时,这些功能中的大部分都被标记为实验性的,并且可能会随着时间而改变。

使用我的 iOS 应用程序作为蓝图,我已经知道我需要什么才能开始使用 Android 方面的东西。开始选择一个 空的撰写活动(材料 3) 并选择最低 API 25 (Lollipop) 的 Kotlin。与 iOS 应用程序一样,我使用模拟器进行验证,并且会在完成每个步骤时经常构建。

Android 平台的差异之一是如何使用颜色和主题。为了获得我需要的颜色,我使用 材质主题生成器 并使用导出 Jetpack 撰写主题 .将其放入应用程序后,我现在可以设置我的 Dark & Light Preview 灯光预览,这是通过创建不同的 预览可组合 并设置 使用深色主题 多变的。我喜欢用 显示背景 显示系统界面 在预览窗口上以及只是为了获得每种类型的完整预览。

Code Snippet for setting up Light and Dark preview windows in Android

Android Light & Dark Mode Previews

为了提供相同的导航和实时数据,我需要通过使用以下依赖项更新应用程序 gradle 文件来添加一些 Compose 库以开始使用。

 科特林{  
 // ...  
 依赖{  
 实现 'androidx.navigation:navigation-compose:2.5.0-alpha01'  
 实现“androidx.compose.runtime:runtime-livedata:1.0.5”  
 }  
 }

现在,由于我已经知道我需要一个类别模型来处理主屏幕的所有逻辑,而不是构建线框,我可以设置实际模型以在视图中使用。使用 Kotlin,我可以使用 枚举 同样,我可以设置使用枚举值用于所有主要显示项目的模型。

Android Category Enum & Model

通过模型设置,我的线框可以跳过使用字符串数组进行测试的步骤,并且我现在可以让我的类别项数组与简单的文本视图一起使用以显示标题。使用 惰性垂直网格 现在是实验性的,但这正是我想要提供相同的卡片视图的,所以我会使用它。设置它实际上也与 iOS 上的网格视图非常相似。

Code Snippet for the Category View in Android and Preview example

Android Grid Wireframe

下一步是处理 Category 项目的 Card 视图。材料设计库带有一个 卡片 在 Jetpack Compose 和混合使用的视图 在 Android 端获得类似的布局非常容易。对于图像资源,我使用的是 画家资源 选项,因此它适用于视图模型和图标资源 ID。我稍后会回来添加导航逻辑,只是为了不让这一步过于复杂。

Android Category Card View

现在就像 iOS 应用程序一样,我可以返回到我的类别视图并通过更改 文本 领域到 卡片视图 会给我我的类别屏幕一切准备就绪

Android Category Card View and Layout

完成该部分后,下一个要处理的部分是转换器视图。同样,由于我们将 iOS 应用程序用作蓝图,我可以直接进入视图模型并设置所有转换器逻辑。在 Jetpack Compose 中,用户界面通过使用 可变实时数据 在 ViewModel 内部,然后使用 .postValue() 在这些变量上使 UI 响应这些变化。大多数转换逻辑遵循与 iOS 相同的模式,获取所有转换选项,设置所选值,然后为每个可用选项执行转换。我必须做的唯一更改是 Unit 选项,似乎 Android 上的内置选项没有提供与 iOS 库相同的功能。我找到了这个图书馆 测量的 这行得通,但它没有使用所有相同的单位,所以我必须在添加它后进行一些调整。

Code Snippet for Android Converter View Model

Android Converter View Model

将转换器视图连接到视图模型需要使用 记住 或者 观察状态() 实时数据变量上的 API 方法,就像 iOS 应用程序一样简单 文本域 对于输入和一个 懒人列 因为结果列表会给我我需要的一切。为了使转换在键入时执行,修饰符 onValueChange 可用于调用 TextField 上的转换逻辑。

Code Snippet for Converter View layout in Android with Preview example

Android Converter View

在点击类别卡后可以查看转换器视图之前,还需要添加另一部分,即 导航控制器 . Jetpack Compose 端使用 导航主机 它采用可用的不同视图以及用于到达该视图的路线。使用 论据 在 NavController 中,我们可以识别所选类别卡的 id,然后将所选类别传递给转换器视图。在里面 MainActivity.kt 首先设置 NavHost,然后更新主 创建 使用更新的导航组件。从这里开始 导航控制器 需要传递给卡片视图,并在 点击 方法使用参数中传递的类别 ID 添加导航调用。

 onClick = { navController.navigate(NavigationRoutes.DETAIL.name + "/${item.option.id}") }

Code Snippet for setting up the Navigation Controller in Android

Android Navigation Component

从这里开始,Android 应用程序已经准备就绪。类别屏幕应显示每种类型的所有图标和颜色,并且可以导航到转换器视图。最后一部分是添加一个单元测试,在 Android 端我将再次使用默认的测试库。因为我使用的是带有一些 MutableLiveData 的 ViewModel,所以有一个 规则 需要将其添加到测试库中才能访问实时数据值。一旦添加了这些,编写测试就相当简单了,并且几乎与 iOS 端相同。

Code Snippet for unit tests in Android

Android Unit Tests

好的,现在移动应用程序已经完成,是时候使用响应式 Web 应用程序了。

One more to go

网络应用

最低要求:Visual Studio Code、Vite、Svelte、TypeScript 和 TailwindCSS。

与移动应用程序相比,Web 应用程序绝对是一个更“开放”的游乐场,因为可以使用的框架种类要多得多。虽然有一些框架比其他框架使用更广泛,但我选择了一个我认为最适合我的开发风格的堆栈,它来自纯移动背景。对于测试,我喜欢使用 嘶嘶的 作为开发浏览器,因为我可以看到小屏幕和大屏幕。

  1. Vite — 一种更新的构建工具,速度极快并提供热重载(实时更新)
  2. Svelte — 用于构建反应式组件的前端框架
  3. TypeScript — 用于添加类型安全的后端逻辑,这是我作为移动开发人员所习惯的
  4. TailwindCSS — 一个 CSS 框架,使响应式类更易于编写和阅读。

首先,我将使用 Vite 脚手架选项来设置项目 npm init [[email protected]](/cdn-cgi/l/email-protection) 并选择 苗条的打字稿 选项。项目完成后,可以使用简单的命令添加 TailwindCSS npx [[email protected]](/cdn-cgi/l/email-protection) tailwindcss 现在唯一需要的项目是 FontAwesome 图标。对于 FontAwesome,我喜欢使用本地选项,下载资产并将 CSS 链接添加到 索引.html 文件,现在 Web 应用程序库已准备就绪。

以前的应用程序的经验有助于让我了解 Web 应用程序工作所需的一些基本结构,所以我将从导航部分开始。 Svelte 带有一个 苗条的导航员 可用于设置导航的库。我将从一些简单的链接和空白页面开始,以确保一切设置正确。

Web App initial Routing setup

运行应用程序应该会产生两个简单的页面,可以使用每个页面上的链接在它们之间导航。现在和其他应用程序一样,我知道我需要一个类别项目的模型,虽然 TypeScript 确实有一个 Enum 类,但它与其他平台的工作方式并不完全相同,所以我将使用可导出的命名空间来完成所有UI 导出就像我在其他应用程序中所做的那样。我还将添加 计量单位 库,所以我可以使用我的 Enum 类中的单位。

为了构建 UI,我将使用 雏菊用户界面 为 TailwindCSS 和 被称为苗条 模板来完成从头开始构建整个 UI 的一些工作。为了保持 UI 简单,并与移动应用程序有相似的感觉,我将让主页显示一些简单的文本和每个类别的一些卡片状形状。为了处理导航,我将使用内置的 苗条的商店 跟踪输入字段中输入的所选类别、所选单位和当前值。首先,我设置卡片布局。

Svelte Category Card View

使用 Svelte 的好处之一是能够使用 #每个 循环创建多个类别卡,而无需为每个项目重新键入所有相同的类别。

Svelte Category Cards

与所有其他应用程序一样,完成下一部分的类别项目是转换器视图。我将从 ViewModel 开始,因为与其他应用程序一样,我需要设置执行转换的逻辑并将所有结果格式化为结果表。逻辑仍然遵循非常相似的模式,首先获取当前选定的单位和该数量的输入值,获取选定类别的所有转换选项,然后从结果中过滤掉选定的项目。

Code snippet for Converter View Model in TypeScript

TypeScript Converter View Model

将 ViewModel 连接到 UI 组件与其他平台相同, 输入 字段输入一个值,然后一个列表显示结果。由于在网络上并没有真正使用默认的“网格”,而且由于一张桌子最终会有很多额外的空间,我将使用卡片式设计来代替。对于输入视图,为了提供与移动应用程序相同的功能并在用户输入值时转换值,我将使用 开:输入 在视图模型中调用转换逻辑的事件。对于转换后的列表(或卡片),我将使用 Svelte 商店设置一个 。订阅 所选单位值上的事件,该事件将允许用户将输入值与任何转换选项进行交换。这只是每个视图的主要部分

Svelte Converter Input & Converted Results

Svelte Converter View Preview

这将在很大程度上将 Web App 功能与移动应用程序结合起来,但是要完成一个 Web 应用程序还需要更多的项目。基本上它 描述 设置一个测试类和 预计 解释在每个函数中执行什么样的测试的函数 功能。

Code snippet for Unit Tests in TypeScript

TypeScript Unit Test

完成单元测试后,我们知道有 3 个应用程序准备好发布并推向公众。

部署阶段

按照与之前相同的模式,我将介绍每个应用程序的部署选项,首先从 iOS 应用程序开始。

iOS 应用包

发布 iOS 应用程序需要 App Store,无论您要使用哪种分发类型。对于这个应用程序,我将使用 对此 分发选项,因此我可以将应用程序安装在我自己的特定设备上。使用 产品 菜单选择 档案 启动构建过程的选项。在存档窗口中选择 对此 选项并按照说明结束 .ipa 可以使用 苹果配置器 应用程序。

安卓应用包

发布一个 Android 应用比 iOS 端更开放一点,不需要使用 Google Play 商店来构建一个 对此 应用程序的版本。要开始使用 建造 前往的菜单 生成签名的 APK 然后选择 应用程序包 选项。下一个屏幕将要求您为将来更新软件包所需的应用程序设置密钥库,因此请确保将其安全地存储在某处。最后一步是选择保存 APK 文件的位置以及用于构建的版本(使用 发布 build),这就是 Android 方面的内容。该应用程序可以手动安装在设备上,也可以上传到 Google Play 商店进行公开分发。

网络包

对于 Web 应用程序,Vite 附带了已经设置好的脚本,用于生成构建和预览构建。构建脚本完成后,最后一步是为 Web 应用程序找到主机。根据项目的需要和可用资源,有很多选项可供选择,从免费到商业。对于这个项目,可以使用一个简单的免费托管选项 韦尔塞尔 并使用 CLI 选项,您只需运行 韦尔塞尔 来自项目的命令 距离 文件夹并按照提示启动应用程序。可以在这里找到实时预览: 算术预览

总结一下

即使只是对每个应用程序进行了高级概述,如果您按照所有三个应用程序进行操作,这也是相当多的。好消息是这个项目足够小,如果你想向这个应用程序添加更多功能,它现在可以向任何方向发展。以下是一些可以扩展的领域的想法:

  1. 更多的转换选项——这可能需要更多的库或不同的库。
  2. 添加收藏夹的能力 - 添加更多导航选项的另一个功能是创建收藏夹屏幕以轻松访问经常使用的转换。
  3. 更多测试——可以添加 UI 测试,或者来自 GitHub 端的一些自动化测试。

不管你做什么,我只是希望这是一个很好的起点,可以帮助你想象你可能有的一些想法。我将继续这个系列 ,目前处于预设计阶段。请继续关注更多。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/7670/50500108

posted @ 2022-09-01 08:53  哈哈哈来了啊啊啊  阅读(35)  评论(0编辑  收藏  举报