Recently, the company asked to do a nine Sudoku unlock, I used the millet cell phone, watching him that set the lock screen nine Sudoku very good-looking, did the component, do not use picture resources, pure code to achieve.
Respect each hard blogger, modify on the basis of http://blog.csdn.net/mu399/article/details/38734449
Effect Chart:
Key Code classes:
Mathutil.java
/**
* @author soban
* @create 2016/12/5 15:52.
*
/public class Mathutil {public
static double distance (double x1, double y1, double x2, double y2) {return
Math.sqrt (Math.Abs (x1-x2) * Math.Abs (X1-X2)
+ math.abs (y1-y2) * Math.Abs (Y1-y2));
public static double Pointtotodegrees (double x, double y) {return
math.todegrees (math.atan2 (x, y));
}
public static Boolean checkinround (float sx, float sy, float R, float x,
float y) {return
math.sqrt (sx-x) * (sx-x) + (sy-y) * (sy-y)) < R;
}
}
Point.java
/**
* @author soban
* @create 2016/12/5 15:51.
* * Public
class Point {public
static int state_normal = 0;
public static int state_check = 1; public
static int state_check_error = 2;//public
float x;
public float y;
public int state = 0;
public int index = 0;//public Point
() {
} (
float x, float y, int value) {
this.x = X;
this.y = y;
index = value;
}
public int Getcolnum () {return
(index-1)% 3;
}
public int Getrownum () {return
(index-1)/3;
}
}
Locuspasswordview.java
Import Android.content.Context;
Import Android.graphics.Canvas;
Import Android.graphics.Paint;
Import Android.graphics.Paint.Style;
Import Android.text.TextUtils;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import android.view.MotionEvent;
Import Android.view.View;
Import java.util.ArrayList;
Import java.util.List;
Import Java.util.Timer;
Import Java.util.TimerTask;
/** * @author Soban * @create 2016/12/5 15:49.
* * public class Locuspasswordview extends View {/** * control's wide high/private float width = 0;
Private float height = 0; Private Boolean iscache = false;
Cache Pwdmaxlen Dot Private Paint mpaint = new Paint (Paint.anti_alias_flag);
Private point[][] mpoints = new Point[3][3];
private float Dotradius = 0;
Select >pwdminlen Point private list<point> spoints = new arraylist<point> ();
Private Boolean checking = false;
Private long clear_time = 1000;
private int pwdmaxlen = 9;
private int pwdminlen = 4;
Private Boolean Istouch = true; PRivate Paint Linepaint;
Private Paint Normalpaint;
Private Paint Selectedpaint;
Private Paint Errorpaint;
private int normaldotcolor = 0xff929292;
private int selectedcolor = 0XFFC3C3C3;
private int selectedlinecolor = 0xffEDEDED;
private int errorcolor = 0XFFF34B2A;
private int errorlinecolor = 0XFFEEBFB6;
Public Locuspasswordview (context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle);
Public Locuspasswordview (context, AttributeSet attrs) {Super (context, attrs);
Public Locuspasswordview {Super (context); @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, H
EIGHTMEASURESPEC);
int width = measuredimension (widthmeasurespec);
int height = measuredimension (heightmeasurespec);
if (width > height) {setmeasureddimension (height, height);
else {setmeasureddimension (width, width); } public int measuredimension (int defaultsize, int measurespec) {int result;
int specmode = Measurespec.getmode (Measurespec);
int specsize = measurespec.getsize (Measurespec);
if (Specmode = = measurespec.exactly) {result = Specsize; else {result = DefaultSize//unspecified if (Specmode = = measurespec.at_most) {result = Math.min (result, specsize)
;
} return result;
@Override public void OnDraw (Canvas Canvas) {if (!iscache) {Initcache ();
} drawtocanvas (canvas);
} private void Drawtocanvas (Canvas Canvas) {Boolean inerrorstate = false; float Radiu = dotradius/16; The radius of the circle/dot for (int i = 0; i < mpoints.length; i++) {for (int j = 0; J < Mpoints[i].length; J +) {point P = m
POINTS[I][J];
if (p.state = = Point.state_check) {selectedpaint.setcolor (selectedcolor);
Canvas.drawcircle (p.x, P.y, Radiu, Selectedpaint);
else if (p.state = = point.state_check_error) {inerrorstate = true;
Errorpaint.setcolor (Errorcolor);
Canvas.drawcircle (p.x, P.y, Radiu, Errorpaint); else {NormalpainT.setcolor (Normaldotcolor);
Canvas.drawcircle (p.x, P.y, Radiu, Normalpaint);
}} if (Inerrorstate) {linepaint.setcolor (errorlinecolor);
else {linepaint.setcolor (selectedlinecolor);
//Draw line if (Spoints.size () > 0) {int tmpalpha = Mpaint.getalpha ();
Point tp = spoints.get (0);
for (int i = 1; i < spoints.size (); i++) {Point P = spoints.get (i);
DrawLine (TP, p, canvas, linepaint);
TP = P;
} if (This.movingnopoint) {drawLine (TP, New Point (Moveingx, Moveingy,-1), canvas, linepaint);
} mpaint.setalpha (Tmpalpha); /** * Draw Line * @param start * @param end * @param canvas * @param paint/private void DrawLine (point start, Poi NT End, Canvas Canvas, Paint Paint) {float Radiu = dotradius/16;//circle radius Double D = mathutil.distance (Start.x, Start.y
, End.X, END.Y);
float rx = (float) ((end.x-start.x) * radiu/d);
float ry = (float) ((end.y-start.y) * radiu/d);
Canvas.drawline (start.x + rx, Start.y + ry, End.x-rx, End.y-ry, paint); }
/**
* Cache control width Height with point position * * private void Initcache () {width = This.getwidth ();
Height = this.getheight ();
float x = 0;
Float y = 0;
if (width > height) {x = (width-height)/2;
width = height;
else {y = (height-width)/2;
Height = width;
int leftpadding = 15;
float dotpadding = WIDTH/3-leftpadding;
float Middlex = WIDTH/2;
float Middley = HEIGHT/2;
Mpoints[0][0] = new Point (x + middlex-dotpadding, y + middley-dotpadding, 1);
MPOINTS[0][1] = new Point (x + middlex, y + middley-dotpadding, 2);
MPOINTS[0][2] = new Point (x + Middlex + dotpadding, y + middley-dotpadding, 3);
Mpoints[1][0] = new Point (x + middlex-dotpadding, y + Middley, 4);
MPOINTS[1][1] = new Point (x + middlex, y + Middley, 5);
MPOINTS[1][2] = new Point (x + Middlex + dotpadding, y + Middley, 6);
Mpoints[2][0] = new Point (x + middlex-dotpadding, y + Middley + dotpadding, 7);
MPOINTS[2][1] = new Point (x + middlex, y + Middley + dotpadding, 8); MPOINTS[2][2] = new Point (x + miDdlex + dotpadding, y + Middley + dotpadding, 9);
LOG.D ("Jerome", "Canvas width:" + width);
Dotradius = WIDTH/10;
Iscache = true;
Initpaints ();
private void Initpaints () {linepaint = new Paint ();
Linepaint.setcolor (Selectedcolor);
Linepaint.setstyle (Style.fill);
Linepaint.setantialias (TRUE);
Linepaint.setstrokewidth (DOTRADIUS/9);
Selectedpaint = new Paint ();
Selectedpaint.setstyle (Style.fill);
Selectedpaint.setantialias (TRUE);
Selectedpaint.setstrokewidth (DOTRADIUS/6);
Errorpaint = new Paint ();
Errorpaint.setstyle (Style.fill);
Errorpaint.setantialias (TRUE);
Errorpaint.setstrokewidth (DOTRADIUS/6);
Normalpaint = new Paint ();
Normalpaint.setstyle (Style.fill);
Normalpaint.setantialias (TRUE);
Normalpaint.setstrokewidth (DOTRADIUS/9); /** * Check * @param x * @param y * @return/private point Checkselectpoint (float x, float y) {for (int i = 0 ; i < mpoints.length; i++) {for (int j = 0; J < Mpoints[i].length; J + +) {point P = mpoints[i][j];
if (Mathutil.checkinround (p.x, P.y, Dotradius, (int) x, (int) y)) {return p;
}} return null;
/** * Reset */private void Reset () {for (point p:spoints) {p.state = Point.state_normal;
} spoints.clear ();
This.enabletouch (); /** * Determine if there is a cross return of 0, new point, 1 overlap with the above 2, and not the last point overlap * * @param p * @return/private int crosspoint (point P) {//overlapping not most The latter is reset if (Spoints.contains (p)) {if (Spoints.size () > 2) {//with a non-final overlap if (spoints.get (Spoints.size ()-1). ind
Ex!= P.index) {return 2; } return 1; Overlap with the last bit} else {return 0;//New Point}}/** * Add a dot * * @param point */private void Addpoint (points point) {if (Spoints.size () > 0)
{Point lastpoint = Spoints.get (Spoints.size ()-1);
int dx = Math.Abs (Lastpoint.getcolnum ()-point.getcolnum ());
int dy = Math.Abs (Lastpoint.getrownum ()-point.getrownum ()); if (dx > 1 | | dy > 1) && (dx = 0 | | dy = 0 | | dx = = DY)) {//if (dx > 1 | | dy > 1) && (d X!= 2 * dY) && (dy!= 2 * dx)) {int Middleindex = (Point.index + lastpoint.index)/2-1;
Point middlepoint = mpoints[middleindex/3][middleindex% 3];
if (middlepoint.state!= point.state_check) {middlepoint.state = Point.state_check;
Spoints.add (Middlepoint);
}} this.sPoints.add (point); /** * Convert to String */private string topointstring () {if (Spoints.size () >= Pwdminlen && spoints.size () &l
t;= pwdmaxlen) {stringbuffer SF = new StringBuffer ();
for (point p:spoints) {sf.append (p.index);
return sf.tostring ();
else {return "";
} Boolean movingnopoint = false;
float MOVEINGX, moveingy;
@Override public boolean ontouchevent (Motionevent event) {//non-operation if (!istouch) {return false;
} Movingnopoint = false;
float ex = Event.getx ();
float ey = event.gety ();
Boolean isfinish = false;
Boolean redraw = false;
Point p = null;
Switch (event.getaction ()) {case Motionevent.action_down://click///If the password is being purged, cancel if (task!= null) {Task.cancel ();
task = null;
LOG.D ("task", "Touch Cancel");
}//Remove the point reset () before;
p = Checkselectpoint (ex, EY);
if (P!= null) {checking = true;
Mcompletelistener.onprompt ("Release the Finger after completion");
Break
Case motionevent.action_move://Move if (checking) {p = Checkselectpoint (ex, EY);
if (p = = null) {Movingnopoint = true;
MOVEINGX = ex;
Moveingy = ey;
}} break;
Case motionevent.action_up://Lift p = checkselectpoint (ex, EY);
checking = false;
Isfinish = true;
Break
} if (!isfinish && checking && p!= null) {int RK = CrossPoint (p);
if (RK = = 2) {//with non final overlap//reset ();
checking = false;
Movingnopoint = true;
MOVEINGX = ex;
Moveingy = ey;
Redraw = true;
else if (RK = = 0) {//a new point p.state = Point.state_check;
Addpoint (P);
Redraw = true;
//RK = = 1}//whether to redraw if (redraw) {} if (Isfinish) {if (this.sPoints.size () = 1) {this.reset ();
Isfirstpwdempty (); else if (spoints.size () > 0 && spoints.size () < Pwdminlen) {error ();
Clearpassword ();
Isfirstpwdempty ();
else if (Mcompletelistener!= null) {if (This.sPoints.size () >= Pwdminlen) {This.disabletouch ();
Ispwdequal ();
}} this.postinvalidate ();
return true; private void Isfirstpwdempty () {if (Textutils.isempty (Firstpassword)) {mcompletelistener.onprompt ("at least 4 points must be connected, please try again.")
");
else {mcompletelistener.onprompt ("please retry");
} private void Ispwdequal () {if (Textutils.isempty (Firstpassword)) {mcompletelistener.onprompt ("plot pattern again to confirm");
Mcompletelistener.oncomplete (Topointstring ());
else {if (Firstpassword.equals (topointstring ()) {mcompletelistener.onprompt ("Your new Unlock pattern");
Mcompletelistener.oncomplete (Topointstring ());
else {mcompletelistener.onprompt ("please retry");
Error ();
Clearpassword ();
}}/** * setting is already selected as Error/private void error () {for (point p:spoints) {p.state = Point.state_check_error;
}/** * Set to input error/public void Markerror () {markerror (clear_time); /** * Set to input error */Public void Markerror (final long time) {for (point p:spoints) {p.state = Point.state_check_error;
} This.clearpassword (time);
/** * is set to operable */public void Enabletouch () {Istouch = true;
/** * is set to not operate */public void Disabletouch () {Istouch = false;
Private Timer timer = new timer ();
Private TimerTask task = null;
/** * Clear Password */public void Clearpassword () {Clearpassword (clear_time);
/** * Clear Password */public void Clearpassword (final long) {if (Time > 1) {if (Task!= null) {task.cancel ();
LOG.D ("task", "Clearpassword Cancel ()");
} postinvalidate ();
task = new TimerTask () {public void run () {reset ();
Postinvalidate ();
}
};
LOG.D ("task", "Clearpassword schedule (" + Time +) ");
Timer.schedule (task, time);
else {reset ();
Postinvalidate ();
}} private String Firstpassword;
Public String Getfirstpassword () {return firstpassword;
} public void Setfirstpassword (String firstpassword) {This.firstpassword = Firstpassword;Private Oncompletelistener Mcompletelistener;
public void Setoncompletelistener (Oncompletelistener mcompletelistener) {this.mcompletelistener = MCompleteListener;
public interface Oncompletelistener {void OnComplete (string password);//password void Onprompt (string prompt);//Prompt info} }
Example: You can support redrawing, and you need to set your password two times.
Mainactivity.class
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.util.Log;
Import Android.view.View;
Import Android.widget.Button;
Import Android.widget.TextView;
Import Android.widget.Toast;
Import SOBAN.NINELOCKSCREEN.R;
public class Mainactivity extends activity implements View.onclicklistener, Locuspasswordview.oncompletelistener {
Private String TAG = Main2Activity.class.getName ();
Private TextView Mexplaintv;
Private Button mrepaintbtn;
Private Button mconfirmbtn;
Private Locuspasswordview Mpwdview;
Private String Firstpassword;
Private String Againpassword;
Private Boolean Isfirst;
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Initviews ();
private void Initviews () {Mexplaintv = (TextView) Findviewbyid (R.id.tv_explain);
MREPAINTBTN = (Button) Findviewbyid (r.id.btn_repaint);
MCONFIRMBTN = (Button) Findviewbyid (r.id.btn_confirm); Mpwdview = (LocuspasswordView) Findviewbyid (R.ID.MPASSWORDVIEW2);
Mrepaintbtn.setonclicklistener (this);
Mconfirmbtn.setonclicklistener (this);
Mpwdview.setoncompletelistener (this);
Initchoose ();
@Override public void OnClick (view view) {switch (View.getid ()) {case r.id.btn_repaint:repaint ();
Break
Case R.id.btn_confirm:confirm ();
Break
}} private void Repaint () {Mpwdview.clearpassword (0);
Initchoose ();
} private void Confirm () {Toast.maketext (Mainactivity.this, "You set the password:" + Againpassword, Toast.length_short). Show ();
@Override public void OnComplete (String password) {if (Isfirst) {firstchoose (password);
else {secondchoose (password);
LOG.E (TAG, "oncomplete->" + password);
@Override public void Onprompt (String prompt) {mexplaintv.settext (prompt);
private void Initchoose () {Isfirst = true;
Firstpassword = "";
Againpassword = "";
Mpwdview.setfirstpassword ("");
Mrepaintbtn.setvisibility (View.gone);
Mconfirmbtn.setvisibility (View.gone); } Private void Firstchoose (String password) {Isfirst = false;
Firstpassword = password;
Mpwdview.setfirstpassword (password);
Mpwdview.clearpassword (0);
Mrepaintbtn.setenabled (TRUE);
Mconfirmbtn.setenabled (FALSE);
Mrepaintbtn.setvisibility (view.visible);
Mconfirmbtn.setvisibility (view.visible);
} private void Secondchoose (String password) {Isfirst = true;
Againpassword = password;
Mrepaintbtn.setenabled (TRUE);
Mconfirmbtn.setenabled (TRUE); }
}
Layout: Activity_main.xml
<?xml version= "1.0" encoding= "Utf-8"?> <relativelayout xmlns:android= "http://schemas.android.com/apk/res/" Android "Android:layout_width=" Match_parent "android:layout_height=" match_parent "android:gravity=" Center_ Horizontal "android:orientation=" vertical "> <linearlayout android:id=" @+id/bottomlayout "Android:layout_" Width= "Match_parent" android:layout_height= "50dip" android:layout_alignparentbottom= "true" android:orientation= " Horizontal "> <button android:id=" @+id/btn_repaint "android:layout_width=" Match_parent "Android:layout_height" = "Wrap_content" android:layout_weight= "1" android:text= "Redraw"/> <button android:id= "@+id/btn_confirm" android:l Ayout_width= "Match_parent" android:layout_height= "Wrap_content" android:layout_weight= "1" android:text= "Confirmation"/> & lt;/linearlayout> <soban.ninelockscreen.demo.locuspasswordview android:id= "@+id/mPassWordView2" Android: Layout_width= "Fill_parent" android:layout_height= "Fill_parent" Android:laYout_above= "@id/bottomlayout"/> <textview android:id= "@+id/tv_explain" android:layout_width= "Match_parent" android:layout_height= "Wrap_content" android:layout_above= "@id/mpasswordview2" android:layout_alignparenttop= " True "android:background=" @color/colorprimary "android:gravity=" center "android:text=" to draw unlock patterns, connect at least 4 dots "Android: Textcolor= "#FFFFFF"/> </RelativeLayout>
The above is a small set to introduce the Android imitation Millet lock screen to achieve nine Sudoku unlock function (no need for picture resources), I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!