zoukankan      html  css  js  c++  java
  • 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; }
        }
    }
  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/devin_zhou/p/8047313.html
Copyright © 2011-2022 走看看