• Xamarin.iOS 手势密码


    Xamarin.iOS 手势密码

    主要问题:

    1. 图形绘制

    • 实心圆
    • 空心圆
    • 线段

    2. Touch事件处理

    • TouchesBegan
    • TouchesMoved
    • TouchesEnded
    • TouchesCancelled

    3. 各个圆坐标计算

    4. 圆圈的选中逻辑

    • 判断点是否在圆内
    • 判断选中的两个圆心连线是否经过一个圆,如果是则该圆也是选中
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using CoreGraphics;
    using Foundation;
    using ObjCRuntime;
    using UIKit;
    
    namespace MyPassword.iOS.View.GuestureLock
    {
        [Register("GuestureLockUIView")]
        public partial class GuestureLockUIView : UIView
        {
    
            private int Circle_R = 20;
            private int Distance = 40;
            private int Circle_r = 3;
    
            private int Length = 0;
    
            private double ViewWidth = 0;
            private double ViewHight = 0;
            private double MyPadding = 0;
    
            private int X_Zero = 0;
            private int Y_Zero = 0;
            
    
            CGContext cGContext;
    
            public GuestureLockUIView(IntPtr handle) : base(handle)
            {
                Initialize();
            }
    
            public GuestureLockUIView()
            {
                Initialize();
            }
    
            public GuestureLockUIView(RectangleF bounds) : base(bounds)
            {
                Initialize();
            }
            
            void Initialize()
            {
                BackgroundColor = UIColor.Green;
                
                Length = 3 * Circle_R * 2 + Distance * 2;
                ViewWidth = 320f;
                ViewHight = 320f;
    
                MyPadding = (ViewWidth - Length) / 2;
                X_Zero = (int)MyPadding + Circle_R;
                Y_Zero = (int)MyPadding + Circle_R;
                InitPointList();
            }
    
    
    
            private List<Vector2> pointList = new List<Vector2>();
    
            private List<Vector2> checkedList = new List<Vector2>();
    
            private List<Vector2> drawList = new List<Vector2>();
    
            private List<int> indexList = new List<int>();
            
    
            public delegate void CheckCompeleteDelegate(List<int> checkList);
    
            private CheckCompeleteDelegate _CheckCompeleteDelegate;
    
            public event CheckCompeleteDelegate CheckCompeleteEvent
            {
                add
                {
                    _CheckCompeleteDelegate = Delegate.Combine(_CheckCompeleteDelegate, value) as CheckCompeleteDelegate;
                }
                remove
                {
                    _CheckCompeleteDelegate = Delegate.Remove(_CheckCompeleteDelegate, value) as CheckCompeleteDelegate;
                }
            }
    
    
            private void GetCheckedIndex()
            {
                indexList.Clear();
                foreach (var item in checkedList)
                {
                    int index = pointList.IndexOf(item);
                    indexList.Add(index);
                }
            }
            
    
            public override void Draw(CGRect rect)
            {
                base.Draw(rect);
    
                cGContext = UIGraphics.GetCurrentContext();
                int size = pointList.Count;
               
                for (int i = 0; i < size; i++)//绘制元素点图
                {
                    Vector2 item = pointList.ElementAt(i);
    
                    cGContext.SetFillColor(UIColor.Blue.CGColor);
                    cGContext.AddEllipseInRect(new CGRect(item.X - Circle_r, item.Y - Circle_r, Circle_r * 2, Circle_r * 2));
                    cGContext.DrawPath(CGPathDrawingMode.Fill);
    
                    cGContext.SetStrokeColor(UIColor.Blue.CGColor);
                    cGContext.SetLineWidth(2);
                    cGContext.AddEllipseInRect(new CGRect(item.X- Circle_R, item.Y- Circle_R, Circle_R * 2, Circle_R * 2));
                    cGContext.DrawPath(CGPathDrawingMode.Stroke);
                }
                size = drawList.Count;
                for (int i = 0; i < size; i++)//绘制选中点图
                {
                    Vector2 item = drawList.ElementAt(i);
    
    
                    cGContext.SetFillColor(UIColor.Red.CGColor);
                    cGContext.AddEllipseInRect(new CGRect(item.X- Circle_r, item.Y- Circle_r, Circle_r * 2, Circle_r * 2));
                    cGContext.DrawPath(CGPathDrawingMode.Fill);
                    if (i < size - 1)
                    {
                        Vector2 item2 = drawList.ElementAt(i + 1);
    
                        cGContext.SetStrokeColor(UIColor.Red.CGColor);
                        cGContext.MoveTo(item.X,item.Y);
                        cGContext.AddLineToPoint(item2.X,item2.Y);
                        cGContext.DrawPath(CGPathDrawingMode.Stroke);
    
                        cGContext.SetStrokeColor(UIColor.Red.CGColor);
                        cGContext.SetLineWidth(2);
                        cGContext.AddEllipseInRect(new CGRect(item.X - Circle_R, item.Y- Circle_R, Circle_R * 2, Circle_R * 2));
                        cGContext.DrawPath(CGPathDrawingMode.Stroke);
                    }
                }
    
            }
    
    
            public void Reset()
            {
                checkedList.Clear();
                drawList.Clear();
                SetNeedsDisplay();
            }
    
    
            private double touch_x = 0;
            private double touch_y = 0;
    
            public override void TouchesBegan(NSSet touches, UIEvent evt)
            {
                base.TouchesBegan(touches, evt);
                if (touches.AnyObject is UITouch touch)
                {
                    touch_x = touch.LocationInView(this).X;
                    touch_y = touch.LocationInView(this).Y;
                    ProcessTouchEvent(touch_x, touch_y);
                }
            }
    
            public override void TouchesMoved(NSSet touches, UIEvent evt)
            {
                base.TouchesMoved(touches, evt);
                if (touches.AnyObject is UITouch touch)
                {
                    touch_x= touch.LocationInView(this).X;
                    touch_y= touch.LocationInView(this).Y;
                    ProcessTouchEvent(touch_x, touch_y);
                }
            }
    
            public override void TouchesEnded(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
                GetCheckedIndex();
                if (_CheckCompeleteDelegate != null)
                {
                    _CheckCompeleteDelegate.Invoke(indexList);
                }
                Reset();
            }
            public override void TouchesCancelled(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
                Reset();
            }
    
            private void ProcessTouchEvent(double x, double y)
            {
                //DebugUtil.WriteLine("x = "+x + "  y = "+y);
                if (x < 0 || y < 0 || x > ViewWidth || y > ViewHight)
                {
    
                }
                else
                {
                    Vector2 item = CheckRange(x, y, out bool isIn);
                    if (isIn && !IsAdded(item))
                    {
                        if (checkedList.Count > 0)
                        {
                            var item2 = checkedList.Last();
                            foreach (Vector2 v in pointList)
                            {
                                if (item != v && !IsAdded(v) && CheckOnLine(item, item2, v))
                                {
                                    checkedList.Add(v);
                                }
                            }
                        }
                        checkedList.Add(item);
                    }
                    else
                    {
                        drawList.Clear();
                        drawList.AddRange(checkedList);
                        drawList.Add(item);
                    }
    
                    SetNeedsDisplay();
                }
            }
    
    
    
            /// <summary>
            /// 判断 v 是否在 v1、v2连线内  用了最粗暴的方法  
            /// </summary>
            /// <param name="v1"></param>
            /// <param name="v2"></param>
            /// <param name="v"></param>
            /// <returns></returns>
            private bool CheckOnLine(Vector2 v1, Vector2 v2, Vector2 v)
            {
                double len = CalcLengthBetweenTwoPoint(v1, v2);
                double len1 = CalcLengthBetweenTwoPoint(v1, v);
                double len2 = CalcLengthBetweenTwoPoint(v2, v);
                return len == len1 + len2;
            }
    
            /// <summary>
            /// 计算v1、v2连线长度
            /// </summary>
            /// <param name="v1"></param>
            /// <param name="v2"></param>
            /// <returns></returns>
            private double CalcLengthBetweenTwoPoint(Vector2 v1, Vector2 v2)
            {
                double value = Math.Pow(v1.X - v2.X, 2.0) + Math.Pow(v1.Y - v2.Y, 2.0);
                //return value;
                return Math.Abs(Math.Sqrt(value));
            }
    
            /// <summary>
            /// 判断x、y 是否在其中一个圆内
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="isIn"></param>
            /// <returns></returns>
            private Vector2 CheckRange(double x, double y, out bool isIn)
            {
                foreach (Vector2 v in pointList)
                {
                    if (IsInCircle(x, y, v) && !IsAdded(v))
                    {
                        isIn = true;
                        return v;
                    }
                }
                isIn = false;
                return new Vector2 { X = (int)x, Y = (int)y };
    
            }
    
            /// <summary>
            /// 判断x、y 是否在 v 为圆心 Circle_R 为半径的圆内
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="v"></param>
            /// <returns></returns>
            private bool IsInCircle(double x, double y, Vector2 v)
            {
                return Math.Pow(x - v.X, 2.0) + Math.Pow(y - v.Y, 2.0) <= Math.Pow(Circle_R, 2.0);
            }
    
            /// <summary>
            /// 判断item 是否已经选中
            /// </summary>
            /// <param name="item"></param>
            /// <returns></returns>
            private bool IsAdded(Vector2 item)
            {
                return checkedList.Contains(item);
            }
    
            /// <summary>
            /// 初始化 原始数据
            /// </summary>
            private void InitPointList()
            {
                int deta_x = 0;
                int deta_y = 0;
                int x = 0;
                int y = 0;
                for (int i = 0; i < 9; i++)
                {
                    deta_x = i % 3;
                    deta_y = i / 3;
                    x = X_Zero + deta_x * (Distance + 2 * Circle_R);
                    y = Y_Zero + deta_y * (Distance + 2 * Circle_R);
                    
                    pointList.Add(new Vector2
                    {
                        X = x,
                        Y = y
                    });
    
                }
            }
    
        }
        
        class Vector2
        {
            public int X { get; set; }
            public int Y { get; set; }
        }
    }
  • 相关阅读:
    ASP.NET 2.0个性化配置(profile)
    03 创建虚拟机
    一些新的Blender的视频教程
    [转载]虚拟家庭存档文件修改方法
    [转载]游戏开发中常用的设计模式
    批处理for命令详解(转)
    [转载]高效软件开发团队的特征
    软件构架师的特点
    一点SICP(Structure and Interpretation of Computer Programs) 资料 (转载加整理)
    [译]游戏编程入门(by David Astle)
  • 原文地址:https://www.cnblogs.com/devin_zhou/p/8047313.html
Copyright © 2020-2023  润新知