Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[完成翻译] src/content/cookbook/effects/drag-a-widget.md #1497

Merged
merged 2 commits into from
Sep 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 116 additions & 1 deletion src/content/cookbook/effects/drag-a-widget.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
# title: Drag a UI element
title: 创建一个可拖放的 UI 组件
description: How to implement a draggable UI element.
# description: How to implement a draggable UI element.
description: 如何实现一个可拖放的 UI 组件
js:
- defer: true
url: /assets/js/inject_dartpad.js
Expand All @@ -19,17 +20,32 @@ where the user long presses on a choice of food,
and then drags that food to the picture of the customer who
is paying for it.

拖放是移动应用程序中的一种常见交互。
当用户长按(有时称为“触摸并按住”)某个 widget 时,
另一个 widget 会出现在用户的手指下方,
用户可以将该 widget 拖动到最终位置并释放。
在这个示例中,你将构建一个拖放交互,
用户可以长按一个食物选项,
然后将该食物拖动到正在为其付款的顾客图片上。

The following animation shows the app's behavior:

下面的动画展示了应用程序的行为:

![Ordering the food by dragging it to the person](/assets/images/docs/cookbook/effects/DragAUIElement.gif){:.site-mobile-screenshot}

This recipe begins with a prebuilt list of menu items and
a row of customers.
The first step is to recognize a long press
and display a draggable photo of a menu item.

本示例从一个预先构建的菜单项列表和一排顾客开始。
第一步是识别长按操作并显示一个可拖放的菜单项图片。

## Press and drag

## 按下并拖动

Flutter provides a widget called [`LongPressDraggable`][]
that provides the exact behavior that you need to begin
a drag-and-drop interaction. A `LongPressDraggable`
Expand All @@ -39,9 +55,18 @@ As the user drags, the widget follows the user's finger.
`LongPressDraggable` gives you full control over the
widget that the user drags.

Flutter 提供了一个名为 [`LongPressDraggable`][] 的 widget,
它提供了开始拖放交互所需的确切行为。
`LongPressDraggable` widget 能够识别长按操作,
然后在用户手指附近显示一个新 widget。
当用户拖动时,该 widget 会跟随用户的手指移动。
`LongPressDraggable` 让你完全控制用户拖动的 widget。

Each menu list item is displayed with a custom
`MenuListItem` widget.

每个菜单列表项都通过一个自定义的 `MenuListItem` widget 来显示。

<?code-excerpt "lib/main.dart (MenuListItem)" replace="/^child: //g;/^\),$/)/g"?>
```dart
MenuListItem(
Expand All @@ -53,6 +78,8 @@ MenuListItem(

Wrap the `MenuListItem` widget with a `LongPressDraggable` widget.

用 `LongPressDraggable` widget 包裹 `MenuLIstItem` widget。

<?code-excerpt "lib/main.dart (LongPressDraggable)" replace="/^return //g;/^\),$/)/g"?>
```dart
LongPressDraggable<Item>(
Expand All @@ -77,36 +104,65 @@ This `DraggingListItem` displays a photo of the
selected food item, centered beneath
the user's finger.

在本例中,当用户长按 `MenuListItem` widget 时,
`LongPressDraggable` widget 会显示一个 `DraggingListItem`。
这个 `DraggingListItem` 会在用户手指下方居中显示所选的食物图片。

The `dragAnchorStrategy` property is set to
[`pointerDragAnchorStrategy`][].
This property value instructs `LongPressDraggable`
to base the `DraggableListItem`'s position on the
user's finger. As the user moves a finger,
the `DraggableListItem` moves with it.

`dragAnchorStrategy` 属性设置为 [`pointerDragAnchorStrategy`][]。
这个属性的值指示 `LongPressDraggable`
将 `DraggableListItem` 的位置基于用户的手指来定位。
当用户移动手指时,`DraggableListItem` 也会跟随移动。

Dragging and dropping is of little use if no information
is transmitted when the item is dropped.
For this reason, `LongPressDraggable` takes a `data` parameter.
In this case, the type of `data` is `Item`,
which holds information about the
food menu item that the user pressed on.

如果拖放操作在释放时没有传递任何信息,那么它几乎没有什么用处。
为此,`LongPressDraggable` 提供了一个 `data` 参数。
在本例中,`data` 的类型是 `Item`,
它包含了用户按下的菜单项的食物信息。

The `data` associated with a `LongPressDraggable`
is sent to a special widget called `DragTarget`,
where the user releases the drag gesture.
You'll implement the drop behavior next.

与 `LongPressDraggable` 相关联的 `data`
会被传递到一个名为 `DragTarget` 的特殊 widget 上,
用户在此释放拖动手势。接下来你将实现拖放行为。

## Drop the draggable

## 放下拖动项

The user can drop a `LongPressDraggable` wherever they choose,
but dropping the draggable has no effect unless it's dropped
on top of a `DragTarget`. When the user drops a draggable on
top of a `DragTarget` widget, the `DragTarget` widget
can either accept or reject the data from the draggable.

用户可以将 `LongPressDraggable` 放在任意位置,
但除非将其放在 `DragTarget` 之上,
否则拖放操作不会有任何效果。
当用户将一个可拖放的 widget 放在 `DragTarget` widget 上时,
`DragTarget` 可以选择接受或拒绝来自可拖放 widget 的数据。

In this recipe, the user should drop a menu item on a
`CustomerCart` widget to add the menu item to the user's cart.

在本示例中,用户应将菜单项拖放到 `CustomerCart` widget 上,
从而将菜单项添加到用户的购物车中。

<?code-excerpt "lib/main.dart (CustomerCart)" replace="/^return //g;/^\),$/)/g"?>
```dart
CustomerCart(
Expand All @@ -118,6 +174,8 @@ CustomerCart(

Wrap the `CustomerCart` widget with a `DragTarget` widget.

用 `DragTarget` widget 包裹 `CustomCart` widget。

<?code-excerpt "lib/main.dart (DragTarget)" replace="/^child: //g;/^\),$/)/g"?>
```dart
DragTarget<Item>(
Expand All @@ -143,6 +201,11 @@ when the user drags a draggable on top of the `DragTarget`.
The `DragTarget` also recognizes when the user drops
a draggable on top of the `DragTarget` widget.

`DragTarget` 显示你现有的 widget,
并与 `LongPressDraggable` 协调,
识别用户何时将可拖放的 widget 拖动到 `DragTarget` 之上。
同时,`DragTarget` 也能识别用户何时在其上方放下一个可拖放的 widget。

When the user drags a draggable on the `DragTarget` widget,
`candidateItems` contains the data items that the user is dragging.
This draggable allows you to change what your widget looks
Expand All @@ -151,30 +214,53 @@ the `Customer` widget turns red whenever any items are dragged above the
`DragTarget` widget. The red visual appearance is configured with the
`highlighted` property within the `CustomerCart` widget.

当用户将可一个可拖放的 widget 拖动到 `DragTarget` widget 上时,
`candidateItems` 包含用户正在拖动的数据项。
你可以根据用户拖动的情况更改 widget 的外观。
在本例中,`Customer` widget 在有项目拖动到 `DragTarget` widget 上方时会变成红色。
这个红色的外观是通过 `CustomerCart` widget 中的 `highlighted` 属性配置的。

When the user drops a draggable on the `DragTarget` widget,
the `onAcceptWithDetails` callback is invoked. This is when you get
to decide whether or not to accept the data that was dropped.
In this case, the item is always accepted and processed.
You might choose to inspect the incoming item to make a
different decision.

当用户将一个可拖放的 widget 放在 `DragTarget` widget 上时,
会调用 `onAcceptWithDetails` 回调。这时你可以决定是否接受拖放的数据。
在本例中,数据项总是会被接受和处理。
你也可以选择检查传入的数据项,以做出不同的决定。

Notice that the type of item dropped on `DragTarget`
must match the type of the item dragged from `LongPressDraggable`.
If the types are not compatible, then
the `onAcceptWithDetails` method isn't invoked.

注意,拖放到 `DragTarget` 上的数据项类型必须与从 `LongPressDraggable` 拖出的数据项类型匹配。
如果类型不兼容,`onAcceptWithDetails` 方法将不会被调用。

With a `DragTarget` widget configured to accept your
desired data, you can now transmit data from one part
of your UI to another by dragging and dropping.

通过配置 `DragTarget` widget 来接受你所需的数据,
现在你可以通过拖放在 UI 的不同部分之间传递数据。

In the next step,
you update the customer's cart with the dropped menu item.

在下一步中,你将更新顾客的购物车,将放下的菜单项添加进去。

## Add a menu item to a cart

## 将菜单项添加到购物车

Each customer is represented by a `Customer` object,
which maintains a cart of items and a price total.

每位顾客由一个 `Customer` 对象表示,该对象维护一个物品购物车和总价格。

<?code-excerpt "lib/main.dart (CustomerClass)"?>
```dart
class Customer {
Expand All @@ -199,9 +285,13 @@ class Customer {
The `CustomerCart` widget displays the customer's photo,
name, total, and item count based on a `Customer` instance.

`CustomerCart` widget 根据一个 `Customer` 实例显示顾客的照片、姓名、总价和物品数量。

To update a customer's cart when a menu item is dropped,
add the dropped item to the associated `Customer` object.

要在菜单项被拖放时更新顾客的购物车,需要将放下的物品添加到关联的 `Customer` 对象中。

<?code-excerpt "lib/main.dart (AddCart)"?>
```dart
void _itemDroppedOnCustomerCart({
Expand All @@ -221,26 +311,51 @@ The `_itemDroppedOnCustomerCart` method is invoked in
layout update, the UI refreshes with the new customer's
price total and item count.

当用户将菜单项拖放到 `CustomerCart` widget 上时,
`onAcceptWithDetails()` 中会调用 `_itemDroppedOnCustomerCart` 方法。
通过将放下的物品添加到 `customer` 对象中,
并调用 `setState()` 来触发布局更新,
UI 将会刷新,显示新的顾客总价和物品数量。

Congratulations! You have a drag-and-drop interaction
that adds food items to a customer's shopping cart.

恭喜!你现在已经实现了一个将食物项添加到顾客购物车的拖放交互。

## Interactive example

## 交互示例

Run the app:

运行应用程序

* Scroll through the food items.

浏览食物项列表。

* Press and hold on one with your
finger or click and hold with the
mouse.

用手指长按其中一个食物项,或用鼠标点击并按住。

* While holding, the food item's image
will appear above the list.

按住时,食物项的图片将出现在列表上方。

* Drag the image and drop it on one of the
people at the bottom of the screen.
The text under the image updates to
reflect the charge for that person.
You can continue to add food items
and watch the charges accumulate.

将图片拖动并放到屏幕底部的某个人身上。
图片下方的文本会更新,显示该人的费用。
你可以继续添加食物项,观察费用的累计情况。

<!-- Start DartPad -->

<?code-excerpt "lib/main.dart"?>
Expand Down
Loading