From cf084055f956e5d622852ae7bd3b10a6495d8d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=87=AA=E7=94=B1=E7=9A=84=E4=B8=96=E7=95=8C=E4=BA=BA?= <3196812536@qq.com> Date: Sat, 24 Aug 2024 17:25:44 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=AE=8C=E5=96=84=E7=BF=BB=E8=AF=91]=20src/co?= =?UTF-8?q?okbook/effects/download-button.md=20#1171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 感谢你的悉心指导,我对该文件又进行了完善,采取了你的建议 由于初次接触,可能会对相关方面的步骤不太熟悉,会尽力配合更正的 --- .../cookbook/effects/download-button.md | 132 ++++++++++-------- 1 file changed, 75 insertions(+), 57 deletions(-) diff --git a/src/content/cookbook/effects/download-button.md b/src/content/cookbook/effects/download-button.md index 2e4067b071..01fdf45aff 100644 --- a/src/content/cookbook/effects/download-button.md +++ b/src/content/cookbook/effects/download-button.md @@ -1,8 +1,8 @@ --- -title: Create a download button -标题:创建一个下载按钮 -description: How to implement a download button. -描述:如何实现下载按钮 +# title: Create a download button +title:创建一个带进度条的下载按钮 +# description: How to implement a download button. +description:如何实现下载按钮 js: - defer: true url: /assets/js/inject_dartpad.js @@ -20,14 +20,15 @@ to provide this feedback. In this recipe, you'll build a download button that transitions through multiple visual states, based on the status of an app download. -应用程序中充满了执行长时间操作的按钮。 +应用程序中有许多按钮需要执行长时间的操作。 例如,一个按钮可能会触发下载, -启动下载过程,并在一段时间内接收数据, -然后提供对下载资源的访问。 -向用户显示长时间运行过程的进度是很有帮助的, -而按钮本身是提供此反馈的好地方。 -在这个示例中,你将构建一个下载按钮, -根据应用程序下载的状态在多个视觉状态之间切换。 +从而启动下载流程,并在一段时间内接收数据, +最终提供对下载资源的访问。 +向用户展示长时间运行过程的进度有助于提升体验, +而按钮本身正是传达这种反馈的理想位置。 +在本教程中, +你将构建一个能够根据应用程序的下载状态, +切换不同视觉效果的下载按钮。 The following animation shows the app's behavior: @@ -43,12 +44,12 @@ Your button widget needs to change its appearance over time. Therefore, you need to implement your button with a custom stateless widget. -你的button widget需要随着时间的推移改变其外观。 -因此,你需要使用 custom stateless widget来实现你的按钮。 +你的按钮 widget 需要随着时间的推移改变其外观。 +因此,你需要自定义 stateless widget 来实现这种按钮。 Define a new stateless widget called `DownloadButton`. -定义一个名为 `DownloadButton` 的新stateless widget。 +定义一个新的 stateless widget,名为 `DownloadButton`。 ```dart @@ -68,7 +69,7 @@ class DownloadButton extends StatelessWidget { ## Define the button's possible visual states -## 定义按钮的可能的视觉状态 +## 定义按钮的各种视觉状态 The download button's visual presentation is based on a given download status. Define the possible states of @@ -77,9 +78,10 @@ a `DownloadStatus` and a `Duration` for how long the button should take to animate from one status to another. 下载按钮的视觉呈现基于给定的下载状态。 -首先定义下载可能的状态,然后更新 `DownloadButton` -以接受一个 `DownloadStatus` 和一个 `Duration`, -用于指定按钮从一个状态动画过渡到另一个状态所需的时间。 +首先定义下载可能会出现的各种状态, +然后更新 `DownloadButton`, +使其接收一个 `DownloadStatus` 和一个 `Duration` 类型的参数, +`Duration` 用于指定按钮在不同状态之间切换时的动画过渡时间。 ```dart @@ -130,16 +132,17 @@ you ensure greater reusability for the widget, easier testing, and easier changes to application behavior in the future. -每次定义custom widget时, -你都必须决定是将所有相关信息从其parent widget传递给该组件, -还是让该组件在其内部协调应用程序行为。 -例如,`DownloadButton` 可以从其parent widget接收当前的 `DownloadStatus`, -也可以在其 `State` 对象内部管理下载过程。 -对于大多数组件来说,最佳做法是将相关信息从parent widget传递到组件内部, -而不是在组件内部管理行为。 -通过传递所有相关信息, -你可以确保组件具有更高的可重用性、更容易进行测试, -以及在未来更容易更改应用程序行为。 +每次自定义 widget 时, +你都需要决定所有相关信息, +是否从父级传递给该 widget, +还是让该 widget 在内部自行协调应用程序的行为。 +例如,`DownloadButton` 可以从父级接收当前的 `DownloadStatus`, +或者也可以在其 `State` 对象内部自行协调下载过程。 +对于大多数 widget 来说,最佳做法是将相关信息从父级传递给 widget, +而不是在 widget 内部自行协调行为。 +通过将所有相关信息传递给 widget, +你可以确保 widget 具有更高的可重用性、更易于测试, +同时也更方便在未来改变应用程序的行为。 ::: @@ -163,8 +166,8 @@ build an `AnimatedContainer` with a rectangle or a circle. 根据当前的 `DownloadStatus`, -构建一个带有 `ShapeDecoration` 的 `AnimatedContainer`, -该装饰可以显示圆角矩形或圆形。 +构建一个 `AnimatedContainer`, +其中使用 `ShapeDecoration` 来显示圆角矩形或圆形。 Consider defining the shape's widget tree in a separated `Stateless` widget so that the main `build()` @@ -175,16 +178,16 @@ like `Widget _buildSomething() {}`, always prefer creating a considerations on this can be found in the [documentation]({{site.api}}/flutter/widgets/StatelessWidget-class.html) or in a dedicated video in the Flutter [YouTube channel]({{site.yt.watch}}?v=IOyq-eTRhvo). -建议将形状的widget tree定义在一个单独的 `Stateless` 组件中, -这样主 `build()` 方法可以保持简洁,便于后续添加功能。 -与其创建一个返回组件的函数(例如 `Widget _buildSomething() {}`), +建议将形状的 widget 树定义在一个单独的 `Stateless` widget 中, +这样可以保持主 `build()` 方法的简洁,便于后续添加功能。 +与其创建一个返回 widget 的函数(例如 `Widget _buildSomething() {}`), 更好的做法是创建一个 `StatelessWidget` 或 `StatefulWidget`,这在性能上更优。 有关更多的考虑因素,你可以在 [文档]({{site.api}}/flutter/widgets/StatelessWidget-class.html) 中找到, 或者在 Flutter 的 [YouTube 频道]({{site.yt.watch}}?v=IOyq-eTRhvo) 上观看相关视频。 For now, the `AnimatedContainer` child is just a `SizedBox` because we will come back at it in another step. -目前,`AnimatedContainer` 的child widget只是一个 `SizedBox`, +目前,`AnimatedContainer` 的子 widget 只是一个 `SizedBox`, 因为我们将在后续步骤中再来处理它。 @@ -272,8 +275,10 @@ ending shape of a circle. But, you don't want the final circle to be visible, so you make it transparent, which causes an animated fade-out. -你可能会疑惑,为什么需要为一个透明的圆形使用 `ShapeDecoration` 组件,毕竟它是不可见的。 -这个透明圆形的目的是为了协调动画效果。`AnimatedContainer` 一开始显示为圆角矩形。 +你可能会疑惑,既然透明圆形是不可见的, +为什么还需要使用 `ShapeDecoration` widget 呢? +因为这个透明圆形的目的是为了协调动画效果。 +`AnimatedContainer` 一开始显示为圆角矩形。 当 `DownloadStatus` 变为 `fetchingDownload` 时, `AnimatedContainer` 需要从圆角矩形动画过渡到圆形,并在动画进行的过程中逐渐淡出。 实现这种动画的唯一方法是定义圆角矩形的起始形状和圆形的结束形状。 @@ -288,15 +293,18 @@ The `DownloadButton` displays `GET` during the phase, and no text in between. `DownloadButton` 在 `notDownloaded` 阶段显示 `GET`, -在 `downloaded` 阶段显示 `OPEN`,在中间阶段没有文本。 +在 `downloaded` 阶段显示 `OPEN`, +而在其他阶段则不显示文本。 Add widgets to display text during each download phase, and animate the text's opacity in between. Add the text widget tree as a child of the `AnimatedContainer` in the button wrapper widget. -添加用于显示每个下载阶段文本的组件,并在阶段之间动画化文本的透明度。 -将text widget tree作为 `AnimatedContainer` 的child widget添加到按钮包装组件中。 +添加用于显示每个下载阶段文本的 widget, +并在各阶段之间对文本的不透明度进行动画处理。 +将文本 widget 树作为 `AnimatedContainer` 的子 widget, +添加到包装按钮的 widget 中。 ```dart @@ -357,26 +365,26 @@ class ButtonShapeWidget extends StatelessWidget { ## Display a spinner while fetching download -## 下载时显示一个进度条 +## 获取下载时显示一个加载指示器 During the `fetchingDownload` phase, the `DownloadButton` displays a radial spinner. This spinner fades in from the `notDownloaded` phase and fades out to the `fetchingDownload` phase. -在 `fetchingDownload` 阶段,`DownloadButton` 会显示一个径向进度条。 -这个进度条从 `notDownloaded` 阶段淡入,到 `fetchingDownload` 阶段淡出。 +在 `fetchingDownload` 阶段,`DownloadButton` 会显示一个旋转的加载指示器。 +这个加载指示器从 `notDownloaded` 阶段淡入,到 `fetchingDownload` 阶段淡出。 Implement a radial spinner that sits on top of the button shape and fades in and out at the appropriate times. -实现一个位于按钮形状之上的径向进度条,并在适当的时间淡入和淡出。 +实现一个覆盖在按钮上方的加载指示器,并在适当的时机淡入和淡出。 We have removed the `ButtonShapeWidget`'s constructor to keep the focus on its build method and the `Stack` widget we've added. 我们删除了 `ButtonShapeWidget` 的构造函数, -以便集中精力关注其 build 方法和添加的 `Stack` 组件。 +以便将重点放在 build 方法和我们添加的 `Stack` widget 上。 ```dart @@ -421,15 +429,17 @@ radial progress bar. The `DownloadButton` also displays a stop button icon so that the user can cancel an in-progress download. 在 `fetchingDownload` 阶段之后,是 `downloading` 阶段。 -在 `downloading` 阶段,`DownloadButton` 会用增长型的径向进度条替换径向进度条。 +在 `downloading` 阶段, +`DownloadButton` 会用一个随进度增长的径向进度条来替代加载指示器。 `DownloadButton` 还会显示一个停止按钮图标,以便用户可以取消正在进行的下载。 Add a progress property to the `DownloadButton` widget, and then update the progress display to switch to a radial progress bar during the `downloading` phase. -将一个进度属性添加到 `DownloadButton` 组件中, -然后在 `downloading` 阶段切换到径向进度条。 +为 `DownloadButton` widget 添加一个进度属性, +然后更新进度的显示, +使其在 `downloading` 阶段切换到径向进度条。 Next, add a stop button icon at the center of the radial progress bar. @@ -486,18 +496,20 @@ Widget build(BuildContext context) { The last detail that your `DownloadButton` needs is the button behavior. The button must do things when the user taps it. -`DownloadButton` 的最后一个细节是按钮行为。当用户点击按钮时,该按钮必须做某些事情。 +最后一步,`DownloadButton` 还需要实现按钮的行为。 +按钮必须在用户点击时执行相应的操作。 Add widget properties for callbacks to start a download, cancel a download, and open a download. -添加回调属性,以开始下载、取消下载和打开下载。 +为 widget 添加回调,用于开始下载、取消下载和打开下载。 Finally, wrap `DownloadButton`'s existing widget tree with a `GestureDetector` widget, and forward the tap event to the corresponding callback property. -最后,用 `GestureDetector` 包装 `DownloadButton` 的现有widget tree,并将点击事件转发到相应的回调属性。 +最后,用 `GestureDetector` widget 包装 `DownloadButton` 现有的 widget 树, +并将点击事件转发到相应的回调属性。 ```dart @@ -560,13 +572,13 @@ fetching download, downloading, and downloaded. Now, the user can tap to start a download, tap to cancel an in-progress download, and tap to open a completed download. -恭喜!您已经有一个按钮, -该按钮根据按钮所处的阶段而改变其显示:未下载、获取下载、下载中和已下载。 -现在,用户可以点击以启动下载、点击以取消正在进行的下载,并点击以打开已完成的下载。 +恭喜!你已经完成了一个按钮, +它会根据按钮所处的阶段来改变显示效果:未下载、获取下载、下载中和已下载。 +现在,用户可以点击按钮来启动下载、取消正在进行的下载,或者打开已完成的下载。 ## Interactive example -## 互动示例 +## 交互示例 Run the app: @@ -574,16 +586,22 @@ Run the app: * Click the **GET** button to kick off a simulated download. + + 点击 **GET** 按钮开始模拟下载。 + * The button changes to a progress indicator to simulate an in-progress download. + + 按钮会切换到进度指示器,以模拟下载中的状态。 + * When the simulated download is complete, the button transitions to **OPEN**, to indicate that the app is ready for the user to open the downloaded asset. -* 点击 **GET** 按钮以启动模拟下载。 -* 该按钮更改为进度指示器以模拟正在进行的下载。 -* 当模拟下载完成时,按钮将过渡到 **OPEN** ,表示应用已准备好让用户打开下载的资源。 + 当模拟下载完成后, + 按钮将过渡到 **OPEN**, + 表示应用已准备好让用户打开下载的资源。