• Xamarin.Android 手势密码


    Xamarin.Android 手势密码

    主要问题:

    1. 图形绘制

    • 实心圆
    • 空心圆
    • 线段

    2. Touch事件处理

    •  MotionEventActions.Down
    •  MotionEventActions.Move
    • MotionEventActions.Up

    3. 各个圆坐标计算

    4. 圆圈的选中逻辑

    • 判断点是否在圆内
    • 判断选中的两个圆心连线是否经过一个圆,如果是则该圆也是选中
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 
      6 using Android.App;
      7 using Android.Content;
      8 using Android.Graphics;
      9 using Android.OS;
     10 using Android.Runtime;
     11 using Android.Util;
     12 using Android.Views;
     13 using Android.Widget;
     14 using static Android.Views.View;
     15 using MyPassword.Droid.Utils;
     16 using MyPassword.Utils;
     17 
     18 namespace MyPassword.Droid.Views
     19 {
     20     public class GestureLockView : View,IOnTouchListener
     21     {
     22 
     23 
     24         private  int Circle_R = 20;
     25         private  int Distance = 40;
     26         private  int Circle_r = 3;
     27 
     28         private int Length = 0;
     29 
     30         private double ViewWidth = 0;
     31         private double ViewHight = 0;
     32         private double MyPadding = 0;
     33 
     34         private int X_Zero = 0;
     35         private int Y_Zero = 0;
     36 
     37 
     38 
     39         private List<Vector2> pointList = new List<Vector2>();
     40 
     41         private List<Vector2> checkedList = new List<Vector2>();
     42 
     43         private List<Vector2> drawList = new List<Vector2>();
     44 
     45         private List<int> indexList = new List<int>();
     46 
     47         Paint paint;
     48 
     49         public delegate void CheckCompeleteDelegate(List<int> checkList);
     50 
     51         private CheckCompeleteDelegate _CheckCompeleteDelegate;
     52 
     53         public event CheckCompeleteDelegate CheckCompeleteEvent
     54         {
     55             add
     56             {
     57                 _CheckCompeleteDelegate = Delegate.Combine(_CheckCompeleteDelegate, value) as CheckCompeleteDelegate;
     58             }
     59             remove
     60             {
     61                 _CheckCompeleteDelegate = Delegate.Remove(_CheckCompeleteDelegate, value) as CheckCompeleteDelegate;
     62             }
     63         }
     64 
     65 
     66         private void GetCheckedIndex()
     67         {
     68             indexList.Clear();
     69             foreach (var item in checkedList)
     70             {
     71                 int index = pointList.IndexOf(item);
     72                 indexList.Add(index);
     73 
     74             }
     75         }
     76 
     77         public GestureLockView(Context context, IAttributeSet attrs) :
     78             base(context, attrs)
     79         {
     80             Initialize();
     81         }
     82 
     83         public GestureLockView(Context context, IAttributeSet attrs, int defStyle) :
     84             base(context, attrs, defStyle)
     85         {
     86             Initialize();
     87         }
     88 
     89         private void Initialize()
     90         {
     91             Circle_r = DensityUtil.Dp2px(Context,3f);
     92             Circle_R = DensityUtil.Dp2px(Context, 20f);
     93             Distance = DensityUtil.Dp2px(Context, 40f);
     94             Length = 3 * Circle_R * 2 + Distance * 2;
     95             ViewWidth = DensityUtil.Dp2px(Context, 320f);
     96             ViewHight = DensityUtil.Dp2px(Context, 320f);
     97 
     98             MyPadding = (ViewWidth - Length) / 2;
     99             X_Zero = (int)MyPadding + Circle_R;
    100             Y_Zero = (int)MyPadding + Circle_R;
    101             paint = new Paint();
    102             SetOnTouchListener(this);
    103             InitPointList();
    104             PostInvalidate();
    105         }
    106 
    107 
    108 
    109 
    110         protected override void OnDraw(Canvas canvas)
    111         {
    112             base.OnDraw(canvas);
    113 
    114             int size = pointList.Count;
    115             paint.StrokeWidth = 6;
    116             paint.AntiAlias = true;
    117             for (int i = 0; i < size; i++)//绘制元素点图
    118             {
    119                 Vector2 item = pointList.ElementAt(i);
    120                 paint.Color = Color.Blue;
    121                 paint.SetStyle(Paint.Style.Fill);//设置为实心
    122                 canvas.DrawCircle(item.X, item.Y, Circle_r,paint);
    123                 paint.SetStyle(Paint.Style.Stroke);//设置为空心
    124                 canvas.DrawCircle(item.X, item.Y, Circle_R, paint);
    125             }
    126             size = drawList.Count;
    127             for (int i = 0; i < size; i++)//绘制选中点图
    128             {
    129                 Vector2 item = drawList.ElementAt(i);
    130                 paint.Color = Color.Red;
    131                 paint.SetStyle(Paint.Style.Fill);//设置为实心
    132                 canvas.DrawCircle(item.X, item.Y, Circle_r, paint);
    133                 if (i < size - 1)
    134                 {
    135                     Vector2 item2 = drawList.ElementAt(i + 1);
    136                     paint.Color = Color.Red;
    137                     canvas.DrawLine(item.X, item.Y, item2.X, item2.Y, paint);
    138                     paint.SetStyle(Paint.Style.Stroke);//设置为空心
    139                     canvas.DrawCircle(item.X, item.Y, Circle_R, paint);
    140                 }
    141             }
    142 
    143         }
    144 
    145 
    146         public void Reset()
    147         {
    148             checkedList.Clear();
    149             drawList.Clear();
    150             PostInvalidate();
    151         }
    152 
    153 
    154         private double touch_x = 0;
    155         private double touch_y = 0;
    156 
    157         public bool OnTouch(View v, MotionEvent e)
    158         {
    159             switch (e.Action)
    160             {
    161                 case MotionEventActions.Down:
    162                 case MotionEventActions.Move:
    163                     touch_x = e.GetX();
    164                     touch_y = e.GetY();
    165                     ProcessTouchEvent(touch_x, touch_y);
    166                     break;
    167                 case MotionEventActions.Up:
    168                     GetCheckedIndex();
    169                     if (_CheckCompeleteDelegate != null)
    170                     {
    171                         _CheckCompeleteDelegate.Invoke(indexList);
    172                     }
    173                     Reset();
    174                     break;
    175             }
    176             return true;
    177         }
    178 
    179 
    180         private void ProcessTouchEvent(double x, double y)
    181         {
    182             if (x < 0 || y < 0 || x > ViewWidth || y > ViewHight)
    183             {
    184 
    185             }
    186             else
    187             {
    188                 Vector2 item = CheckRange(x, y, out bool isIn);
    189                 if (isIn && !IsAdded(item))
    190                 {
    191                     if (checkedList.Count > 0)
    192                     {
    193                         var item2 = checkedList.Last();
    194                         foreach (Vector2 v in pointList)
    195                         {
    196                             if (item != v && !IsAdded(v) && CheckOnLine(item, item2, v))
    197                             {
    198                                 checkedList.Add(v);
    199                             }
    200                         }
    201                     }
    202                     checkedList.Add(item);
    203                 }
    204                 else
    205                 {
    206                     drawList.Clear();
    207                     drawList.AddRange(checkedList);
    208                     drawList.Add(item);
    209                 }
    210                 PostInvalidate();
    211             }
    212         }
    213 
    214 
    215 
    216         /// <summary>
    217         /// 判断 v 是否在 v1、v2连线内  用了最粗暴的方法  
    218         /// </summary>
    219         /// <param name="v1"></param>
    220         /// <param name="v2"></param>
    221         /// <param name="v"></param>
    222         /// <returns></returns>
    223         private bool CheckOnLine(Vector2 v1, Vector2 v2, Vector2 v)
    224         {
    225             double len = CalcLengthBetweenTwoPoint(v1, v2);
    226             double len1 = CalcLengthBetweenTwoPoint(v1, v);
    227             double len2 = CalcLengthBetweenTwoPoint(v2, v);
    228             return len == len1 + len2;
    229         }
    230 
    231         /// <summary>
    232         /// 计算v1、v2连线长度
    233         /// </summary>
    234         /// <param name="v1"></param>
    235         /// <param name="v2"></param>
    236         /// <returns></returns>
    237         private double CalcLengthBetweenTwoPoint(Vector2 v1, Vector2 v2)
    238         {
    239             double value = Math.Pow(v1.X - v2.X, 2.0) + Math.Pow(v1.Y - v2.Y, 2.0);
    240 
    241             return Math.Abs(Math.Sqrt(value));
    242         }
    243 
    244         /// <summary>
    245         /// 判断x、y 是否在其中一个圆内
    246         /// </summary>
    247         /// <param name="x"></param>
    248         /// <param name="y"></param>
    249         /// <param name="isIn"></param>
    250         /// <returns></returns>
    251         private Vector2 CheckRange(double x, double y, out bool isIn)
    252         {
    253             foreach (Vector2 v in pointList)
    254             {
    255                 if (IsInCircle(x, y, v) && !IsAdded(v))
    256                 {
    257                     isIn = true;
    258                     return v;
    259                 }
    260             }
    261             isIn = false;
    262             return new Vector2 { X = (int)x, Y = (int)y };
    263 
    264         }
    265 
    266         /// <summary>
    267         /// 判断x、y 是否在 v 为圆心 Circle_R 为半径的圆内
    268         /// </summary>
    269         /// <param name="x"></param>
    270         /// <param name="y"></param>
    271         /// <param name="v"></param>
    272         /// <returns></returns>
    273         private bool IsInCircle(double x, double y, Vector2 v)
    274         {
    275             return Math.Pow(x - v.X, 2.0) + Math.Pow(y - v.Y, 2.0) <= Math.Pow(Circle_R, 2.0);
    276         }
    277 
    278         /// <summary>
    279         /// 判断item 是否已经选中
    280         /// </summary>
    281         /// <param name="item"></param>
    282         /// <returns></returns>
    283         private bool IsAdded(Vector2 item)
    284         {
    285             return checkedList.Contains(item);
    286         }
    287 
    288         /// <summary>
    289         /// 初始化 原始数据
    290         /// </summary>
    291         private void InitPointList()
    292         {
    293             //DebugUtil.WriteLine("Distance   == "+ Distance);
    294             int deta_x = 0;
    295             int deta_y = 0;
    296             int x = 0;
    297             int y = 0;
    298             for (int i = 0; i < 9; i++)
    299             {
    300                 deta_x = i % 3;
    301                 deta_y = i / 3;
    302                 x = X_Zero + deta_x * (Distance + 2 * Circle_R);
    303                 y = Y_Zero + deta_y * (Distance + 2 * Circle_R);
    304 
    305 
    306                 pointList.Add(new Vector2
    307                 {
    308                     X = x,
    309                     Y = y
    310                 });
    311 
    312             }
    313         }
    314 
    315     }
    316 
    317     class Vector2 {
    318         public int X { get; set; }
    319         public int Y { get; set; }
    320     }
    321 
    322 }
    View Code
  • 相关阅读:
    xcode debug
    ios 使用Quartz 2D画虚线
    ios UIGestureRecognizer
    ios 实现带矩形框的屏幕截图
    ios UISegemetedControl
    centos最小安装之后无法使用ifconfig
    无线LoRa智能远传水表
    智能水表188协议汇总
    无线LoRa远传智能水表
    静电除尘器除尘原理
  • 原文地址:https://www.cnblogs.com/devin_zhou/p/8057243.html
Copyright © 2020-2023  润新知