Flutter cơ bản-Hướng dẫn tạo GestureDetector Widget với thao tác di chuyển và phóng to thu nhỏ hình ảnh
Đăng lúc: 09:16 AM - 07/06/2024 bởi Charles Chung - 520Gestures là một tính năng trong Flutter cho phép chúng ta tương tác với ứng dụng di động qua màn hình cảm ứng, trong bài viết này tôi sẽ hướng dẫn các bạn tạo một GestureDetector Widget với thao tác di chuyển và phóng to thu nhỏ hình ảnh.
1. Yêu cầu chung
- Có kiến thức về lập trình Dart
- Máy đã cài đặt môi trường phát triển ứng dụng Flutter
2. Mô tả về cử chỉ trên màn hình cảm ứng
- Khi màn hình di động bị khóa, bạn trượt ngón tay trên màn hình để mở khóa.
- Nhấn vào một nút trên màn hình điện thoại di động của bạn và
- Nhấn và giữ biểu tượng ứng dụng trên thiết bị dựa trên cảm ứng để kéo biểu tượng đó qua các màn hình.
Tap − Chạm vào bề mặt thiết bị bằng đầu ngón tay trong thời gian ngắn sau đỏ thả ngón tay ra ngay
Double Tap − Tap 2 lần trong thời gian ngắn
Drag − Chạm vào bề mặt của thiết bị bằng đầu ngón tay và sau đó di chuyển đầu ngón tay một cách ổn định và cuối cùng thả ngón tay ra.
Flick − Tương tự như drag nhưng thực hiện nhanh hơn.
Pinch − Chụm bề mặt của thiết bị bằng hai ngón tay
Spread/Zoom − Ngược lại với Pinch.
Panning − Chạm vào bề mặt của thiết bị bằng đầu ngón tay và di chuyển nó theo bất kỳ hướng nào mà không nhả đầu ngón tay.
3. Giới thiệu GestureDetector Widget
Flutter cung cấp một sự hỗ trợ tuyệt vời để xử lý tất cả các loại cử chỉ thông qua một tiện ích duy nhất GestureDetector. Để xác định các cử chỉ tác động lên một widget, ta chỉ cần đặt widget đó bên trong GestureDetector widget. GestureDetector sẽ bắt các cử chỉ và gửi nhiều sự kiện dựa trên cử chỉ đó.
4. Sử dụng GestureDetector
Ví dụ sau đây sẽ thực hiện việc zoom in/out một hình ảnh sử dụng cử chỉ Scale của GestureDetector Widget
- Tạo project Flutter: các bạn có thể thực hiện theo 2 cách:
- Mở Android Studio -> tạo project flutter với tên "GestureZoomImage"
- Gõ lệnh tạo project tại dòng lệnh
flutter create example_validate_form
- Cấu trúc các widget trên màn hình
- Mở file main.dart code khung cơ bản theo gợi ý sau
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Example01-Lab12', home: MyBox(), debugShowCheckedModeBanner: false, ); } } class MyBox extends StatefulWidget { @override State<MyBox> createState() => _MyBoxState(); } class _MyBoxState extends State<MyBox> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Thao tác cử chỉ trên mobile'),), body: Stack( fit: StackFit.expand, children: [ Container( padding: EdgeInsets.all(10), color: Colors.white60, child: Text('Chạm vào hình giữ và kéo hoặc zoom',style: TextStyle(fontSize: 26),), ), ], ), ); } }
- Tạo thư mục assets/images trong project sau đó copy hình ảnh bạn muốn vào đó -> cấu hình assets trong tệp pubspec.yaml
- Để điều khiển cử chỉ bạn cần tạo một GestureDetector widget chứa một hình ảnh bên trong và đăng ký sự kiện Scale, hãy xem đoạn code sau
Positioned( top: 0, //giá trị này sẽ phải cập nhật lại khi sự kiện thay đổi left: 0, //giá trị này sẽ phải cập nhật lại khi sự kiện thay đổi child: GestureDetector( onScaleStart: (detail){}, //sự kiện bắt đầu thay đổi onScaleUpdate:(detail){}, //sự kiện cập nht thay đổi child: SizedBox( width: 100, //giá trị này sẽ phải cập nhật lại khi sự kiện thay đổi height: 100, //giá trị này sẽ phải cập nhật lại khi sự kiện thay đổi child: const CircleAvatar(backgroundImage: AssetImage("assets/icon-support.png"), backgroundColor: Colors.white60,), ), ) )
Như vậy chúng ta cần khai báo các biến lưu trữ vị trí ban đầu, và vị trí sẽ thay đổi của Positioned và tỉ lệ zoom của SizeBox, tiếp theo cần cập nhật lại các giá trị và tỉ lệ zoom trong 2 sự kiện Scale. đoạn code hoàn chỉnh của lớp _MyBoxState như sau:
class _MyBoxState extends State<MyBox> { //tiêu điểm bắt đầu late Offset _startingFocalPoint; //vị trí trước late Offset _previousOffset; //vị trí hiện tại Offset _offset = Offset.zero; //giá trị zoom trước late double _previousZoom; //giá trị zoom ban đầu double _zoom = 1.0; //kích thước hình ban đầu final containerSize = const Size(100, 100); //phương thức đáp ứng sự kiện bắt đầu thay đổi tỉ lệ void _handleScaleStart(ScaleStartDetails details) { setState(() { _startingFocalPoint = details.focalPoint; _previousOffset = _offset; _previousZoom = _zoom; }); } //phương thức đáp ứng sự kiện cập nhật lại giá trị khi thay đổi void _handleScaleUpdate(ScaleUpdateDetails details) { setState(() { _zoom = _previousZoom * details.scale; final Offset normalizedOffset = (_startingFocalPoint - _previousOffset) / _previousZoom; _offset = details.focalPoint - normalizedOffset * _zoom; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Thao tác cử chỉ trên mobile'),), body: Stack( fit: StackFit.expand, children: [ Container( padding: EdgeInsets.all(10), color: Colors.white60, child: Text('Chạm vào hình giữ và kéo hoặc zoom',style: TextStyle(fontSize: 26),), ), Positioned( top: _offset.dy, left: _offset.dx, child: GestureDetector( onScaleStart: _handleScaleStart, //sự kiện bắt đầu thay đổi onScaleUpdate:_handleScaleUpdate, //sự kiện cập nht thay đổi child: SizedBox( width: containerSize.width * _zoom, height: containerSize.height * _zoom, child: const CircleAvatar(backgroundImage: AssetImage("assets/icon-support.png"), backgroundColor: Colors.white60,), ), ) ), ], ), ); } }
- Chạy ứng dụng và kiểm tra kết quả
thay lời cảm ơn!
Các bài cũ hơn
- Flutter cơ bản-Hướng dẫn xây dựng, Validating và Styling cho các Field trên Form trong Flutter (10:18 AM - 06/06/2024)
- Bảo mật phân quyền người dùng trong ứng dụng Web với Spring Boot 3 Security (03:02 PM - 03/06/2024)
- Hướng dẫn cài đặt môi trường lập trình Dart và Flutter trên Windows 10 từ A-Z (03:47 PM - 15/05/2024)
- Phát hiện khuôn mặt người trong ảnh sử dụng thư viện Haar Cascade với OpenCV-Python (09:53 AM - 27/03/2024)
- Hướng dẫn đăng nhập trên trang chủ và trang quản trị Spring MVC-MongoDB (05:58 PM - 21/03/2024)