手势解锁自定义View

  1 package com.rxx.view;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 import java.util.Timer;
  6 import java.util.TimerTask;
  7 import android.content.Context;
  8 import android.graphics.Canvas;
  9 import android.graphics.Color;
 10 import android.graphics.Paint;
 11 import android.graphics.Path;
 12 import android.util.AttributeSet;
 13 import android.view.MotionEvent;
 14 import android.view.View;
 15 
 16 /**
 17  * 自定义锁屏View
 18  */
 19 public class GestureLockView extends View {
 20     /** 解锁密码key */
 21     private String key = "";
 22     private OnGestureFinishListener onGestureFinishListener;
 23 
 24     /** 解锁圆点数组 */
 25     private LockCircle[] cycles;
 26     /** 存储触碰圆的序列 */
 27     private List<Integer> linedCycles = new ArrayList<Integer>();
 28 
 29     // 画笔
 30     /** 空心外圆 */
 31     private Paint paintNormal;
 32     /** 点击后内部圆 */
 33     private Paint paintInnerCycle;
 34     /** 画路径 */
 35     private Paint paintLines;
 36     private Path linePath = new Path();
 37 
 38     /** 当前手指X,Y位置 */
 39     private int eventX, eventY;
 40 
 41     /** 能否操控界面绘画 */
 42     private boolean canContinue = true;
 43     /** 验证结果 */
 44     private boolean result;
 45     private Timer timer;
 46 
 47     /** 未选中颜色 */
 48     private final int NORMAL_COLOR = Color.parseColor("#959BB4");
 49     /** 错误颜色 */
 50     private final int ERROE_COLOR = Color.parseColor("#FF2525"); // 正常外圆颜色
 51     /** 选中时颜色 */
 52     private final int TOUCH_COLOR = Color.parseColor("#409DE5"); // 选中内圆颜色
 53 
 54     // =================================start=构造方法========================
 55     public GestureLockView(Context context, AttributeSet attrs, int defStyle) {
 56         super(context, attrs, defStyle);
 57         init();
 58     }
 59 
 60     public GestureLockView(Context context, AttributeSet attrs) {
 61         this(context, attrs, 0);
 62     }
 63 
 64     public GestureLockView(Context context) {
 65         this(context, null);
 66     }
 67 
 68     // ===============================end=构造方法========================
 69 
 70     /** 初始化 */
 71     public void init() {
 72         paintNormal = new Paint();
 73         paintNormal.setAntiAlias(true);
 74         paintNormal.setStrokeWidth(5);
 75         paintNormal.setStyle(Paint.Style.STROKE);
 76 
 77         paintInnerCycle = new Paint();
 78         paintInnerCycle.setAntiAlias(true);
 79         paintInnerCycle.setStyle(Paint.Style.FILL);
 80 
 81         paintLines = new Paint();
 82         paintLines.setAntiAlias(true);
 83         paintLines.setStyle(Paint.Style.STROKE);
 84         paintLines.setStrokeWidth(10);
 85 
 86     }
 87 
 88     @Override
 89     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 90         int specMode = MeasureSpec.getMode(widthMeasureSpec);
 91         int spceSize = MeasureSpec.getSize(widthMeasureSpec);
 92         heightMeasureSpec = MeasureSpec.makeMeasureSpec(
 93                 (int) (spceSize * 0.85 + 0.5f), specMode);
 94         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 95     }
 96 
 97     @Override
 98     protected void onLayout(boolean changed, int left, int top, int right,
 99             int bottom) {
100         super.onLayout(changed, left, top, right, bottom);
101         int perWidthSize = getWidth() / 7;
102         int perHeightSize = getHeight() / 6;
103         /** 初始化圆的参数 */
104         if (cycles == null && (perWidthSize > 0) && (perHeightSize > 0)) {
105             cycles = new LockCircle[9];
106             for (int i = 0; i < 3; i++) {
107                 for (int j = 0; j < 3; j++) {
108                     LockCircle lockCircle = new LockCircle();
109                     lockCircle.setNum(i * 3 + j);
110                     lockCircle.setOx(perWidthSize * (j * 2 + 1.5f) + 0.5f);
111                     lockCircle.setOy(perHeightSize * (i * 2 + 1) + 0.5f);
112                     lockCircle.setR(perWidthSize * 0.6f);
113                     cycles[i * 3 + j] = lockCircle;
114                 }
115             }
116         }
117 
118     }
119 
120     public void setKey(String key) {
121         this.key = key;
122     }
123 
124     public void setOnGestureFinishListener(
125             OnGestureFinishListener onGestureFinishListener) {
126         this.onGestureFinishListener = onGestureFinishListener;
127     }
128 
129     /** 手势输入完成后回调接口 */
130     public interface OnGestureFinishListener {
131         /** 手势输入完成后回调函数 */
132         public void OnGestureFinish(boolean success, String key);
133     }
134 
135     /** 监听手势 */
136     @Override
137     public boolean onTouchEvent(MotionEvent event) {
138         if (canContinue) {
139             switch (event.getAction()) {
140             case MotionEvent.ACTION_DOWN:
141             case MotionEvent.ACTION_MOVE:
142                 eventX = (int) event.getX();
143                 eventY = (int) event.getY();
144                 for (int i = 0; i < cycles.length; i++) {
145                     if (cycles[i].isPointIn(eventX, eventY)) {
146                         cycles[i].setOnTouch(true);
147                         if (!linedCycles.contains(cycles[i].getNum())) {
148                             linedCycles.add(cycles[i].getNum());
149                         }
150                     }
151                 }
152                 break;
153             case MotionEvent.ACTION_UP:
154                 // 手指离开暂停触碰
155                 canContinue = false;
156                 StringBuffer stringBuffer = new StringBuffer();
157                 for (int i = 0; i < linedCycles.size(); i++) {
158                     stringBuffer.append(linedCycles.get(i));
159                 }
160                 result = key.equals(stringBuffer.toString());
161                 if (onGestureFinishListener != null && linedCycles.size() > 0) {
162                     onGestureFinishListener.OnGestureFinish(result,
163                             stringBuffer.toString());
164                 }
165                 timer = new Timer();
166                 timer.schedule(new TimerTask() {
167                     @Override
168                     public void run() {
169                         eventX = eventY = 0;
170                         for (int i = 0; i < 9; i++) {
171                             cycles[i].setOnTouch(false);
172                         }
173                         linedCycles.clear();
174                         linePath.reset();
175                         canContinue = true;
176                         postInvalidate();// 在非ui线程刷新界面
177                     }
178                 }, 1000);
179                 break;
180             }
181             invalidate();
182         }
183         return true;
184     }
185 
186     @Override
187     protected void onDraw(Canvas canvas) {
188         super.onDraw(canvas);
189         int cycleSize = cycles.length;
190         for (int i = 0; i < cycleSize; i++) {
191             // 画完并且错误
192             if (!canContinue && !result) {
193                 if (cycles[i].isOnTouch()) {
194                     drawInnerCycle(cycles[i], canvas, ERROE_COLOR);
195                     drawOutsideCycle(cycles[i], canvas, ERROE_COLOR);
196                 } else
197                     drawOutsideCycle(cycles[i], canvas, NORMAL_COLOR);
198             }
199             // 绘画中
200             else {
201                 if (cycles[i].isOnTouch()) {
202                     drawInnerCycle(cycles[i], canvas, TOUCH_COLOR);
203                     drawOutsideCycle(cycles[i], canvas, TOUCH_COLOR);
204                 } else
205                     drawOutsideCycle(cycles[i], canvas, NORMAL_COLOR);
206             }
207         }
208 
209         if (!canContinue && !result) {
210             drawLine(canvas, ERROE_COLOR);
211         } else {
212             drawLine(canvas, TOUCH_COLOR);
213         }
214 
215     }
216 
217     /** 画空心圆 */
218     private void drawOutsideCycle(LockCircle lockCircle, Canvas canvas,
219             int color) {
220         paintNormal.setColor(color);
221         canvas.drawCircle(lockCircle.getOx(), lockCircle.getOy(),
222                 lockCircle.getR(), paintNormal);
223     }
224 
225     /** 画横线 */
226     private void drawLine(Canvas canvas, int color) {
227         // 构建路径
228         linePath.reset();
229         if (linedCycles.size() > 0) {
230             int size = linedCycles.size();
231             for (int i = 0; i < size; i++) {
232                 int index = linedCycles.get(i);
233                 float x = cycles[index].getOx();
234                 float y = cycles[index].getOy();
235                 if (i == 0) {
236                     linePath.moveTo(x, y);
237                 } else {
238                     linePath.lineTo(x, y);
239                 }
240             }
241             if (canContinue) {
242                 linePath.lineTo(eventX, eventY);
243             } else {
244                 linePath.lineTo(
245                         cycles[linedCycles.get(linedCycles.size() - 1)].getOx(),
246                         cycles[linedCycles.get(linedCycles.size() - 1)].getOy());
247             }
248             paintLines.setColor(color);
249             canvas.drawPath(linePath, paintLines);
250         }
251     }
252 
253     /** 画中心圆圆 */
254     private void drawInnerCycle(LockCircle myCycle, Canvas canvas, int color) {
255         paintInnerCycle.setColor(color);
256         canvas.drawCircle(myCycle.getOx(), myCycle.getOy(),
257                 myCycle.getR() / 3f, paintInnerCycle);
258     }
259 
260     /**
261      * 每个圆点类
262      */
263     class LockCircle {
264         /** 圆心横坐标 */
265         private float ox;
266         /** 圆心纵坐标 */
267         private float oy;
268         /** 半径长度 */
269         private float r;
270         /** 代表数值 */
271         private Integer num;
272         /** 是否选择:false=未选中 */
273         private boolean onTouch;
274 
275         public float getOx() {
276             return ox;
277         }
278 
279         public void setOx(float ox) {
280             this.ox = ox;
281         }
282 
283         public float getOy() {
284             return oy;
285         }
286 
287         public void setOy(float oy) {
288             this.oy = oy;
289         }
290 
291         public void setOy(int oy) {
292             this.oy = oy;
293         }
294 
295         public float getR() {
296             return r;
297         }
298 
299         public void setR(float r) {
300             this.r = r;
301         }
302 
303         public Integer getNum() {
304             return num;
305         }
306 
307         public void setNum(Integer num) {
308             this.num = num;
309         }
310 
311         public boolean isOnTouch() {
312             return onTouch;
313         }
314 
315         public void setOnTouch(boolean onTouch) {
316             this.onTouch = onTouch;
317         }
318 
319         /** 判读传入位置是否在圆心内部 */
320         public boolean isPointIn(int x, int y) {
321             double distance = Math.sqrt((x - ox) * (x - ox) + (y - oy)
322                     * (y - oy));
323             return distance < r;
324         }
325     }
326 }
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="fill_parent"
 3     android:layout_height="fill_parent"
 4     android:background="#232736"
 5     android:gravity="center"
 6     android:orientation="vertical" >
 7 
 8     <!-- 小头像 -->
 9     <ImageView
10         android:layout_width="70dp"
11         android:layout_height="70dp"
12         android:src="@drawable/tempfenlei" />
13 
14     <TextView
15         android:id="@+id/textview"
16         android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:layout_marginTop="10dp"
19         android:text=""
20         android:textColor="#FF2525"
21         android:textSize="16sp"
22         android:visibility="invisible" />
23 
24     <com.rxx.view.GestureLockView
25         android:id="@+id/gestureLockView"
26         android:layout_width="wrap_content"
27         android:layout_height="wrap_content" />
28 
29     <LinearLayout
30         android:layout_width="fill_parent"
31         android:layout_height="wrap_content"
32         android:orientation="horizontal"
33         android:padding="10dp" >
34 
35         <TextView
36             android:layout_width="fill_parent"
37             android:layout_height="wrap_content"
38             android:layout_weight="1"
39             android:gravity="center"
40             android:text="管理手势密码"
41             android:textColor="#585C6E"
42             android:textSize="16sp" />
43 
44         <TextView
45             android:layout_width="fill_parent"
46             android:layout_height="wrap_content"
47             android:layout_weight="1"
48             android:gravity="center"
49             android:text="登陆其他账号"
50             android:textColor="#585C6E"
51             android:textSize="16sp" />
52     </LinearLayout>
53 
54 </LinearLayout>
 1 package com.rxx.gesturelockdemo;
 2 
 3 import android.app.Activity;
 4 import android.graphics.Color;
 5 import android.os.Bundle;
 6 import android.view.View;
 7 import android.view.animation.Animation;
 8 import android.view.animation.TranslateAnimation;
 9 import android.widget.TextView;
10 
11 import com.rxx.view.GestureLockView;
12 import com.rxx.view.GestureLockView.OnGestureFinishListener;
13 
14 public class MainActivity extends Activity {
15 
16     private GestureLockView gestureLockView;
17     private TextView textview;
18     private Animation animation;
19 
20     @Override
21     protected void onCreate(Bundle savedInstanceState) {
22         super.onCreate(savedInstanceState);
23         setContentView(R.layout.activity_main);
24         init();
25     }
26 
27     /** 初始化 */
28     public void init() {
29         gestureLockView = (GestureLockView) findViewById(R.id.gestureLockView);
30         textview = (TextView) findViewById(R.id.textview);
31         animation = new TranslateAnimation(-20, 20, 0, 0);
32         animation.setDuration(50);
33         animation.setRepeatCount(2);
34         animation.setRepeatMode(Animation.REVERSE);
35         // 设置密码
36         gestureLockView.setKey("1");
37         // 手势完成后回调
38         gestureLockView
39                 .setOnGestureFinishListener(new OnGestureFinishListener() {
40                     @Override
41                     public void OnGestureFinish(boolean success, String key) {
42                         if (success) {
43                             textview.setTextColor(Color.parseColor("#FFFFFF"));
44                             textview.setVisibility(View.VISIBLE);
45                             textview.setText("密码正确!");
46                             textview.startAnimation(animation);
47                         } else {
48                             textview.setTextColor(Color.parseColor("#FF2525"));
49                             textview.setVisibility(View.VISIBLE);
50                             textview.setText("密码错误!");
51                             textview.startAnimation(animation);
52                         }
53                     }
54                 });
55     }
56 }
原文地址:https://www.cnblogs.com/androidsj/p/4290157.html