Flutter 手勢系列教程--Listener

Jimi 2021-09-18 14:25:07 阅读数:348

flutter 系列 教程 listener

Listener介紹

Listener它是主要的功能是用來監聽屏幕觸摸事件,取决於它的子組件區域範圍,比如按下、移動、抬起、取消等操作時可以添加監聽。

我們知道Flutter組件只有按鈕才會有事件,那麼如果我需要在文字或者某個容器上添加事件那我就需要借助Listener

視頻教程地址

手勢系列視頻教程地址

在什麼情况下使用Listener?

Listener常用於當手指滑動屏幕時進行隱藏鍵盤或者下拉刷新、上拉加載時進行事件監聽。

一般在實際的開發過程中我們很少會用到Listener來監聽手勢,一般都是通過GestureDetector來進行監聽或者使用MouseRegion來監聽鼠標的事件,而MouseRegion常用於web開發中,GestureDetector常用於app。

Listener原理

  • 當指針按下時,Flutter會對應用程序執行命中測試(Hit Test),以確定指針與屏幕接觸的比特置存在哪些組件(widget)
  • 指針按下事件(以及該指針的後續事件)然後被分發到由命中測試發現的最內部的組件
  • 事件會沿著最內部的組件向組件樹的根冒泡分發
  • 沒有機制取消或停止“冒泡”過程

Listener構造函數

我們經常使用的回調函數主要有三個

  • onPointerDown()
  • onPointerMove()
  • onpointUp()
const Listener({
Key key,
this.onPointerDown,
this.onPointerMove,
// We have to ignore the lint rule here in order to use deprecated
// parameters and keep backward compatibility.
// TODO(tongmu): After it goes stable, remove these 3 parameters from Listener
// and Listener should no longer need an intermediate class _PointerListener.
// https://github.com/flutter/flutter/issues/36085
@Deprecated(
'Use MouseRegion.onEnter instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.'
)
this.onPointerEnter,
@Deprecated(
'Use MouseRegion.onExit instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.'
)
this.onPointerExit,
@Deprecated(
'Use MouseRegion.onHover instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.'
)
this.onPointerHover,
this.onPointerUp,
this.onPointerCancel,
this.onPointerSignal,
this.behavior = HitTestBehavior.deferToChild,
Widget child,
}) : assert(behavior != null),
_child = child,
super(key: key);

Listener屬性和說明

字段 屬性 描述
onPointerDown PointerDownEventListener 指針按下時觸發回調
onPointerMove PointerMoveEventListener 指針移動時觸發回調
onPointerUp PointerUpEventListener 指針移開時觸發回調
onPointerSignal PointerSignalEventListener 當指針信號出現時調用
onPointerCancel PointerCancelEventListener 指針取消時觸發回調
onPointerEnter PointerEnterEventListener 當指針進入區域時回調(已廢弃)
onPointerExit PointerExitEventListener 當指針移出區域時回調(已廢弃)
onPointerHover PointerHoverEventListener 當沒有觸發 [onPointerDown] 的指針改變時調用
behavior HitTestBehavior 在命中測試期間如何錶現
child Widget 子組件

Listener基本使用

我們這裏主要是針對onPointerDownonPointerMoveonPointerUp 進行演示,因為我們在平時的開發過程中最常用到的屬性就是這三個,而且其他的屬性也都被廢弃掉了。

import 'package:flutter/material.dart';
class ListenerExample extends StatefulWidget {
@override
_ListenerExampleState createState() => _ListenerExampleState();
}
class _ListenerExampleState extends State<ListenerExample> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Listener"),
),
body: Center(
child: Stack(
children: [
Listener(
onPointerDown: (event) {
print("onPointerDown----$event");
},
onPointerMove: (event) {
print("onPointerMove----$event");
},
onPointerUp: (event) {
print("onPointerUp----$event");
},
// onPointerSignal: (event) {
// print("onPointerSignal----$event");
// },
// onPointerCancel: (event) {
// print("onPointerCancel----$event");
// },
// onPointerEnter: (event) {
// print("onPointerEnter----$event");
// },
// onPointerExit: (event) {
// print("onPointerExit----$event");
// },
// onPointerHover: (event) {
// print("onPointerHover----$event");
// },
child: Container(
color: Colors.pink,
child: Text("Jimi",
style: TextStyle(
color: Colors.white,
fontSize: 30
),
),
),
),
Positioned(
child: Listener(
onPointerDown: (event) {
print("red---- $event");
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
child: Text("Jimi"),
),
),
)
],
),
),
);
}
}

控制臺輸出

我們這裏先點擊柳丁色容器,在點擊一次紅色容器,他們打印的結果如下。

flutter: onPointerDown----PointerDownEvent#128be(position: Offset(204.5, 403.5))
flutter: onPointerUp----PointerUpEvent#a9558(position: Offset(204.5, 403.5))
flutter: red---- PointerDownEvent#8ffdf(position: Offset(140.5, 317.0))

PointerEvent介紹

PointerEvent是觸摸、手寫筆、鼠標事件的基類。

在上文中,我們知道了什麼是Listener並寫了一個簡單的案例,在使用案例的過程中我們的事件裏面都帶了一個event參數,而所有的事件最終都是繼承自PointerEvent,那我們接下來看看event的參數有什麼作用。

PointerEvent構造函數

const PointerEvent({
this.embedderId = 0,
this.timeStamp = Duration.zero,
this.pointer = 0,
this.kind = PointerDeviceKind.touch,
this.device = 0,
this.position = Offset.zero,
Offset? localPosition,
this.delta = Offset.zero,
Offset? localDelta,
this.buttons = 0,
this.down = false,
this.obscured = false,
this.pressure = 1.0,
this.pressureMin = 1.0,
this.pressureMax = 1.0,
this.distance = 0.0,
this.distanceMax = 0.0,
this.size = 0.0,
this.radiusMajor = 0.0,
this.radiusMinor = 0.0,
this.radiusMin = 0.0,
this.radiusMax = 0.0,
this.orientation = 0.0,
this.tilt = 0.0,
this.platformData = 0,
this.synthesized = false,
this.transform,
this.original,
}) : localPosition = localPosition ?? position,
localDelta = localDelta ?? delta;

PointerEvent屬性和說明

PointerEvent的屬性非常多,但在我們實際的開發過程中很少會使用到,只有在特定的情景下才會使用對應的屬性。

如需要做一個全局懸浮的按鈕我們會使用到position

如需要做繪圖軟件我們需要用到buttonskind

所以大家可以根據實際的應用場景來使用對應的屬性即可,下面是我對PointerEvent的屬性進行的一個詳細描述。

總共29個屬性
字段 屬性 描述
embedderId int 標識平臺事件ID
timeStamp Duration 事件調度時間
pointer int 指針唯一標識符,每一次點擊都會是一個新的,不會重複
kind PointerDeviceKind 指針事件的輸入設備類型
device int 設備唯一標識符,在交互中會重複使用
position Offset 指針相對於全局坐標的偏移
localPosition Offset 指針相對於當前容器坐標的偏移
delta Offset 兩次指針移動事件的距離
localDelta Offset 兩次指針移動事件的距離(當前容器)
buttons int 它是*button常量,經常與kind配合使用,做繪圖的畫筆軟件是經常用到該屬性,如果它的值為6,kind是PointerDeviceKind.invertedStylus,那麼這錶示一個倒置觸控筆
down bool 設置當前指針是否按下
obscured bool 是否遮擋應用程序的窗口,該屬性官方還沒實現
pressure double 按壓力度,壓力傳感器(如iPhone的3D Touch)中使用,取值0.0-1.0
pressureMin double 按壓力度最小值
pressureMax double 按壓力度最大值
distance double 檢測物體與輸入錶面的距離
distanceMin double 限制檢測物體與輸入錶面的距離最小值
distanceMax double 限制檢測物體與輸入錶面的距離最大值
size double 被按下屏幕的區域大小
radiusMajor double 接觸橢圓沿主軸的半徑,以邏輯像素為單比特
radiusMinor double 接觸橢圓沿短軸的半徑,以邏輯像素為單比特
radiusMin double radiusMajor和radiusMinor報告的最小值
radiusMax double radiusMajor和radiusMinor報告的最大值
orientation double 檢測到的物體的方向(指針移動方向),以弧度為單比特
tilt double 檢測到的物體的傾斜角度,以弧度為單比特
platformData int 與事件關聯的不透明平臺特定數據
synthesized bool 設置事件是否由 Flutter 合成。
transform Matrix4 用於從全局坐標轉換此事件的轉換
original PointerEvent 在任何transform之前的原始未轉換PointerEvent事件

behavior屬性

behavior屬性,它决定子組件如何響應命中測試,它的值類型為HitTestBehavior,這是一個枚舉類,有三個枚舉值

HitTestBehavior.deferToChild

對子組件一個接一個的進行命中測試,如果子組件中有測試通過的,則當前組件通過,這就意味著,如果指針事件作用於子組件上時,其父級組件也肯定可以收到該事件。

HitTestBehavior.opaque

在命中測試時,將當前組件當成不透明處理(即使本身是透明的),最終的效果相當於當前Widget的整個區域都是點擊區域

HitTestBehavior.translucent

點擊組件透明區域時,可以對自身邊界內及底部可視區域都進行命中測試,這意味著點擊頂部組件透明區域時,頂部組件和底部組件都可以接收到事件

代碼演示

import 'package:flutter/material.dart';
class ListenerSimpleExample extends StatefulWidget {
@override
_ListenerSimpleExampleState createState() => _ListenerSimpleExampleState();
}
class _ListenerSimpleExampleState extends State<ListenerSimpleExample> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
appBar: AppBar(
title: Text("Listener"),
),
body: Center(
child: Stack(
children: [
Listener(
child: ConstrainedBox(
constraints: BoxConstraints.tight(Size(400, 200)),
child: Container(
color: Colors.greenAccent,
)
),
onPointerDown: (event) => print("綠色盒子被點擊了"),
),
Listener(
child: ConstrainedBox(
constraints: BoxConstraints.tight(Size(400, 200)),
child: Center(child: Text("點擊文字", style: TextStyle(
color: Colors.white,
fontSize: 30
),)),
),
onPointerDown: (event) => print("文字點擊事件回調"),
behavior: HitTestBehavior.deferToChild,
// behavior: HitTestBehavior.opaque,
// behavior: HitTestBehavior.translucent,
)
],
),
),
);
}
}

當屬性設置為HitTestBehavior.deferToChild控制臺輸出結果

我們這裏演示每次都是先點擊綠色盒子在點擊文字,以便大家能更好的分辨出這三個屬性的使用區別

flutter: 綠色盒子被點擊了
flutter: 文字點擊事件回調

當屬性設置為HitTestBehavior.opaque控制臺輸出結果

flutter: 文字點擊事件回調
flutter: 文字點擊事件回調

當屬性設置為HitTestBehavior.translucent控制臺輸出結果

flutter: 文字點擊事件回調
flutter: 綠色盒子被點擊了
flutter: 文字點擊事件回調

總結

ListenerFlutter中比較重要的功能性組件,它主要的功能是用來監聽屏幕觸摸事件,事件回調可以獲取對應的屬性來個性化定制app功能。

版权声明:本文为[Jimi]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918142506533C.html