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

update demo gesture password #34

Merged
merged 1 commit into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,18 @@ Map<String, WidgetBuilder> routers = {
return un_bounded_listview.UnboundedListViewDemoPage();
});
},
"PageView嵌套PageView": (context) {
return ContainerAsyncRouterPage(
pageview_in_pageview_demo_page.loadLibrary(), (context) {
return pageview_in_pageview_demo_page.PageViewInPageViewDemoPage();
});
},
"手势密码": (context) {
return ContainerAsyncRouterPage(gesture_password_demo_page.loadLibrary(),
(context) {
return gesture_password_demo_page.GesturePasswordDemoPage();
});
},
};

```
Expand Down
9 changes: 9 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ import 'package:gsy_flutter_demo/widget/un_bounded_listview.dart'
import 'package:gsy_flutter_demo/widget/pageview_in_pageview_demo_page.dart'
deferred as pageview_in_pageview_demo_page;

import 'package:gsy_flutter_demo/widget/gesture_password/gesture_password_demo_page.dart'
deferred as gesture_password_demo_page;

import 'package:window_location_href/window_location_href.dart';

void main() => runApp(const MyApp());
Expand Down Expand Up @@ -917,6 +920,12 @@ Map<String, WidgetBuilder> routers = {
return pageview_in_pageview_demo_page.PageViewInPageViewDemoPage();
});
},
"手势密码": (context) {
return ContainerAsyncRouterPage(gesture_password_demo_page.loadLibrary(),
(context) {
return gesture_password_demo_page.GesturePasswordDemoPage();
});
},
};

enum Cat {
Expand Down
44 changes: 44 additions & 0 deletions lib/widget/gesture_password/gesture_password_demo_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:gsy_flutter_demo/widget/gesture_password/gesture_password_view.dart';
import 'package:gsy_flutter_demo/widget/link_sliver/link_flexible_space_bar.dart';

class GesturePasswordDemoPage extends StatefulWidget {
const GesturePasswordDemoPage({super.key});

@override
_GesturePasswordDemoState createState() => _GesturePasswordDemoState();
}

class _GesturePasswordDemoState extends State<GesturePasswordDemoPage> {
String _pwd = '';

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("手势密码"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 300,
height: 300,
child: GesturePasswordView(
pathWidth: 6,
frameRadius: 30,
onDone: (value) {
setState(() {
_pwd = value.join();
});
},
),
),
Text("当前密码: $_pwd"),
],
),
),
);
}
}
87 changes: 87 additions & 0 deletions lib/widget/gesture_password/gesture_password_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'package:flutter/material.dart';

import 'src/gesture_view_controller.dart';
import 'src/gesture_view_path.dart';
import 'src/gesture_view_point.dart';

class GesturePasswordView extends StatefulWidget {

/// 圆圈半径
final double frameRadius;

/// 圆圈中心点半径
final double pointRadius;

/// 圆圈普通状态下颜色
final Color color;

/// 圆圈选中颜色
final Color highlightColor;

/// 连线颜色
final Color pathColor;

/// 连线半径
final double pathWidth;

/// 手势结果
final Function(List<int>)? onDone;

const GesturePasswordView({
super.key,
this.pointRadius = 10,
this.frameRadius = 40,
this.color = Colors.grey,
this.highlightColor = Colors.blue,
this.pathColor = Colors.blue,
this.onDone,
this.pathWidth = 5,
});

@override
State<StatefulWidget> createState() => _GesturePasswordState();
}

class _GesturePasswordState extends State<GesturePasswordView> {
final GestureViewController controller = GestureViewController();

@override
void initState() {
controller.initParameters(
pointRadius: widget.pointRadius,
frameRadius: widget.frameRadius,
color: widget.color,
highlightColor: widget.highlightColor,
pathColor: widget.pathColor,
onFinishGesture: widget.onDone,
pathWidth: widget.pathWidth,
updateView: (){
setState(() {});
}
);
WidgetsBinding.instance.addPostFrameCallback((_) => controller.setPointValues());
super.initState();
}

@override
Widget build(BuildContext context) {
return SizedBox(
key: controller.globalKey,
width: double.infinity,
height: double.infinity,
child: Stack(
children: [
GestureDotsPanelWidget(points: controller.point),
GestureViewPathWidget(
points: controller.pathPoint,
pathWidth: controller.pathWidth,
color: controller.pathColor,
onPanDown: controller.onPanDown,
onPanEnd: controller.onPanEnd,
onPanUpdate: controller.onPanUpdate,
),
],
),
);
}
}
141 changes: 141 additions & 0 deletions lib/widget/gesture_password/src/gesture_view_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import 'package:flutter/material.dart';

import 'gesture_view_model.dart';

class GestureViewController {
final List<GesturePasswordPointModel> _points = [];
final List<Offset> _pathPoint = [];
final GlobalKey globalKey = GlobalKey();
double _frameRadius = 0.0;
double _pointRadius = 0.0;
Color _color = Colors.grey;
Color _highlightColor = Colors.blue;
Color _pathColor = Colors.blue;
Function(List<int>)? _onFinishGesture;
double _pathWidth = 5;
Function()? _updateView;
Offset? _firstPoint;
Offset? _movePoint;
List<int> _result = [];
}

extension Data on GestureViewController {
List<GesturePasswordPointModel> get point => _points;

List<Offset> get pathPoint {
List<Offset> tempPathPoint = [];
tempPathPoint.addAll(_pathPoint);
if (_movePoint != null) {
tempPathPoint.add(_movePoint!);
}
return tempPathPoint;
}

Color get pathColor => _pathColor;

double get pathWidth => _pathWidth;

}

extension Private on GestureViewController {
void _initPoint() {
_points.addAll(List.generate(
9,
(index) => GesturePasswordPointModel(
index: index,
frameRadius: _frameRadius,
pointRadius: _pointRadius,
color: _color,
highlightColor: _highlightColor,
pathColor: _pathColor,
),
));
}

double _getPointWidth(double width) => width / 3;
}

extension Public on GestureViewController {
void initParameters({
double frameRadius = 0.0,
double pointRadius = 0.0,
Color color = Colors.grey,
Color highlightColor = Colors.blue,
Color pathColor = Colors.blue,
Function(List<int>)? onFinishGesture,
Function()? updateView,
double pathWidth = 5,
}) {
_frameRadius = frameRadius;
_pointRadius = pointRadius;
_color = color;
_highlightColor = highlightColor;
_pathColor = pathColor;
_onFinishGesture = onFinishGesture;
_updateView = updateView;
_pathWidth = pathWidth;
_initPoint();
}

void setPointValues() {
try {
Size size = globalKey.currentContext?.size ?? Size.zero;
double pointWidth = _getPointWidth(size.width);
List<Offset> pointCenter = [];
for (int x = 1; x <= 3; x++) {
for (int y = 1; y <= 3; y++) {
Offset center = Offset((y - 1) * pointWidth + pointWidth / 2,
(x - 1) * pointWidth + pointWidth / 2);
pointCenter.add(center);
}
}
for (int index = 0; index < pointCenter.length; index++) {
_points[index].centerPoint = pointCenter[index];
}
} catch (_) {}
}
}

extension Tap on GestureViewController {
void onPanDown(DragDownDetails e) {
for (var item in _points) {
if (item.containPoint(e.localPosition)) {
item.selected = true;
_firstPoint = e.localPosition;
_pathPoint.add(item.centerPoint);
_updateView?.call();
_result.add(item.index);
break;
}
}
}

void onPanUpdate(DragUpdateDetails e) {
if (_firstPoint == null) return;
_movePoint = e.localPosition;
for (var item in _points) {
if (item.containPoint(e.localPosition)) {
if (!item.selected) {
item.selected = true;
_pathPoint.add(item.centerPoint);
_result.add(item.index);
}
break;
}
}
_updateView?.call();
}

void onPanEnd(DragEndDetails e) {
_firstPoint = null;
_movePoint = null;

_onFinishGesture?.call(_result);
_result.clear();
for (var element in _points) {
element.selected = false;
}
_pathPoint.clear();
_updateView?.call();
}
}
43 changes: 43 additions & 0 deletions lib/widget/gesture_password/src/gesture_view_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

import 'dart:math';
import 'package:flutter/material.dart';

class GesturePasswordPointModel {
Offset centerPoint = Offset.zero;
bool selected = false;
double frameRadius;
double pointRadius;
Color color = Colors.grey;
Color highlightColor = Colors.blue;
Color pathColor = Colors.blue;
int index = 0;

GesturePasswordPointModel({
this.index = 0,
this.centerPoint = Offset.zero,
this.frameRadius = 0.0,
this.pointRadius = 0.0,
this.selected = false,
this.color = Colors.grey,
this.highlightColor = Colors.blue,
this.pathColor = Colors.blue,
});


Color get pointColor{
return selected ? highlightColor : color;
}
Color get frameColor => selected ? highlightColor : color;

bool containPoint(Offset offset){
return distanceTo(offset, centerPoint) <= frameRadius;
}


double distanceTo(Offset f1, Offset f2){
var dx= f1.dx - f2.dx;
var dy= f1.dy - f2.dy;
return sqrt(dx * dx + dy * dy);
}

}
Loading
Loading