• 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
  • 相关阅读:
    参数传递(值传递与引用传递)
    存入redis中的java对象都需要序列化
    windows环境Apache服务器启动失败的原因
    IDEA/Eclipse安装 Alibaba Java Coding Guidelines 插件
    使用freemarker对模板进行渲染
    java使用freemarker作为模板导出Excel表格
    mybatis 中 foreach collection的三种用法
    利用freemarker导出页面格式复杂的excel
    mysql limit和offset用法
    设计模式之二十一:中介者模式(Mediator)
  • 原文地址:https://www.cnblogs.com/devin_zhou/p/8052305.html
Copyright © 2020-2023  润新知