Android自制九宮格解鎖控件
本文實(shí)例為大家分享了Android自制九宮格解鎖控件的具體代碼,供大家參考,具體內(nèi)容如下
前兩天從網(wǎng)上學(xué)習(xí)了下如何自定義一個(gè)九宮格解鎖的控件,于是自己根據(jù)邏輯寫(xiě)了一遍,自定義控件的代碼如下:
public class LockedView extends View { ? ? ? private boolean isFirst = true;//設(shè)置第一次加載時(shí)為true,后面重新畫(huà)圖不再執(zhí)行 ? ? private int width, height;//獲取控件的寬度和高度 ? ? private int offsetX, offsetY;//獲取點(diǎn)坐標(biāo)時(shí)的X軸和Y軸的偏移量 ? ? private Point[][] pointList;//每個(gè)點(diǎn)的坐標(biāo)存放的數(shù)組 ? ? private int r;//每個(gè)圓的半徑 ? ? private Bitmap map1, map2, map3;//3種狀態(tài)的bitmap ? ? private float eventX, eventY;//觸摸控件時(shí)的X坐標(biāo)和Y坐標(biāo) ? ? private boolean isPressed;//判斷是否觸摸著控件 ? ? private boolean moveOnPoint;//判斷是否移動(dòng)到一個(gè)點(diǎn)上了 ? ? private boolean isFinish;//判斷手勢(shì)是否結(jié)束 ? ? private List<Point> list = new ArrayList<>();//存放經(jīng)過(guò)的點(diǎn)的集合 ? ? private Point checkedPoint; ? ? private Paint paint;//畫(huà)筆 ? ? public static final int LOCKED_FIRST=0;//第一次加載acitivity時(shí)設(shè)置密碼時(shí)的返回值 ? ? public static final int LOCKED_TRUE=1;//解鎖成功時(shí)的返回值 ? ? public static final int LOCKED_FALSE=2;//解鎖失敗的返回值 ? ? private OnLockedChangedListener onLocked;//接口回調(diào) ? ? ? public LockedView(Context context, AttributeSet attrs) { ? ? ? ? super(context, attrs); ? ? ? } ? ? ? @Override ? ? protected void onDraw(Canvas canvas) { ? ? ? ? super.onDraw(canvas); ? ? ? ? //判斷是否第一次加載 ? ? ? ? if (isFirst) { ? ? ? ? ? ? //初始化點(diǎn)坐標(biāo) ? ? ? ? ? ? initPoints(); ? ? ? ? ? ? //初始化畫(huà)筆 ? ? ? ? ? ? initPaint(); ? ? ? ? ? ? isFirst = false; ? ? ? ? } ? ? ? ? //根據(jù)每個(gè)點(diǎn)的狀態(tài)來(lái)畫(huà)對(duì)應(yīng)的bitmap ? ? ? ? drawPoints(canvas); ? ? ? ? //畫(huà)手勢(shì)滑動(dòng)過(guò)程中的線 ? ? ? ? drawLines(canvas); ? ? } ? ? ? //初始化畫(huà)筆 ? ? private void initPaint() { ? ? ? ? paint = new Paint(Paint.ANTI_ALIAS_FLAG); ? ? ? ? //設(shè)置畫(huà)筆顏色為藍(lán)色 ? ? ? ? paint.setColor(getResources().getColor(R.color.LockedColor)); ? ? ? ? //設(shè)置畫(huà)筆的寬度為8 ? ? ? ? paint.setStrokeWidth(8); ? ? } ? ? ? //畫(huà)線 ? ? private void drawLines(Canvas canvas) { ? ? ? ? //如果集合有值 ? ? ? ? if (list.size() > 0) { ? ? ? ? ? ? //獲得起始點(diǎn)的實(shí)例 ? ? ? ? ? ? Point startPoint = list.get(0); ? ? ? ? ? ? for (int i = 1; i < list.size(); i++) { ? ? ? ? ? ? ? ? //獲得停止點(diǎn)的實(shí)例 ? ? ? ? ? ? ? ? Point stopPoint = list.get(i); ? ? ? ? ? ? ? ? //根據(jù)起始點(diǎn)坐標(biāo)跟停止點(diǎn)坐標(biāo)來(lái)畫(huà)線 ? ? ? ? ? ? ? ? canvas.drawLine(startPoint.getX(), startPoint.getY(), stopPoint.getX(), stopPoint.getY(), paint); ? ? ? ? ? ? ? ? //把停止點(diǎn)賦值給起始點(diǎn),這樣每次遍歷的時(shí)候起始點(diǎn)都是上一個(gè)點(diǎn) ? ? ? ? ? ? ? ? startPoint = stopPoint; ? ? ? ? ? ? } ? ? ? ? ? ? //如果沒(méi)有移動(dòng)到一個(gè)點(diǎn)上 ? ? ? ? ? ? if (moveOnPoint == false) { ? ? ? ? ? ? ? ? //則根據(jù)最后個(gè)點(diǎn)的坐標(biāo)跟當(dāng)前手勢(shì)移動(dòng)的坐標(biāo)畫(huà)線 ? ? ? ? ? ? ? ? canvas.drawLine(startPoint.getX(), startPoint.getY(), eventX, eventY, paint); ? ? ? ? ? ? } ? ? ? ? ? } ? ? } ? ? ? //設(shè)置觸摸事件 ? ? @Override ? ? public boolean onTouchEvent(MotionEvent event) { ? ? ? ? //獲得觸摸的X坐標(biāo) ? ? ? ? eventX = event.getX(); ? ? ? ? //獲得觸摸的Y坐標(biāo) ? ? ? ? eventY = event.getY(); ? ? ? ? //每次觸摸到離開(kāi)屏幕之前都默認(rèn)為沒(méi)有完成 ? ? ? ? isFinish = false; ? ? ? ? //默認(rèn)移動(dòng)到點(diǎn)上了 ? ? ? ? moveOnPoint = true; ? ? ? ? //選中的點(diǎn) ? ? ? ? checkedPoint = null; ? ? ? ? switch (event.getAction()) { ? ? ? ? ? ? case MotionEvent.ACTION_DOWN: ? ? ? ? ? ? ? ? //如果按下,重置下點(diǎn) ? ? ? ? ? ? ? ? reset(); ? ? ? ? ? ? ? ? //根據(jù)觸摸的X,Y坐標(biāo)以及圓的半徑來(lái)判斷是否觸摸到了一個(gè)圓上,如果有則返回實(shí)例,沒(méi)有則返回空 ? ? ? ? ? ? ? ? checkedPoint = checkPoint(eventX, eventY, r); ? ? ? ? ? ? ? ? if (checkedPoint != null) { ? ? ? ? ? ? ? ? ? ? //如果實(shí)例不為空,則設(shè)置選中點(diǎn)的狀態(tài)為選中 ? ? ? ? ? ? ? ? ? ? checkedPoint.setState(Point.POINT_XUANZHONG); ? ? ? ? ? ? ? ? ? ? //第一次按下按到點(diǎn)上時(shí)設(shè)置為true ? ? ? ? ? ? ? ? ? ? isPressed = true; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_MOVE: ? ? ? ? ? ? ? ? //如果按下在一個(gè)點(diǎn)上,就會(huì)執(zhí)行移動(dòng)動(dòng)作的邏輯 ? ? ? ? ? ? ? ? if (isPressed) { ? ? ? ? ? ? ? ? ? ? //同上 ? ? ? ? ? ? ? ? ? ? checkedPoint = checkPoint(eventX, eventY, r); ? ? ? ? ? ? ? ? ? ? if (checkedPoint != null) { ? ? ? ? ? ? ? ? ? ? ? ? checkedPoint.setState(Point.POINT_XUANZHONG); ? ? ? ? ? ? ? ? ? ? ? ? //如果實(shí)例不為空,則設(shè)置移動(dòng)到了點(diǎn)上 ? ? ? ? ? ? ? ? ? ? ? ? moveOnPoint = true; ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? //否則設(shè)置沒(méi)有移動(dòng)到點(diǎn)上 ? ? ? ? ? ? ? ? ? ? ? ? moveOnPoint = false; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_UP: ? ? ? ? ? ? ? ? //抬起時(shí),設(shè)置第一次按在點(diǎn)上的參數(shù)為false以及完成了觸摸過(guò)程 ? ? ? ? ? ? ? ? isPressed = false; ? ? ? ? ? ? ? ? isFinish = true; ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_CANCEL: ? ? ? ? ? ? ? ? isPressed = false; ? ? ? ? ? ? ? ? isFinish = true; ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? //如果第一下按在了點(diǎn)上并且沒(méi)有完成觸摸并且選中的點(diǎn)的實(shí)例不為空 ? ? ? ? if (isPressed && !isFinish && checkedPoint != null) { ? ? ? ? ? ? //判斷這個(gè)實(shí)例是否在list集合中 ? ? ? ? ? ? if (isInList(checkedPoint)) { ? ? ? ? ? ? ? ? //如果在,則設(shè)置沒(méi)有移動(dòng)在點(diǎn)上 ? ? ? ? ? ? ? ? moveOnPoint = false; ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? //否則就添加到集合里面 ? ? ? ? ? ? ? ? list.add(checkedPoint); ? ? ? ? ? ? } ? ? ? ? ? ? //如果完成了觸摸 ? ? ? ? } else if (isFinish) { ? ? ? ? ? ? if (list.size() > 0) { ? ? ? ? ? ? ? ? //如果集合長(zhǎng)度為1,則表示只是摸到了一個(gè)點(diǎn),直接重置 ? ? ? ? ? ? ? ? if(list.size()==1){ ? ? ? ? ? ? ? ? ? ? reset(); ? ? ? ? ? ? ? ? ? ? //如果集合長(zhǎng)度小于5,則表示密碼太短了不符合要求,把選中的點(diǎn)設(shè)置為錯(cuò)誤狀態(tài),并且通過(guò)接口回調(diào)返回?cái)?shù)據(jù) ? ? ? ? ? ? ? ? }else if(list.size()<5){ ? ? ? ? ? ? ? ? ? ? errorPoint(); ? ? ? ? ? ? ? ? ? ? if(onLocked!=null){ ? ? ? ? ? ? ? ? ? ? ? ? onLocked.onResult("密碼太短"); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? //如果集合長(zhǎng)度滿足要求,則通過(guò)接口的返回值,來(lái)判斷不同的情況 ? ? ? ? ? ? ? ? }else if(list.size()>=5){ ? ? ? ? ? ? ? ? ? ? StringBuffer buffer=new StringBuffer(); ? ? ? ? ? ? ? ? ? ? for(int i=0;i<list.size();i++){ ? ? ? ? ? ? ? ? ? ? ? ? buffer.append(list.get(i).getIndex()); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? if(onLocked!=null){ ? ? ? ? ? ? ? ? ? ? ? ? switch (onLocked.onPassword(buffer.toString())){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? //第一次打開(kāi)activity時(shí),shared里面沒(méi)有值,則把當(dāng)前的密碼存到shared里 ? ? ? ? ? ? ? ? ? ? ? ? ? ? case LOCKED_FIRST: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? onLocked.onResult("設(shè)置密碼成功"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? reset(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? //如果shared里面有值,則根據(jù)值對(duì)比下當(dāng)前的密碼值,如果一樣則解鎖成功,不一樣則失敗 ? ? ? ? ? ? ? ? ? ? ? ? ? ? case LOCKED_TRUE: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? onLocked.onResult("解鎖成功"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? reset(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? case LOCKED_FALSE: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? onLocked.onResult("解鎖失敗"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? errorPoint(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? //重新調(diào)用onDraw方法 ? ? ? ? ? ? ? ? ? ? ? ? postInvalidate(); ? ? ? ? ? ? ? ? ? ? ? ? //此次觸摸消費(fèi)掉 ? ? ? ? ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? ? postInvalidate(); ? ? ? ? return true; ? ? } ? ? ? //設(shè)置錯(cuò)誤的點(diǎn)的狀態(tài) ? ? private void errorPoint() { ? ? ? ? for(int i=0;i<list.size();i++){ ? ? ? ? ? ? list.get(i).setState(Point.POINT_XUANCUO); ? ? ? ? } ? ? } ? ? ? //判斷點(diǎn)是否在集合里面 ? ? private boolean isInList(Point checkedPoint) { ? ? ? ? return list.contains(checkedPoint); ? ? } ? ? ? //根據(jù)觸摸點(diǎn)的X,Y軸坐標(biāo)以及圓半徑判斷是否觸摸到了一個(gè)圓 ? ? private Point checkPoint(float eventX, float eventY, int r) { ? ? ? ? for (int i = 0; i < pointList.length; i++) { ? ? ? ? ? ? for (int j = 0; j < pointList[i].length; j++) { ? ? ? ? ? ? ? ? Point point = pointList[i][j]; ? ? ? ? ? ? ? ? double juli = getPointJuli(eventX, eventY, point.getX(), point.getY()); ? ? ? ? ? ? ? ? if (juli < r) { ? ? ? ? ? ? ? ? ? ? return point; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return null; ? ? } ? ? ? //重置點(diǎn) ? ? private void reset() { ? ? ? ? for (int i = 0; i < list.size(); i++) { ? ? ? ? ? ? list.get(i).setState(Point.POINT_MOREN); ? ? ? ? } ? ? ? ? list.clear(); ? ? } ? ? ? //獲取兩點(diǎn)之間的距離 ? ? private double getPointJuli(float eventX, float eventY, int x, int y) { ? ? ? ? return Math.sqrt(Math.abs(eventX - x) * Math.abs(eventX - x) + Math.abs(eventY - y) * Math.abs(eventY - y)); ? ? } ? ? ? ? //根據(jù)點(diǎn)的狀態(tài)來(lái)畫(huà)點(diǎn) ? ? private void drawPoints(Canvas canvas) { ? ? ? ? for (int i = 0; i < pointList.length; i++) { ? ? ? ? ? ? for (int j = 0; j < pointList[i].length; j++) { ? ? ? ? ? ? ? ? Point point = pointList[i][j]; ? ? ? ? ? ? ? ? switch (point.getState()) { ? ? ? ? ? ? ? ? ? ? case Point.POINT_MOREN: ? ? ? ? ? ? ? ? ? ? ? ? canvas.drawBitmap(map1, point.getX() - r, point.getY() - r, null); ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? case Point.POINT_XUANZHONG: ? ? ? ? ? ? ? ? ? ? ? ? canvas.drawBitmap(map2, point.getX() - r, point.getY() - r, null); ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? ? ? case Point.POINT_XUANCUO: ? ? ? ? ? ? ? ? ? ? ? ? canvas.drawBitmap(map3, point.getX() - r, point.getY() - r, null); ? ? ? ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? //初始化點(diǎn)坐標(biāo)和bitmap ? ? private void initPoints() { ? ? ? ? //獲得控件的寬度 ? ? ? ? width = getWidth(); ? ? ? ? //獲得控件的高度 ? ? ? ? height = getHeight(); ? ? ? ? //設(shè)置X的偏移量為0 ? ? ? ? offsetX = 0; ? ? ? ? //設(shè)置Y的偏移量為0 ? ? ? ? offsetY = 0; ? ? ? ? //如果是豎屏則 ? ? ? ? if (width < height) { ? ? ? ? ? ? offsetY = (height - width) / 2; ? ? ? ? ? ? height = width; ? ? ? ? } else { ? ? ? ? ? ? offsetX = (width - height) / 2; ? ? ? ? ? ? width = height; ? ? ? ? } ? ? ? ? //創(chuàng)建一個(gè)Point數(shù)組存放點(diǎn)的坐標(biāo) ? ? ? ? pointList = new Point[3][3]; ? ? ? ? //設(shè)置索引,好判斷密碼 ? ? ? ? int index=1; ? ? ? ? //遍歷,用算法算出每個(gè)點(diǎn)的坐標(biāo) ? ? ? ? for (int i = 0; i < pointList.length; i++) { ? ? ? ? ? ? for (int j = 0; j < pointList[i].length; j++) { ? ? ? ? ? ? ? ? pointList[i][j] = new Point(offsetX + width / 4 * (i + 1), offsetY + height / 4 * (j + 1)); ? ? ? ? ? ? ? ? pointList[i][j].setIndex(index); ? ? ? ? ? ? ? ? index++; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? //設(shè)置3個(gè)bitmap,分別是默認(rèn)狀態(tài)的,選中狀態(tài)的,錯(cuò)誤狀態(tài)的 ? ? ? ? map1 = BitmapFactory.decodeResource(getResources(), R.drawable.aa); ? ? ? ? map2 = BitmapFactory.decodeResource(getResources(), R.drawable.bb); ? ? ? ? map3 = BitmapFactory.decodeResource(getResources(), R.drawable.cc); ? ? ? ? //獲得圓的半徑 ? ? ? ? r = map1.getWidth() / 2; ? ? } ? ? ? public void setOnLockedChangedListener(OnLockedChangedListener onLocked){ ? ? ? ? this.onLocked=onLocked; ? ? } ? ? ? //設(shè)置回調(diào)接口 ? ? public interface OnLockedChangedListener{ ? ? ? ? public int onPassword(String password); ? ? ? ? public void onResult(String result); ? ? } }
activity代碼:
public class LockedActivity extends Activity { ? ? ? private LockedView lockedView; ? ? private TextView textView; ? ? private SharedPreferences preferences; ? ? private String pass; ? ? @Override ? ? protected void onCreate(Bundle savedInstanceState) { ? ? ? ? super.onCreate(savedInstanceState); ? ? ? ? setContentView(R.layout.activity_locked); ? ? ? ? //初始化控件 ? ? ? ? lockedView= (LockedView) findViewById(R.id.lockedView); ? ? ? ? textView= (TextView) findViewById(R.id.textView); ? ? ? ? //獲得shared ? ? ? ? preferences=getSharedPreferences("Locked",MODE_PRIVATE); ? ? ? ? //根據(jù)存儲(chǔ)在shared里的鍵獲得密碼值 ? ? ? ? pass=preferences.getString("password",""); ? ? ? ? //如果沒(méi)有代表第一次啟動(dòng)activity,則textview設(shè)置文本為情設(shè)置密碼,如果不是第一次啟動(dòng),則設(shè)置文本為請(qǐng)解鎖 ? ? ? ? if(pass.equals("")){ ? ? ? ? ? ? textView.setText("請(qǐng)?jiān)O(shè)置密碼"); ? ? ? ? }else{ ? ? ? ? ? ? textView.setText("請(qǐng)解鎖"); ? ? ? ? } ? ? ? ? lockedView.setOnLockedChangedListener(new LockedView.OnLockedChangedListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public int onPassword(String password) { ? ? ? ? ? ? ? ? //從shared里取值 ? ? ? ? ? ? ? ? pass=preferences.getString("password",""); ? ? ? ? ? ? ? ? //如果值為空,則把接口返回的password存入shared里 ? ? ? ? ? ? ? ? if(pass.equals("")){ ? ? ? ? ? ? ? ? ? ? SharedPreferences.Editor editor=preferences.edit(); ? ? ? ? ? ? ? ? ? ? editor.putString("password",password); ? ? ? ? ? ? ? ? ? ? editor.commit(); ? ? ? ? ? ? ? ? ? ? textView.setText("請(qǐng)解鎖"); ? ? ? ? ? ? ? ? ? ? return 0; ? ? ? ? ? ? ? ? }else if(pass.equals(password)){ ? ? ? ? ? ? ? ? ? ? //如果匹配了密碼,則返回?cái)?shù)字1代表解鎖成功 ? ? ? ? ? ? ? ? ? ? return 1; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? //如果不匹配密碼返回2 ? ? ? ? ? ? ? ? return 2; ? ? ? ? ? ? } ? ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onResult(String result) { ? ? ? ? ? ? ? ? //根據(jù)密碼匹配情況再?gòu)慕涌讷@得要toast的數(shù)據(jù) ? ? ? ? ? ? ? ? Toast.makeText(LockedActivity.this,result,Toast.LENGTH_SHORT).show(); ? ? ? ? ? ? ? ? //數(shù)據(jù)是解鎖成功,則跳轉(zhuǎn)activity ? ? ? ? ? ? ? ? if(result.equals("解鎖成功")){ ? ? ? ? ? ? ? ? ? ? Intent intent=new Intent(LockedActivity.this,MainActivity.class); ? ? ? ? ? ? ? ? ? ? startActivity(intent); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }); ? ? } }
布局代碼如下:
<?xml version="1.0" encoding="utf-8"?> <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"> ? ? ? <com.example.chaohengdai.test922.LockedView ? ? ? ? android:id="@+id/lockedView" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="match_parent" /> ? ? <TextView ? ? ? ? android:id="@+id/textView" ? ? ? ? android:textSize="20sp" ? ? ? ? android:layout_centerHorizontal="true" ? ? ? ? android:layout_marginTop="50dp" ? ? ? ? android:layout_width="wrap_content" ? ? ? ? android:layout_height="wrap_content" /> </RelativeLayout>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義View九宮格手勢(shì)密碼解鎖
- Android實(shí)現(xiàn)九宮格手勢(shì)解鎖
- Android實(shí)現(xiàn)九宮格解鎖的實(shí)例代碼
- Android自定義控件實(shí)現(xiàn)九宮格解鎖功能
- Android 仿小米鎖屏實(shí)現(xiàn)九宮格解鎖功能(無(wú)需圖片資源)
- 輕松實(shí)現(xiàn)Android自定義九宮格圖案解鎖
- 輕松實(shí)現(xiàn)安卓(Android)九宮格解鎖
- Android實(shí)現(xiàn)九宮格解鎖
- 使用Android自定義控件實(shí)現(xiàn)滑動(dòng)解鎖九宮格
- android 九宮格滑動(dòng)解鎖開(kāi)機(jī)實(shí)例源碼學(xué)習(xí)
相關(guān)文章
Android實(shí)現(xiàn)類似360,QQ管家那樣的懸浮窗
用到的就是WindowManager以及WindowManager.LayoutParams,對(duì)這個(gè)LayoutParams做文章,當(dāng)設(shè)置為屬性后,然后,創(chuàng)建一個(gè)View,將這個(gè)View添加到WindowManager中就行2013-06-06Flutter系統(tǒng)網(wǎng)絡(luò)圖片加載流程解析
這篇文章主要介紹了Flutter系統(tǒng)網(wǎng)絡(luò)圖片加載流程,從構(gòu)造函數(shù)開(kāi)始說(shuō)起,我們以最簡(jiǎn)單的調(diào)用方式舉例,當(dāng)我們使用Image.network(imageUrl)這種方式來(lái)顯示圖片時(shí),Image組件內(nèi)部image屬性就會(huì)被賦值NetworkImage,具體操作步驟跟隨小編一起看看吧2022-05-05Android實(shí)現(xiàn)EditText添加下劃線
這篇文章主要為大家詳細(xì)介紹了Android如何實(shí)現(xiàn)給EditText添加下劃線,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08SurfaceView實(shí)現(xiàn)紅包雨平移動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了SurfaceView實(shí)現(xiàn)紅包雨平移動(dòng)畫(huà),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Android編程中Handler原理及用法實(shí)例分析
這篇文章主要介紹了Android編程中Handler用法,結(jié)合實(shí)例形式分析了Handler的功能,原理及使用技巧,需要的朋友可以參考下2016-01-01非常實(shí)用的小功能 Android應(yīng)用版本的更新實(shí)例
這篇文章主要為大家詳細(xì)介紹了一個(gè)非常實(shí)用的小功能,Android應(yīng)用版本的更新實(shí)例,感興趣的小伙伴們可以參考一下2016-08-08