屏幕锁案例
轉載請注明出處:??http://blog.csdn.net/forwardyzk/article/details/42676213
現在的手機都有屏幕鎖,有圖案的,有數字的。下面介紹一個使用圖案的屏幕鎖。
思路:
1.根據屏幕的寬度,計算出9個點的坐標和半徑。
2.使用畫筆畫出9個圓。
3.根據觸摸的坐標判斷是否在圓的范圍之內,如果在圓的范圍之內,表示此圓被觸摸了。
4.根絕觸摸圓的順序,根據圓心,構建滑動的path,然后使用畫筆畫出。
計算圓的圓心和半徑
int perSize = 0;if (cycles == null && (perSize = getWidth() / 6) > 0) {cycles = new MyCycle[9];for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {MyCycle cycle = new MyCycle();cycle.setNum(i * 3 + j);cycle.setOx(perSize * (j * 2 + 1));cycle.setOy(perSize * (i * 2 + 1));cycle.setR(perSize * 0.5f);cycles[i * 3 + j] = cycle;}}} 根絕控件的寬度,將控件的寬度分為6部分,圓心在1,3,5的線上。
如圖:
初始化畫筆
paintNormal = new Paint();paintNormal.setAntiAlias(true);paintNormal.setStrokeWidth(3);paintNormal.setStyle(Paint.Style.STROKE);setAntiAlias(true):設置線的邊緣平滑
setStrokeWidth():設置線寬
setStyle()設置樣式Paint.Style.STROKE ,Paint.Style.FILL,Paint.Style.FILL_STROKE
在onTouchEvevt()對觸摸事件進行處理
public boolean onTouchEvent(MotionEvent event) {if (canContinue) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE: {eventX = (int) event.getX();eventY = (int) event.getY();for (int i = 0; i < cycles.length; i++) {if (cycles[i].isPointIn(eventX, eventY)) {cycles[i].setOnTouch(true);if (!linedCycles.contains(cycles[i].getNum())) {linedCycles.add(cycles[i].getNum());}}}break;}case MotionEvent.ACTION_UP: {// 暫停觸碰canContinue = false;if (linedCycles.size() >= minCountCycle) {// 大于等于連接圓的最小個數// 檢查結果StringBuffer sb = new StringBuffer();for (int i = 0; i < linedCycles.size(); i++) {sb.append(linedCycles.get(i));}result = key.equals(sb.toString());if (onGestureFinishListener != null) {onGestureFinishListener.OnGestureFinish(result);}} else {Toast.makeText(getContext(), "最少連接" + minCountCycle + "個圓",0).show();}timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {// 還原eventX = eventY = 0;for (int i = 0; i < cycles.length; i++) {cycles[i].setOnTouch(false);}linedCycles.clear();linePath.reset();canContinue = true;postInvalidate();}}, 1000);break;}}invalidate();}return true;}
MotionEvent.ACTION_DOWN和MotionEvent.ACTION_MOVE中根據按下和移動的坐標,判斷是在那一個圓形圖形范圍內,如在其范圍內,那么就添加到一個保存觸摸的圓的集合中。為了計算其滑動的線路和判斷線路是否正確。在添加之前,要保證集合中沒有此圓,否則線路就會重復。
MotionEvent.ACTION_UP:在手指離開的時候,根絕存放觸摸圓的集合,計算其觸摸的順序(形成的圖形)是否正確,是根絕圓對象的代表的數字做判斷。當手指離開時,把計算結果通過接口傳遞出去。
public class MyCycle {private int ox; // 圓心橫坐標private int oy; // 圓心縱坐標private float r; // 半徑長度private Integer num; // 代表數值private boolean onTouch; // false=未選中public int getOx() {return ox;}public void setOx(int ox) {this.ox = ox;}public int getOy() {return oy;}public void setOy(int oy) {this.oy = oy;}public float getR() {return r;}public void setR(float r) {this.r = r;}public Integer getNum() {return num;}public void setNum(Integer num) {this.num = num;}public boolean isOnTouch() {return onTouch;}public void setOnTouch(boolean onTouch) {this.onTouch = onTouch;}public boolean isPointIn(int x, int y) {double distance = Math.sqrt((x - ox) * (x - ox) + (y - oy) * (y - oy));return distance < r;}
判斷是否在其范圍內是亮點之間的距離是否小于半徑來做判斷。
要記得最后離開的后,延遲清除觸摸的圖形。
在onDraw方法中,根絕觸摸的順序,觸摸的狀態隨時更改圖形的顏色。
protected void onDraw(Canvas canvas) {super.onDraw(canvas);for (int i = 0; i < cycles.length; i++) {if (!canContinue && !result) {paintOnTouch.setColor(ERROR_COLOR);paintInnerCycle.setColor(ERROR_COLOR);paintLines.setColor(ERROR_COLOR);} else if (cycles[i].isOnTouch()) {paintOnTouch.setColor(OUT_CYCLE_ONTOUCH);paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);paintLines.setColor(LINE_COLOR);} else {paintNormal.setColor(OUT_CYCLE_NORMAL);paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);paintLines.setColor(LINE_COLOR);}if (cycles[i].isOnTouch()) {if (!isShowPattern) {canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),cycles[i].getR(), paintNormal);} else {canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),cycles[i].getR(), paintOnTouch);drawInnerBlueCycle(cycles[i], canvas);}} else {canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),cycles[i].getR(), paintNormal);}}drawLine(canvas);}
有四中畫筆,paintNormal:正常顯示的使用的畫筆,paintOnTouch:觸摸后的外圓使用的畫筆,paintInnerCycle:觸摸后的內圓使用的畫筆,paintLines:連線使用的畫筆。
根絕當前的狀態,設置畫筆的的顏色,顏色如下
對應五種顏色
private int OUT_CYCLE_NORMAL = Color.rgb(108, 119, 138); // 正常外圓顏色private int OUT_CYCLE_ONTOUCH = Color.rgb(025, 066, 103); // 選中外圓顏色private int INNER_CYCLE_ONTOUCH = Color.rgb(002, 210, 255); // 選擇內圓顏色private int LINE_COLOR = Color.argb(127, 002, 210, 255); // 連接線顏色private int ERROR_COLOR = Color.argb(127, 255, 000, 000); // 連接錯誤醒目提示顏色
畫出觸摸的線路
private void drawLine(Canvas canvas) {if (!isShowPattern) {return;}linePath.reset();if (linedCycles.size() > 0) {for (int i = 0; i < linedCycles.size(); i++) {int index = linedCycles.get(i);float x = cycles[index].getOx();float y = cycles[index].getOy();if (i == 0) {linePath.moveTo(x, y);} else {linePath.lineTo(x, y);}}if (canContinue) {linePath.lineTo(eventX, eventY);} else {linePath.lineTo(cycles[linedCycles.get(linedCycles.size() - 1)].getOx(),cycles[linedCycles.get(linedCycles.size() - 1)].getOy());}canvas.drawPath(linePath, paintLines);}} 根絕觸摸過的圓的圓心,按照順序把圓心連接起啦,就構成了連接的線路。
使用的主要方法有:
setMinCountCycle(int minCountCycle):設置連接最小圓的個數,默認為1
setShowPattern(boolean isShowPath):是否顯示連接的圖案,默認顯示
setOnGestureFinishListener(
OnGestureFinishListener onGestureFinishListener):設置結果返回值監聽
setKey(String key):設置正確圖案代表的值
==========================================
設置畫筆的顏色和線寬,不設置有默認值
setErrorColor(int color):結果錯誤顯示的顏色
setLinesPaint(float width, int color):設置連線的線寬和顏色
setNormalPaint(float width, int color):設置默認外圓展示的線寬和顏色
setOnTouchPaint(float width, int color):設置觸摸外圓的線寬和顏色
setInnerCyclePaint(float width, int color):設置觸摸內圓的線寬和顏色
使用步驟:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/start_background"tools:context=".MainActivity" ><com.example.view.GestureLockViewandroid:id="@+id/gv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:background="#0000" /></RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {private GestureLockView gv;private SharedPreLockUtils spUtil;@Overrideprotected void onCreate(Bundle savedInstanceState) {requestWindowFeature(Window.FEATURE_NO_TITLE);super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);spUtil = SharedPreLockUtils.getInstance(getApplicationContext());gv = (GestureLockView) findViewById(R.id.gv);gv.setKey("0124678"); // Z 字型gv.setOnGestureFinishListener(new OnGestureFinishListener() {@Overridepublic void OnGestureFinish(boolean success) {Toast.makeText(MainActivity.this, String.valueOf(success),Toast.LENGTH_SHORT).show();if (success) {startSettingActivity();}}});gv.setShowPattern(spUtil.getIsShowPattern());}public void startSettingActivity() {MainActivity.this.startActivity(new Intent(MainActivity.this,SettingActivity.class));}@Overrideprotected void onResume() {super.onResume();gv.setShowPattern(spUtil.getIsShowPattern());if (spUtil.getBoolean("ISCHANGE", false)) {gv.setNormalPaint(3f,MainActivity.this.getResources().getColor(android.R.color.holo_red_light));gv.setLinesPaint(10f,MainActivity.this.getResources().getColor(android.R.color.holo_green_light));gv.setInnerCyclePaint(25f, MainActivity.this.getResources().getColor(android.R.color.darker_gray));gv.setOnTouchPaint(10f,MainActivity.this.getResources().getColor(android.R.color.holo_orange_dark));gv.setErrorColor(MainActivity.this.getResources().getColor(android.R.color.holo_purple));}} }
使用了滑動開關,其使用方法請參考自定義滑動開關
源碼下載:?http://download.csdn.net/detail/forwardyzk/8357367
效果圖:
總結
- 上一篇: 张宇1000题线性代数 第八章 相似理论
- 下一篇: email_shoping__案例