Android九宮格程序設(shè)計(jì)代碼
本文介紹Android九宮格程序的設(shè)計(jì)代碼,供大家參考,具體內(nèi)容如下
一.相關(guān)介紹
(一)效果顯示
1.程序剛運(yùn)行時(shí)的效果:
2.在頁(yè)面上點(diǎn)擊選擇并滑動(dòng)時(shí)的畫(huà)面
3.選擇密碼之后的顯示
(二)功能介紹
1.點(diǎn)擊某圓圈后,在該圓圈的中心添加一個(gè)實(shí)行的小圓。
2.頁(yè)面滑動(dòng)出現(xiàn)一條跟隨的線(xiàn)。
3.滑動(dòng)到另一個(gè)圓圈時(shí),產(chǎn)生一條連接的直線(xiàn)。
4.選擇的圓圈點(diǎn)數(shù)大于等于4個(gè)后,手指抬起,就會(huì)保存密碼。
4.選擇的圓圈的數(shù)是最大值后,馬上保存密碼。
(三)涉及到的知識(shí)點(diǎn)
本示例使用的是自定義的View來(lái)繪制九宮格,并保存圖像,這里的九個(gè)點(diǎn)分別代表的是九個(gè)數(shù)值,獲取到對(duì)應(yīng)的數(shù)值證明繪制了那個(gè)點(diǎn)。
程序中使用到的知識(shí):
1、圖像的描繪,圓和點(diǎn)的描繪,線(xiàn)的描繪
2、位置的判斷,判斷用戶(hù)點(diǎn)的位置是否在某一個(gè)圓內(nèi)
3、保存數(shù)據(jù)和相關(guān)判斷
二.程序設(shè)計(jì)
(一)自定義View的設(shè)計(jì)
package com.lwz.gongge; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; import java.util.List; /** * Created by Administrator on 2016/10/28 0028. */ public class NineGridView extends View { //構(gòu)造方法 public NineGridView(Context context) { super(context); init(); } //構(gòu)造方法 public NineGridView(Context context, AttributeSet attrs) { super(context, attrs); init(); } //定義一個(gè)畫(huà)實(shí)心圓的畫(huà)筆 Paint paintCircle; //定義一個(gè)畫(huà)線(xiàn)的畫(huà)筆 Paint paintLine; //定義一個(gè)寬度值,大概是屏幕的四分之一,代表的是每一個(gè)圓點(diǎn)間的x軸距離 int width; //定義一個(gè)背景顏色 int backColor; //定義一個(gè)集合用來(lái)存放點(diǎn)擊過(guò)的圓點(diǎn)0到8表示九個(gè)點(diǎn) List<Integer> listPassword = new ArrayList<>(); //觸屏的位置 float currX, currY; //密碼的個(gè)數(shù) int minPassNum = 4; int maxPassNum = 9; //初始化 private void init() { //定義背景顏色 backColor = Color.rgb(0x17, 0x16, 0x25); //實(shí)例化畫(huà)筆,并作基本設(shè)置 paintLine = new Paint(); paintLine.setAntiAlias(true); paintLine.setDither(true); paintLine.setColor(Color.rgb(0x37, 0x91, 0xe6)); paintCircle = new Paint(); paintCircle.setAntiAlias(true); paintCircle.setDither(true); paintCircle.setColor(backColor); } //丈量屏幕時(shí)回調(diào)的方法,在這個(gè)方法內(nèi)可以取得屏幕的寬度 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getWidth() / 4; } //屏幕圖像繪制回調(diào)的方法 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //設(shè)置屏幕的顏色,(清屏) canvas.drawColor(backColor); //畫(huà)線(xiàn),如果數(shù)據(jù)集合內(nèi)有數(shù)據(jù)才能去畫(huà)線(xiàn) if (listPassword.size() > 0) { //求出最后畫(huà)的那個(gè)點(diǎn)來(lái)做畫(huà)線(xiàn) //這里求得是坐標(biāo)點(diǎn) int x = listPassword.get(listPassword.size() - 1) % 3 + 1;//x軸的方向 int y = listPassword.get(listPassword.size() - 1) / 3 + 1;//y軸的方向 //設(shè)置畫(huà)線(xiàn)的大小 paintLine.setStrokeWidth(8); //畫(huà)線(xiàn),從具體點(diǎn)的位置到觸屏的位置 canvas.drawLine(x * width, y * width, currX, currY, paintLine); //再畫(huà)一個(gè)圓覆蓋掉圓圈內(nèi)的那些線(xiàn) canvas.drawCircle(x * width, y * width, width / 3, paintCircle); //如果集合的數(shù)據(jù)中還有其他的點(diǎn)的數(shù)據(jù) if (listPassword.size() > 1) { //按順序畫(huà)線(xiàn) for (int i = 0; i < listPassword.size() - 1; i++) {//防止越界 //獲取當(dāng)前的一個(gè)i和后面的一個(gè)i //前一個(gè)點(diǎn)的坐標(biāo)點(diǎn) int x1 = listPassword.get(i) % 3 + 1; int y1 = listPassword.get(i) / 3 + 1; //后一個(gè)點(diǎn)的坐標(biāo)點(diǎn) int x2 = listPassword.get(i + 1) % 3 + 1; int y2 = listPassword.get(i + 1) / 3 + 1; //設(shè)置畫(huà)筆的大小 paintLine.setStrokeWidth(8); //畫(huà)線(xiàn),從上一個(gè)點(diǎn)的位置到下一個(gè)點(diǎn)的位置 canvas.drawLine(x1 * width, y1 * width, x2 * width, y2 * width, paintLine); //再畫(huà)一個(gè)圓覆蓋掉圓圈內(nèi)的那些線(xiàn),這里覆蓋的是后面的一個(gè)圓的線(xiàn) canvas.drawCircle(x1 * width, y1 * width, width / 3, paintCircle); } } } //繪制九個(gè)圓圈,用的是線(xiàn) //設(shè)置寬度 paintLine.setStrokeWidth(2); //設(shè)置空心必須要的 paintLine.setStyle(Paint.Style.STROKE); //開(kāi)始畫(huà)圓9個(gè),這里圓的半徑暫時(shí)設(shè)置為圓距離的3分之一 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { //一個(gè)參數(shù)是圓點(diǎn)的x軸的坐標(biāo)值 //二個(gè)參數(shù)是圓點(diǎn)的y軸的坐標(biāo)值 canvas.drawCircle(width * (i + 1), width * (j + 1), width / 3, paintLine); //這里的圖像的y軸上不一定是在中心,但是整體是個(gè)正方形,效果差不多就可以了 } } //繪制實(shí)心圓在圓圈里面,顏色和外面的圓圈的顏色是一樣的,用同一只筆 //這里要判斷你劃過(guò)幾個(gè)點(diǎn),對(duì)集合進(jìn)行遍歷 //設(shè)置實(shí)心樣式 paintLine.setStyle(Paint.Style.FILL); for (int i = 0; i < listPassword.size(); i++) { //取出集合里面的數(shù) int p = listPassword.get(i); int x = p % 3; int y = p / 3; //一個(gè)參數(shù)是圓點(diǎn)的x軸的坐標(biāo)值 //二個(gè)參數(shù)是圓點(diǎn)的y軸的坐標(biāo)值 canvas.drawCircle(width * (x + 1), width * (y + 1), width / 6, paintLine); } } //觸摸屏幕的監(jiān)聽(tīng)事件 @Override public boolean onTouchEvent(MotionEvent event) { //獲取用戶(hù)點(diǎn)擊的坐標(biāo)位置 float x = event.getX(); float y = event.getY(); //判斷用戶(hù)的行為并作相應(yīng)的操作 switch (event.getAction()) { case MotionEvent.ACTION_DOWN://觸屏?xí)r //判斷用戶(hù)是否點(diǎn)擊在某個(gè)圓點(diǎn)范圍內(nèi) if (connetCircle(x, y) != -1) { //更新位置 currX = x; currY = y; //把這個(gè)點(diǎn)的位置添加到存放數(shù)據(jù)的集合中 listPassword.add(connetCircle(x, y)); } break; case MotionEvent.ACTION_UP://手指抬起時(shí) //如果密碼的值到到達(dá)最小位數(shù)后保存密碼給主頁(yè)面 if (listPassword.size() >= minPassNum) { //如果另一邊實(shí)現(xiàn)了監(jiān)聽(tīng)事件,那么就給他數(shù)據(jù) if (listener != null) { //把密碼傳遞過(guò)去 listener.toListenerThePassword(getPasswordString()); } } //清空數(shù)據(jù) listPassword.clear(); break; case MotionEvent.ACTION_MOVE://手指移動(dòng)時(shí) //更新位置 currX = x; currY = y; //移動(dòng)到其他的圓中,那么就添加數(shù)據(jù)到集合中 //獲取該點(diǎn)的位置 int point = connetCircle(x, y); //如果這個(gè)點(diǎn)是在圓內(nèi),并且數(shù)據(jù)里面不包含這個(gè)點(diǎn)的值,那么就添加這個(gè)點(diǎn)的值到集合中 if (point != -1 && !listPassword.contains((Integer) point)) { listPassword.add(point); } //如果密碼的值到到最大值后保存密碼給主頁(yè)面 if (listPassword.size() >= maxPassNum) { //如果另一邊實(shí)現(xiàn)了監(jiān)聽(tīng)事件,那么就給他數(shù)據(jù) if (listener != null) { //把密碼傳遞過(guò)去 listener.toListenerThePassword(getPasswordString()); } break; } } //不管是上面是什么行為最后都要刷新一下屏幕 invalidate();//屏幕重繪 return true; } //判斷用戶(hù)點(diǎn)擊的地方是否在某一個(gè)圓點(diǎn)內(nèi) private boolean isInCircle(float x, float y, float cx, float cy) { //x、y代表的是坐標(biāo)位置 //cx、cy代表的是圓坐標(biāo)位置 //圓點(diǎn)半徑是width/3 //如果點(diǎn)擊的位置減去圓心的位置的平方小于半徑的平方那么這個(gè)點(diǎn)是在圓內(nèi)的 return (x - cx) * (x - cx) + (y - cy) * (y - cy) < (width / 3) * (width / 3); } //判斷用戶(hù)點(diǎn)擊的地方是否在九個(gè)圓點(diǎn)的哪一個(gè)圓點(diǎn)內(nèi) private int connetCircle(float x, float y) { //x、y代表的是坐標(biāo)位置 //依次判斷每個(gè)圓圈看看是否在它的里面 //圓點(diǎn)的坐標(biāo)位置-->(width,width)--(2*width,width)--(3*width,width) //--->(width,2*width)--(2*width,2*width)--(3*width,2*width) //--->(width,3*width)--(2*width,3*width)--(3*width,3*width) for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (isInCircle(x, y, width * (j + 1), width * (i + 1))) {//(i,j) //如果點(diǎn)擊是圓,就把這個(gè)點(diǎn)的值添加到集合中 //0 1 2 (0,0)/(0,1)/(0/2) //3 4 5 (1,0)/(1,1)/(1/2) //6 7 8 (2,0)/(2,1)/(2/2) //如果是7,那么游標(biāo)值(2,1) //返回該點(diǎn)的值 return (3 * i + j); } } } //如果不在九個(gè)圓點(diǎn)位置就返回-1 return -1; } //創(chuàng)建一個(gè)回調(diào)接口,讓主頁(yè)面監(jiān)聽(tīng)這個(gè)事件 interface onFinishListener { void toListenerThePassword(String s); } //設(shè)置一個(gè)監(jiān)聽(tīng)接口的對(duì)象 onFinishListener listener; //設(shè)置監(jiān)聽(tīng)接口的方法 public void setListener(onFinishListener listener) { this.listener = listener; } //獲取密碼的字符串 public String getPasswordString() { //定義密碼的字符串 String pass = ""; //取出集合里面的密碼的數(shù)字 for (int i = 0; i < listPassword.size(); i++) { pass += listPassword.get(i); } return pass; } }
(二)主方法調(diào)用這個(gè)View的類(lèi)
package com.lwz.gongge; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.Toast; public class MainActivity extends AppCompatActivity { //自定義View傳遞過(guò)來(lái)的密碼 String password = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //定義自定義的View并實(shí)例化 NineGridView nine = new NineGridView(this); //顯示自定義的View setContentView(nine); //通過(guò)監(jiān)聽(tīng)方法來(lái)獲取自定義傳來(lái)的密碼 //給視圖設(shè)置監(jiān)聽(tīng)事件 nine.setListener(new NineGridView.onFinishListener() { @Override public void toListenerThePassword(String pass) { //這里的pass是自定義View里面,傳過(guò)來(lái)的數(shù)據(jù) password = pass; //土司密碼 Toast.makeText(MainActivity.this, "密碼:" + password, Toast.LENGTH_SHORT).show(); } }); } }
上面就是九宮格程序設(shè)計(jì)的代碼了。這里沒(méi)有用到xml的布局文件,都是用代碼實(shí)現(xiàn)的。
完成自定義View后,調(diào)用和使用都是比較簡(jiǎn)單的,可以作為一個(gè)工具類(lèi)使用,獲取到自定義View傳過(guò)來(lái)的密碼,可以做其他保存操作,比如保存到本地文件或數(shù)據(jù)庫(kù)中,這里只是做了土司操作,讓用戶(hù)看到效果。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android 九宮格的實(shí)現(xiàn)方法
- android 九宮格滑動(dòng)解鎖開(kāi)機(jī)實(shí)例源碼學(xué)習(xí)
- Android實(shí)現(xiàn)九宮格(GridView中各項(xiàng)平分空間)的方法
- Android開(kāi)發(fā)之實(shí)現(xiàn)GridView支付寶九宮格
- Android編程之九宮格實(shí)現(xiàn)方法實(shí)例分析
- Android實(shí)現(xiàn)九宮格解鎖
- 使用Android自定義控件實(shí)現(xiàn)滑動(dòng)解鎖九宮格
- Android打造流暢九宮格抽獎(jiǎng)活動(dòng)效果
- 輕松實(shí)現(xiàn)Android自定義九宮格圖案解鎖
- Android九宮格手勢(shì)密碼代碼設(shè)計(jì)
- Android編程簡(jiǎn)單實(shí)現(xiàn)九宮格示例
相關(guān)文章
Android使用JobScheduler定期推送本地通知實(shí)例代碼
本篇文章主要介紹了Android使用JobScheduler定期推送本地通知實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06java從輸入流中獲取數(shù)據(jù)并返回字節(jié)數(shù)組示例
這篇文章主要介紹了java從輸入流中獲取數(shù)據(jù)并以字節(jié)數(shù)組返回,這是一個(gè)常用的方法,以后可以直接拿來(lái)用。這種輸入流可以來(lái)自Android本地,也可以來(lái)自網(wǎng)絡(luò)2014-01-01Android實(shí)現(xiàn)Service重啟的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Service重啟的方法,涉及Android操作Service組件實(shí)現(xiàn)服務(wù)重啟的功能,需要的朋友可以參考下2015-05-05Android 7.0 運(yùn)行時(shí)權(quán)限彈窗問(wèn)題的解決
這篇文章主要介紹了Android 7.0 運(yùn)行時(shí)權(quán)限彈窗問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Android 開(kāi)發(fā)中fragment預(yù)加載問(wèn)題
這篇文章主要介紹了Android 開(kāi)發(fā)中fragment預(yù)加載問(wèn)題的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01android自定義ListView實(shí)現(xiàn)底部View自動(dòng)隱藏和消失的功能
本篇文章主要介紹了android自定義ListView實(shí)現(xiàn)底部View自動(dòng)隱藏和消失的功能 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03Android Chronometer控件實(shí)現(xiàn)計(jì)時(shí)器函數(shù)詳解
這篇文章主要為大家詳細(xì)介紹了Android Chronometer控件實(shí)現(xiàn)計(jì)時(shí)器函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04adb通過(guò)wifi連接android設(shè)備流程解析
這篇文章主要介紹了adb通過(guò)wifi連接android設(shè)備流程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12Android開(kāi)發(fā)中使用外部應(yīng)用獲取SD卡狀態(tài)的方法
這篇文章主要介紹了Android開(kāi)發(fā)中使用外部應(yīng)用獲取SD卡狀態(tài)的方法,簡(jiǎn)單分析了Android監(jiān)聽(tīng)SD卡狀態(tài)的方法,并結(jié)合實(shí)例形式分析了Android外部應(yīng)用獲取SD卡狀態(tài)的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11