UWP 手势密码实现

UWP 手势密码实现

通过在画布canvas上绘制实现手势密码:

主要问题:

1. 图形绘制

  • 实心圆
  • 空心圆
  • 线段

2. Touch事件处理

  • ManipulationStarted
  • ManipulationDelta
  • ManipulationCompleted

3. 各个圆坐标计算

4. 圆圈的选中逻辑

  • 判断点是否在圆内
  • 判断选中的两个圆心连线是否经过一个圆,如果是则该圆也是选中

Xaml布局:

1<UserControl2x:Class="MyPassword.UWP.Control.GesturePassword"3xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"4xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"5xmlns:local="using:MyPassword.UWP.Control"6xmlns:d="http://schemas.microsoft.com/expression/blend/2008"7xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"8mc:Ignorable="d"9xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"10d:DesignHeight="300"11d:DesignWidth="400">1213<GridBackground="Transparent">14<canvas:CanvasControlx:Name="canvas"Draw="Canvas_Draw"Loaded="Canvas_Loaded"></canvas:CanvasControl>15</Grid>16</UserControl>
View Code

C#

  1 using MyPassword.Utils;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.IO;
  5 using System.Linq;
  6 using System.Numerics;
  7 using System.Runtime.InteropServices.WindowsRuntime;
  8 using Windows.Foundation;
  9 using Windows.Foundation.Collections;
 10 using Windows.UI;
 11 using Windows.UI.Xaml;
 12 using Windows.UI.Xaml.Controls;
 13 using Windows.UI.Xaml.Controls.Primitives;
 14 using Windows.UI.Xaml.Data;
 15 using Windows.UI.Xaml.Input;
 16 using Windows.UI.Xaml.Media;
 17 using Windows.UI.Xaml.Navigation;
 18 
 19 // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
 20 
 21 namespace MyPassword.UWP.Control
 22 {
 23     public sealed partial class GesturePassword : UserControl
 24     {
 25 
 26         private const int Circle_R = 20;
 27         private const int Distance = 40;
 28         private const int Circle_r = 3;
 29 
 30         private const int Length = 3 * Circle_R * 2 + Distance * 2;
 31 
 32         private double ViewWidth = 0;
 33         private double ViewHight = 0;
 34         private double MyPadding = 0;
 35 
 36         private int X_Zero = 0;
 37         private int Y_Zero = 0;
 38         
 39 
 40         private List<Vector2> pointList = new List<Vector2>();
 41 
 42         private List<Vector2> checkedList = new List<Vector2>();
 43 
 44         private List<Vector2> drawList = new List<Vector2>();
 45 
 46         private List<int> indexList = new List<int>();
 47 
 48         public delegate void CheckCompeleteDelegate(List<int> checkList);
 49 
 50         private CheckCompeleteDelegate _CheckCompeleteDelegate;
 51 
 52         public event CheckCompeleteDelegate CheckCompeleteEvent
 53         {
 54             add
 55             {
 56                 _CheckCompeleteDelegate = Delegate.Combine(_CheckCompeleteDelegate, value) as CheckCompeleteDelegate;
 57             }
 58             remove
 59             {
 60                 _CheckCompeleteDelegate = Delegate.Remove(_CheckCompeleteDelegate, value) as CheckCompeleteDelegate;
 61             }
 62         }
 63 
 64         public GesturePassword()
 65         {
 66             this.InitializeComponent();
 67             Loaded += GesturePassword_Loaded;
 68             Unloaded += GesturePassword_Unloaded;
 69         }
 70 
 71 
 72         
 73 
 74         private void GesturePassword_Loaded(object sender, RoutedEventArgs e)
 75         {
 76             canvas.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
 77             canvas.ManipulationCompleted += Canvas_ManipulationCompleted;
 78             canvas.ManipulationDelta += Canvas_ManipulationDelta;
 79             canvas.ManipulationStarted += Canvas_ManipulationStarted;
 80         }
 81 
 82       
 83 
 84         private double touch_x = 0;
 85         private double touch_y = 0;
 86 
 87         private void Canvas_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
 88         {
 89             touch_x = e.Position.X;
 90             touch_y = e.Position.Y;
 91             ProcessTouchEvent(touch_x, touch_y);
 92         }
 93 
 94         private void Canvas_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
 95         {
 96             touch_x = e.Position.X;
 97             touch_y = e.Position.Y;
 98             ProcessTouchEvent(touch_x,touch_y);
 99         }
100 
101         private void Canvas_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
102         {
103 
104             GetCheckedIndex();
105             if (_CheckCompeleteDelegate != null)
106             {
107                 _CheckCompeleteDelegate.Invoke(indexList);
108             }
109             Reset();
110         }
111 
112         private void GetCheckedIndex()
113         {
114             indexList.Clear();
115             //DebugUtil.WriteLine("Count == " + checkedList.Count);
116             foreach (var item in checkedList)
117             {
118                 int index = pointList.IndexOf(item);
119                 indexList.Add(index);
120                 //DebugUtil.WriteLine("index == " +index);
121             }
122             //DebugUtil.WriteLine("Size == " + indexList.Count);
123         }
124 
125 
126         private void ProcessTouchEvent(double x,double y)
127         {
128             if (x < 0 || y < 0 || x > 320 || y > 320)
129             {
130 
131             }
132             else
133             {
134                 Vector2 item = CheckRange(x, y, out bool isIn);
135                 if (isIn && !IsAdded(item))
136                 {
137                     if (checkedList.Count > 0)
138                     {
139                         var item2 = checkedList.Last();
140                         foreach (Vector2 v in pointList)
141                         {
142                             if (item != v && !IsAdded(v) && CheckOnLine(item, item2, v))
143                             {
144                                 checkedList.Add(v);
145                             }
146                         }
147                     }
148                     checkedList.Add(item);
149                 }
150                 else
151                 {
152                     drawList.Clear();
153                     drawList.AddRange(checkedList);
154                     drawList.Add(item);
155                 }
156                 canvas.Invalidate();
157             }
158         }
159 
160         /// <summary>
161         /// 判断 v 是否在 v1、v2连线内  用了最粗暴的方法  
162         /// </summary>
163         /// <param name="v1"></param>
164         /// <param name="v2"></param>
165         /// <param name="v"></param>
166         /// <returns></returns>
167         private bool CheckOnLine(Vector2 v1,Vector2 v2,Vector2 v)
168         {
169             double len = CalcLengthBetweenTwoPoint(v1,v2);
170             double len1 = CalcLengthBetweenTwoPoint(v1, v);
171             double len2 = CalcLengthBetweenTwoPoint(v2, v);
172             return len == len1 + len2;
173         }
174 
175         /// <summary>
176         /// 计算v1、v2连线长度
177         /// </summary>
178         /// <param name="v1"></param>
179         /// <param name="v2"></param>
180         /// <returns></returns>
181         private double CalcLengthBetweenTwoPoint(Vector2 v1, Vector2 v2)
182         {
183             double value = Math.Pow(v1.X - v2.X, 2.0) + Math.Pow(v1.Y - v2.Y, 2.0);
184             //return value;
185             return Math.Abs(Math.Sqrt(value));
186         }
187 
188         /// <summary>
189         /// 判断x、y 是否在其中一个圆内
190         /// </summary>
191         /// <param name="x"></param>
192         /// <param name="y"></param>
193         /// <param name="isIn"></param>
194         /// <returns></returns>
195         private Vector2 CheckRange(double x ,double y,out bool isIn)
196         {
197             foreach (Vector2 v in pointList)
198             {
199                 if (IsInCircle(x, y, v) && !IsAdded(v))
200                 {
201                     isIn = true;
202                     return v;
203                 }
204             }
205             isIn = false;
206             return new Vector2 { X = (int)x,Y = (int)y};
207 
208         }
209 
210         /// <summary>
211         /// 判断x、y 是否在 v 为圆心 Circle_R 为半径的圆内
212         /// </summary>
213         /// <param name="x"></param>
214         /// <param name="y"></param>
215         /// <param name="v"></param>
216         /// <returns></returns>
217         private bool IsInCircle(double x, double y,Vector2 v)
218         {
219             return Math.Pow(x - v.X, 2.0) + Math.Pow(y - v.Y, 2.0) <= Math.Pow(Circle_R, 2.0);  
220         }
221 
222         /// <summary>
223         /// 判断item 是否已经选中
224         /// </summary>
225         /// <param name="item"></param>
226         /// <returns></returns>
227         private bool IsAdded(Vector2 item)
228         {
229             return checkedList.Contains(item);
230         }
231 
232         /// <summary>
233         /// 初始化 原始数据
234         /// </summary>
235         private void InitPointList()
236         {
237             int deta_x = 0;
238             int deta_y = 0;
239             int x = 0;
240             int y = 0;
241             for (int i = 0; i < 9; i++)
242             {
243                 deta_x = i % 3;
244                 deta_y = i / 3;
245                 x = X_Zero + deta_x * (Distance + 2 * Circle_R);
246                 y = Y_Zero + deta_y * (Distance + 2 * Circle_R);
247 
248                 pointList.Add(new Vector2
249                 {
250                     X = x,
251                     Y = y
252                 });
253                 
254             }
255         }
256 
257         
258         private void Canvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender,Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
259         {
260 
261             int size = pointList.Count;
262             for (int i = 0; i < size; i++)//绘制元素点图
263             {
264                 Vector2 item = pointList.ElementAt(i);
265                 args.DrawingSession.DrawCircle(item,Circle_R, Colors.Blue,3);
266                 args.DrawingSession.DrawCircle(item, 0, Colors.Blue, 6);
267             }
268             size = drawList.Count;
269             for (int i = 0; i < size; i++)//绘制选中点图
270             {
271                 Vector2 item = drawList.ElementAt(i);
272                 args.DrawingSession.DrawCircle(item, 0, Colors.Red, 6);
273                 if (i < size - 1)
274                 {
275                     Vector2 item2 = drawList.ElementAt(i+1);
276                     args.DrawingSession.DrawLine(item, item2, Colors.Red, 3);
277                     args.DrawingSession.DrawCircle(item, Circle_R, Colors.Red, 3);
278                 }
279             }
280         }
281 
282         private void GesturePassword_Unloaded(object sender, RoutedEventArgs e)
283         {
284             canvas.RemoveFromVisualTree();
285             canvas = null;
286         }
287 
288         private void Canvas_Loaded(object sender, RoutedEventArgs e)
289         {
290             ViewWidth = canvas.ActualWidth;
291             ViewHight = canvas.ActualHeight;
292             MyPadding = (ViewWidth - Length) / 2;
293             X_Zero = (int)MyPadding + Circle_R;
294             Y_Zero = (int)MyPadding + Circle_R;
295             InitPointList();
296         }
297 
298         public void Reset()
299         {
300             checkedList.Clear();
301             drawList.Clear();
302             canvas.Invalidate();
303         }
304     }
305 }
View Code
原文地址:https://www.cnblogs.com/devin_zhou/p/8052305.html