Skip to content

Commit becb40c

Browse files
author
zengsong
committed
upload file
1 parent 8583015 commit becb40c

File tree

4 files changed

+443
-0
lines changed

4 files changed

+443
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
## 介绍
2+
3+
AbsorbPointe 它是一个在命中测试期间吸收指针事件的Widget。
4+
5+
与 IgnorePointer 相比较,虽然这两个Widget都能阻止子树接收指针事件,但不同之处在于 AbsorbPointer 本身会参与命中测试,而 IgnorePointer 本身不会参与。这就意味着 AbsorbPointer 本身是可以接收指针事件的(其子树不行),而 IgnorePointer 则不可以。
6+
7+
(注意:只有通过命中测试的Widget才能触发事件)
8+
9+
## 继承关系
10+
11+
Object -> Diagnosticable -> DiagnosticableTree -> Widget RenderObjectWidget -> SingleChildRenderObjectWidget -> AbsorbPointer
12+
13+
## 构造函数
14+
15+
```
16+
AbsorbPointer({Key key, bool absorbing: true, Widget child, bool ignoringSemantics })
17+
```
18+
19+
## 常用属性
20+
21+
- absorbing → bool
22+
是否在命中测试期间吸收指针事件。
23+
24+
- ignoringSemantics → bool
25+
编译语义树的时候, 是否忽略此呈现对象的语义。
26+
27+
当 absorbing 值为tru的时候,此Widget通过终止自身的命中测试来防止其子树接收指针事件。它仍然会在布局时消耗空间,并像往常一样绘制其子对象。实际上它只是防止其子组件成为已定位事件的目标,而它自身不会,因为它从renderbox.hittest返回true。
28+
29+
## 使用示例
30+
31+
#### 1. 不填 absorbing 参数的情况:
32+
33+
```
34+
@override
35+
Widget build(BuildContext context) {
36+
return Scaffold(
37+
appBar: AppBar(
38+
title: Text(widget.title),
39+
),
40+
body: getAbsorbPointerBody(),
41+
);
42+
}
43+
44+
Widget getAbsorbPointerBody() {
45+
return Container(
46+
child: Listener(
47+
child: AbsorbPointer(
48+
child: Listener(
49+
child: Container(
50+
color: Colors.black87,
51+
),
52+
onPointerDown: (event) => print("onReceived AbsorbPointer Child Pointer"),
53+
),
54+
),
55+
onPointerDown: (event) => print("onReceived AbsorbPointer Parent Pointer"),
56+
),
57+
);
58+
}
59+
60+
```
61+
62+
log 输出:
63+
64+
```
65+
21:13:07.305 9 info flutter.tools I/flutter ( 9081): onReceived AbsorbPointer Parent Listener
66+
```
67+
通过日志我们发现,AbsorbPointer 的子部件 Pointer 事件未触发。
68+
69+
#### 2. absorbing = false 的情况:
70+
71+
```
72+
Widget getAbsorbPointerBody() {
73+
return Container(
74+
child: Listener(
75+
child: AbsorbPointer(
76+
child: Listener(
77+
child: Container(
78+
color: Colors.black87,
79+
),
80+
onPointerDown: (event) =>
81+
print("onReceived AbsorbPointer Child Listener"),
82+
),
83+
absorbing: false),
84+
onPointerDown: (event) =>
85+
print("onReceived AbsorbPointer Parent Listener"),
86+
),
87+
);
88+
}
89+
```
90+
91+
log 输出:
92+
```
93+
21:15:33.475 25 info flutter.tools I/flutter ( 9081): onReceived AbsorbPointer Child Listener
94+
21:15:33.475 26 info flutter.tools I/flutter ( 9081): onReceived AbsorbPointer Parent Listener
95+
```
96+
97+
从日志可以看到,AbsorbPointer Widget 的子部件中的 Pointer 事件也触发了,并且符合事件触发的时序,子部件先于父部件触发。
98+
99+
100+
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
## 介绍
2+
3+
Dismissible 是一种可以通过沿指定的方向拖动来关闭的 Widget。
4+
比如,若我们需要向左或者向右滑动来移除一个Widget(比如很常见的“滑动删除”功能),则非常适合使用Dismissible来实现。
5+
6+
## 继承关系
7+
8+
Object -> Diagnosticable -> DiagnosticableTree -> Widget -> StatefulWidget -> Dismissible
9+
10+
## 构造函数
11+
12+
```
13+
Dismissible({@required Key key,
14+
@required Widget child,
15+
Widget background,
16+
Widget secondaryBackground,
17+
ConfirmDismissCallback confirmDismiss,
18+
VoidCallback onResize,
19+
DismissDirectionCallback onDismissed,
20+
DismissDirection direction: DismissDirection.horizontal,
21+
Duration resizeDuration: const Duration(milliseconds: 300),
22+
Map<DismissDirection, double> dismissThresholds: const {},
23+
Duration movementDuration: const Duration(milliseconds: 200),
24+
double crossAxisEndOffset: 0.0,
25+
DragStartBehavior dragStartBehavior: DragStartBehavior.start })
26+
```
27+
28+
## 常用属性
29+
30+
- background → Widget
31+
背景部件。如果还指定了secondaryBackground,则仅在子项被向下或向右拖动时才显示此小部件。
32+
33+
- child → Widget 子部件。
34+
35+
- confirmDismiss → ConfirmDismissCallback
36+
使应用有机会确认或取消的回调。
37+
38+
- crossAxisEndOffset → double
39+
定义取消卡片后横过主轴的结束偏移量
40+
41+
- direction → DismissDirection
42+
可以关闭 Widget 的方向。
43+
44+
- dismissThresholds → Map<DismissDirection, double>
45+
必须拖动项目才能被视为已取消的偏移阈值
46+
47+
- dragStartBehavior → DragStartBehavior
48+
确定处理拖动开始行为的方式。
49+
50+
- movementDuration → Duration
51+
定义了卡片退回或未退回原位置的持续时间。
52+
53+
- onDismissed → DismissDirectionCallback
54+
完成调整大小后,在关闭窗口小部件时调用。
55+
56+
- onResize → VoidCallback
57+
当窗口小部件更改大小时调用(即在关闭前收缩时调用)。
58+
59+
- resizeDuration → Duration
60+
在调用onDismissed之前,窗口小部件所需花费的收缩时间。
61+
62+
- secondaryBackground → Widget
63+
堆叠在子部件后面的背景部件,当子部件被向上或向左拖动时会暴露出来。只有在同时指定了背景时才能指定它。
64+
65+
66+
## 使用示例 (实现滑动删除的 sample)
67+
68+
(参考地址 https://flutterchina.club/cookbook/gestures/dismissible/
69+
)
70+
### 1. 创建item列表
71+
72+
第一步是创建一个我们可以滑动的列表。有关如何创建列表的更多详细说明,请按照使用长列表进行操作。
73+
74+
#### 创建数据源
75+
76+
简单起见,这里生成一个字符串列表。
77+
78+
final items = new List<String>.generate(20, (i) => "Item ${i + 1}");
79+
80+
#### 将数据源转换为List
81+
82+
首先,我们将简单地在屏幕上的列表中显示每个项目(先不支持滑动)。
83+
84+
```
85+
new ListView.builder(
86+
itemCount: items.length,
87+
itemBuilder: (context, index) {
88+
return new ListTile(title: new Text('${items[index]}'));
89+
},
90+
);
91+
```
92+
93+
### 2. 将item包装在Dismissible Widget中
94+
95+
现在我们希望让用户能够将条目从列表中移除,用户删除一个条目后,我们需要从列表中删除该条目并显示一个Snackbar。 在实际的场景中,您可能需要执行更复杂的逻辑,例如从Web服务或数据库中删除条目。
96+
97+
这是我们就可以使用Dismissable。在下面的例子中,我们将更新itemBuilder函数以返回一个DismissableWidget。
98+
99+
```
100+
new Dismissible(
101+
// Each Dismissible must contain a Key. Keys allow Flutter to
102+
// uniquely identify Widgets.
103+
key: new Key(item),
104+
// We also need to provide a function that will tell our app
105+
// what to do after an item has been swiped away.
106+
onDismissed: (direction) {
107+
// Remove the item from our data source
108+
items.removeAt(index);
109+
110+
// Show a snackbar! This snackbar could also contain "Undo" actions.
111+
Scaffold.of(context).showSnackBar(
112+
new SnackBar(content: new Text("$item dismissed")));
113+
},
114+
child: new ListTile(title: new Text('$item')),
115+
);
116+
```
117+
118+
### 3. 提供滑动背景提示
119+
120+
现在,我们的应用程序将允许用户从列表中滑动项目,但用户并不知道滑动后做了什么,所以,我们需要告诉用户滑动操作会移除条目。 为此,我们将在滑动条目时显示指示。在下面的例子中,我们通过将背景设置为红色表示为删除操作。
121+
122+
为此,我们为Dismissable提供一个background参数。
123+
```
124+
new Dismissible(
125+
// Show a red background as the item is swiped away
126+
background: new Container(color: Colors.red),
127+
key: new Key(item),
128+
onDismissed: (direction) {
129+
items.removeAt(index);
130+
131+
Scaffold.of(context).showSnackBar(
132+
new SnackBar(content: new Text("$item dismissed")));
133+
},
134+
child: new ListTile(title: new Text('$item')),
135+
);
136+
```
137+
138+
139+
### 完整代码:
140+
141+
```
142+
import 'package:flutter/foundation.dart';
143+
import 'package:flutter/material.dart';
144+
145+
void main() {
146+
runApp(new MyApp(
147+
items: new List<String>.generate(20, (i) => "Item ${i + 1}"),
148+
));
149+
}
150+
151+
class MyApp extends StatelessWidget {
152+
final List<String> items;
153+
154+
MyApp({Key key, @required this.items}) : super(key: key);
155+
156+
@override
157+
Widget build(BuildContext context) {
158+
final title = 'Dismissing Items';
159+
160+
return new MaterialApp(
161+
title: title,
162+
home: new Scaffold(
163+
appBar: new AppBar(
164+
title: new Text(title),
165+
),
166+
body: new ListView.builder(
167+
itemCount: items.length,
168+
itemBuilder: (context, index) {
169+
final item = items[index];
170+
171+
return new Dismissible(
172+
// Each Dismissible must contain a Key. Keys allow Flutter to
173+
// uniquely identify Widgets.
174+
key: new Key(item),
175+
// We also need to provide a function that will tell our app
176+
// what to do after an item has been swiped away.
177+
onDismissed: (direction) {
178+
items.removeAt(index);
179+
180+
Scaffold.of(context).showSnackBar(
181+
new SnackBar(content: new Text("$item dismissed")));
182+
},
183+
// Show a red background as the item is swiped away
184+
background: new Container(color: Colors.red),
185+
child: new ListTile(title: new Text('$item')),
186+
);
187+
},
188+
),
189+
),
190+
);
191+
}
192+
}
193+
```
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
## 介绍
3+
4+
IgnorePointer 是一种在命中测试期间不可见的Widget部件。通俗地来说,如果我们不想让一个 Widget 接收到触摸事件,就用 IgnorePointer 包裹起来。
5+
6+
与AbsorbPointer相比较,虽然这两个Widget都能阻止子树接收指针事件,但不同之处在于AbsorbPointer本身会参与命中测试,而IgnorePointer本身不会参与。这就意味着AbsorbPointer本身是可以接收指针事件的(其子树不行),而IgnorePointer则不可以。
7+
8+
(注意:只有通过命中测试的Widget才能触发事件)
9+
10+
## 继承关系
11+
12+
Object -> Diagnosticable -> DiagnosticableTree -> Widget RenderObjectWidget -> SingleChildRenderObjectWidget -> IgnorePointer
13+
14+
## 构造函数
15+
16+
```
17+
IgnorePointer({Key key, bool ignoring: true, bool ignoringSemantics, Widget child })
18+
```
19+
20+
## 常用属性
21+
22+
- ignoring → bool
23+
是否在命中测试期间,忽略此Widget。
24+
25+
- ignoringSemantics → bool
26+
编译语义树的时候, 是否忽略此呈现对象的语义。
27+
28+
29+
当ignoring为true时,这个Widget(及其子树)对hit测试是不可见的。但它仍然在布局时消耗空间,并像往常一样绘制其子对象。并且它不能作为已定位事件的目标,因为它从renderbox.hittest返回false。
30+
31+
当ignoringsemantics为true时,语义层将看不到子树(例如 ccessibility 工具)。如果ignoringsemantics为空,则使用忽略的值。
32+
33+
## 使用示例
34+
35+
#### 1. 不填 ignoring 参数的情况:
36+
37+
```
38+
Widget getAbsorbPointerBody() {
39+
return Container(
40+
child: Listener(
41+
child: IgnorePointer(
42+
child: Listener(
43+
child: Container(
44+
color: Colors.red,
45+
),
46+
onPointerDown: (event)=>print("IgnorePointer Child Listener"),
47+
),
48+
),
49+
onPointerDown: (event)=>print("IgnorePointer Parent Listener"),
50+
),
51+
);
52+
}
53+
```
54+
55+
运行应用,无日志打印出来,说明触摸指针事件被拦截了。
56+
57+
58+
#### 2. ignoring = false 的情况:
59+
60+
```
61+
Widget getAbsorbPointerBody() {
62+
return Container(
63+
child: Listener(
64+
child: IgnorePointer(
65+
child: Listener(
66+
child: Container(
67+
color: Colors.black87,
68+
),
69+
onPointerDown: (event) =>
70+
print("onReceived IgnorePointer Child Listener"),
71+
),
72+
ignoring: false),
73+
onPointerDown: (event) =>
74+
print("onReceived IgnorePointer Parent Listener"),
75+
),
76+
);
77+
78+
```
79+
log 输出:
80+
81+
```
82+
21:24:57.268 37 info flutter.tools I/flutter ( 9081): onReceived IgnorePointer Child Listener
83+
21:24:57.268 38 info flutter.tools I/flutter ( 9081): onReceived IgnorePointer Parent Listener
84+
```
85+
86+
从日志可以看到,IgnorePointer Widget 的子部件中的 Pointer 事件也触发了,并且符合事件触发的时序,子部件先于父部件触发。

0 commit comments

Comments
 (0)