Do you have a security / privacy application? You need to lock your application's screen to provide secure access? Well, I am writing a series of open source control which will help you do just that!
In this first article, I am going to cover how to create a Pattern Lock or Swipe Lock, that you might have seen quite often on Android platform. This is my second effort to port such functionality from Android platform or other platforms. First up is Notification Notch Control.
Image 1. A sample for swipe lock
Well, I'll try to create something which blends nicely with Modern UI a.k.a Metro.
Image 2. A sample for WP swipe lock
In this first article, I am going to cover how to create a Pattern Lock or Swipe Lock, that you might have seen quite often on Android platform. This is my second effort to port such functionality from Android platform or other platforms. First up is Notification Notch Control.
Image 1. A sample for swipe lock
Well, I'll try to create something which blends nicely with Modern UI a.k.a Metro.
PREREQUISITE:
Image 3. Snapshot for Project's core component
LETS START BUILDING THE CONTROL:
We will quickly watch for the core STEPS to build this control.CREATE RECTANGULAR COMPONENT:
Our main component is Rectangle (which fits well in Metro design) as shown in image 2.
Image 4. Rectangle when not selected Image 5. Rectangle when selected
Following code is used to build square component:
Note: This class inherits from PatternDesignBase (abstract) class. PatternDesignBase work as a base class for such controls which could have different core items like Square (in current sample), Triangle, Circles, etc.
This method is responsible to initializing SquarePatterns and placing them into a Grid control which collectively forms core of this control
DrawLine
This methods holds the responsibility to draw lines between two square pattern, as we continue to swipe. There are certain methods available in LineHelper class which helps to complete the task by this method. This method comes into action when user starts moving his fingers on screen. I've captured the sample code for a quick reference here.
AddPolygon
This method generates tiny white colored triangle. These little triangles indicate the direction of swipe when user swipes it's fingers from one rectangle to another. These triangles will only be visible when they have moved from one rectangle to another. Logic to identify where the triangles to be drawn is written inside GetPoinstForPolygon(). A sample code for AddPolygon is referenced here:
That's it!! We are DONE!!!
Image 6. A sample selection for result.
Image 4. Rectangle when not selected Image 5. Rectangle when selected
Following code is used to build square component:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;
namespace PatternLockControl.Code
{
public class SquarePattern : PatternDesignBase
{
#region Data
#region SquareProperty
private Border _Square;
public Border Square
{
get
{ return _Square; }
set
{
if (_Square == value)
{
return;
}
_Square = value;
RaisePropertyChanged("Square");
}
}
#endregion
///
/// Sets or gets the Zindex Value for Icon
///
public override int ZIndexVal
{
get { return (int)Square.GetValue(Canvas.ZIndexProperty); }
set { Square.SetValue(Canvas.ZIndexProperty, value); }
}
#region BorderColProperty
private Color _BorderCol;
public Color BorderCol
{
get
{ return _BorderCol; }
set
{
if (_BorderCol == value)
{
return;
}
_BorderCol = value;
RaisePropertyChanged("BorderCol");
BorderBrush = new SolidColorBrush(_BorderCol);
}
}
#endregion
#region BorderBrushProperty
private SolidColorBrush _BorderBrush;
public SolidColorBrush BorderBrush
{
get
{ return _BorderBrush; }
private set
{
if (_BorderBrush == value)
{
return;
}
_BorderBrush = value;
RaisePropertyChanged("BorderBrush");
}
}
#endregion
public int Row { get; set; }
public int Column { get; set; }
#endregion
#region Constructor
public SquarePattern(int row, int column, int width, int value, Color fillNormal, Color fillSelected, Color borderCol)
: base(fillNormal, fillSelected, value)
{
this.FillColNormal = fillNormal;
this.BorderCol = borderCol;
this.Row = row;
this.Column = column;
Square = new Border() { Name = string.Concat(row, column), Width = width, Height = width, Background = this.FillBrushNormal, BorderBrush = BorderBrush, BorderThickness = new Thickness(2) };
ZIndexVal = 1;
}
#endregion
#region Methods
public override void GridPosition(int row, int col)
{
Square.SetValue(Grid.RowProperty, row);
Square.SetValue(Grid.ColumnProperty, col);
}
public override void MarkAsSelected()
{
this.Square.Background = FillBrushSelected;
}
#endregion
}
}
Note: This class inherits from PatternDesignBase (abstract) class. PatternDesignBase work as a base class for such controls which could have different core items like Square (in current sample), Triangle, Circles, etc.
CREATE LAYOUT ROOT :
This control's layout will be hosted in a UserControl which also implements it's core functionality for Pattern Lock Control.
Full code can be found in PatternLockMetroControl.cs and PatternLockMetroControl.xaml. I am going to list down important functionalities from it.
InitializeAnimateGridFull code can be found in PatternLockMetroControl.cs and PatternLockMetroControl.xaml. I am going to list down important functionalities from it.
- InitializeAnimateGrid.
- DrawLine.
- AddPolygon: .
This method is responsible to initializing SquarePatterns and placing them into a Grid control which collectively forms core of this control
private void InitializeAnimateGrid()
{
LockPatterShapes = new ObservableCollection();
var chromeColor = (this.Resources["PhoneAccentBrush"] as SolidColorBrush).Color;
int pattVal = 0;
for (int row = 0, maxRows = RootContainer.RowDefinitions.Count; row < maxRows; ++row)
{
for (int col = 0, maxCols = RootContainer.ColumnDefinitions.Count; col < maxCols; ++col)
{
var LockPatterShape = new SquarePattern(row, col, 100, pattVal++, Colors.Black, chromeColor, chromeColor);
LockPatterShape.GridPosition(row, col);
RootContainer.Children.Add(LockPatterShape.Square);
LockPatterShape.Square.MouseEnter += SquarePattern_MouseMoveEvent;
LockPatterShape.Square.MouseLeftButtonUp += Square_MouseLeftButtonUp;
LockPatterShapes.Add(LockPatterShape);
}
}
}
DrawLine
This methods holds the responsibility to draw lines between two square pattern, as we continue to swipe. There are certain methods available in LineHelper class which helps to complete the task by this method. This method comes into action when user starts moving his fingers on screen. I've captured the sample code for a quick reference here.
private void DrawLine()
{
if (MyPattern.Count < 2) return;
if (_MouseMoveLine != null)
{
RootContainer.Children.Remove(_MouseMoveLine);
_MouseMoveLine = null;
}
Point ptDest, ptSource;
var sqPattEnd = MyPattern.LastOrDefault().Value;
var sqPattStart = MyPattern.ElementAt(MyPattern.Count - 2).Value;
//Find points to draw line from start and end.
ptDest = LineHelper.GetPtRelativeToQuadrant(RootContainer, sqPattEnd.Square, LineHelper.FindQuadrantToDrawLineBW(sqPattEnd.Row, sqPattEnd.Column, sqPattStart.Row, sqPattStart.Column));
ptSource = LineHelper.GetPtRelativeToQuadrant(RootContainer, sqPattStart.Square, LineHelper.FindQuadrantToDrawLineBW(sqPattStart.Row, sqPattStart.Column, sqPattEnd.Row, sqPattEnd.Column));
Line line;
LineType lType = LineHelper.FindLineType(sqPattStart.Row, sqPattStart.Column, sqPattEnd.Row, sqPattEnd.Column);
if (lType == LineType.SIMPLE)
line = LineHelper.CreateLine(ptSource, ptDest, DragLineWidth, (this.Resources["PhoneAccentBrush"] as SolidColorBrush), ZIdxForDrawnLines++, RootContainer, lType);
else
line = LineHelper.CreateLine(ptSource, ptDest, DottedLineWidth, SelectedLineBrush, ZIdxForDrawnLines++, RootContainer, lType);
AddPolygon(MyPattern.ElementAt(MyPattern.Count - 2).Value.Square, LineHelper.FindQuadrantToDrawLineBW(sqPattStart.Row, sqPattStart.Column, sqPattEnd.Row, sqPattEnd.Column));
RootContainer.Children.Add(line);
}
AddPolygon
This method generates tiny white colored triangle. These little triangles indicate the direction of swipe when user swipes it's fingers from one rectangle to another. These triangles will only be visible when they have moved from one rectangle to another. Logic to identify where the triangles to be drawn is written inside GetPoinstForPolygon(). A sample code for AddPolygon is referenced here:
private void AddPolygon(Border shape, LineQuadrant quad)
{
Polygon poly = new Polygon();
poly.Fill = new SolidColorBrush(Colors.White);
poly.Points = LineHelper.GetPointsForPolygon(shape.ActualWidth, quad, poly);
shape.BorderThickness = new Thickness(0);
shape.Child = poly;
//Set the Max ZIdx for poly/Border so that it will always be on top of all drawn lines
shape.SetValue(Canvas.ZIndexProperty, ZIdxForDrawnLines + 1);
}
That's it!! We are DONE!!!
OTHER IMPORTANT FEATURES / INFO:
1. Registration Mode : We can easily configure this control to register a new pattern or to use verify an existing pattern
2. Decoy Pattern : This feature provides an additional flexibility to register additional set of pattern. This will be helpful in case you want your application to support multiple access mode say one for Admin and another for User mode.
3. Pattern Format : Based on your selection i.e. Registration Mode or Verify Pattern mode this control will generate an event to publish the result. In case of Registration mode if your selection is as per Image 6 then it will return a List of integer [1,2,3,6,9].