Android游戲開(kāi)發(fā) 自定義手勢(shì)--輸入法手勢(shì)技術(shù)
進(jìn)行軟件開(kāi)發(fā)時(shí),通常我們都喜歡使用較新版本的工具,但這里我為什么使用低版本的SDK來(lái)開(kāi)發(fā)Android游戲呢?這里介紹下原因:
1、Android SDK 屬于向下兼容!那么低版本可以運(yùn)行的,高版本基本上更是沒(méi)問(wèn)題?。ó?dāng)然每次SDK的更新也會(huì)帶來(lái)新功能,或者修改了一些原來(lái)的BUG等等,那么其實(shí)對(duì)于游戲開(kāi)發(fā)來(lái)說(shuō),如果你的游戲中不需要更高的SDK版本的支持情況下,完全不必去追求最新的SDK?。?/p>
2、使用低版本進(jìn)行游戲開(kāi)發(fā)這樣能兼顧更多的機(jī)型,獲取更多的用戶!
3、大家都知道Android SDK 每次版本的更新,底層代碼也會(huì)更健壯和優(yōu)化了!比如我們公司的網(wǎng)游Android版在G2(SDK1.5)上跑起來(lái)稍微有些卡,而在我的手機(jī)上(SDK2.2)運(yùn)行起來(lái)流暢的沒(méi)說(shuō)的~各種舒坦~~但是這樣也會(huì)帶來(lái)一些弊端,比如我們自己游戲如果上來(lái)就用高版本SDK進(jìn)行開(kāi)發(fā),那么對(duì)于性能、內(nèi)存上到底如何,我們都不會(huì)很容易的看出其效果,如果我們用低版本的SDK則會(huì)讓我們明顯的感受到性能到底如何~你想想如果你的游戲在1.5 ,1.6上跑起來(lái)很流暢,那放在更高版本的SDK機(jī)器上更是沒(méi)說(shuō)的啦~
總結(jié):游戲開(kāi)發(fā)中,如果你游戲不需要更高的API的支持,那么推薦基于SDK 1.5和1.6來(lái)開(kāi)發(fā)!
在上一篇中我給大家介紹了觸摸屏手勢(shì)操作,但是這種觸屏手勢(shì)的操作比較有局限性;比如我們都知道Android可以利用手勢(shì)來(lái)解鎖,類似九宮格形式的,通過(guò)自定義的一個(gè)單筆畫(huà)手勢(shì)可以解開(kāi)屏幕鎖,還可以自定義筆畫(huà)手勢(shì)來(lái)啟動(dòng)一個(gè)應(yīng)用等,那么這種所謂的筆畫(huà)手勢(shì)其實(shí)就是今天我要給大家講解的輸入法手勢(shì)識(shí)別技術(shù)!這種手勢(shì)是我們可以自己來(lái)自定義,而不像之前的觸屏手勢(shì)操作只是利用Android 對(duì)一些觸屏動(dòng)作的封裝罷了。下面上幾張手機(jī)自定義筆劃手勢(shì)解鎖的的截圖:
OK,那么既然利用手勢(shì)既然能進(jìn)行解鎖等操作,那么我們游戲開(kāi)發(fā)中,更是可以加入這一亮點(diǎn)了,比如在游戲中我畫(huà)個(gè)圓形執(zhí)行換背景操作,畫(huà)個(gè)X表示退出游戲等等,等等、哈哈 是不是感覺(jué)很有意思了?好的,下面就開(kāi)始進(jìn)入講解!
首先本篇主要學(xué)習(xí)兩點(diǎn):
1、如何創(chuàng)建輸入法手勢(shì)、刪除輸入法手勢(shì)、從SD卡中讀取出手勢(shì)文件!
2、當(dāng)輸入法手勢(shì)創(chuàng)建后,如何來(lái)匹配出我們的自定義手勢(shì)!
下面我們來(lái)熟習(xí)兩個(gè)類和幾個(gè)概念:
1、什么是 GestureOverlayView ? 簡(jiǎn)單點(diǎn)說(shuō)其實(shí)就是一個(gè)手寫(xiě)繪圖區(qū);
2、什么是 GestureLibrary ? 這個(gè)類是對(duì)手勢(shì)進(jìn)行保存、刪除等操作的,一個(gè)存放手勢(shì)的小倉(cāng)庫(kù)!
3、筆劃是什么,字體筆畫(huà)? 是的,其實(shí)就是跟我們寫(xiě)字的筆劃一個(gè)概念!
4、什么是筆劃類型? 輸入法手勢(shì)操作中,筆劃類型有兩種;一種是:?jiǎn)我还P劃,另外一種是:多筆劃
所謂單一筆劃筆劃就是一筆劃畫(huà)出一個(gè)手勢(shì),從你手指接觸屏幕開(kāi)始到你離開(kāi)屏幕筆畫(huà)就會(huì)立刻形成一個(gè)手勢(shì)!一氣呵成!
而多筆劃則是可以在一定緊湊時(shí)間內(nèi)隨意幾筆劃都可,然后超過(guò)這個(gè)緊湊時(shí)間后便會(huì)形成一個(gè)手勢(shì)!
先出項(xiàng)目截圖,簡(jiǎn)單說(shuō)下其功能和操作:
圖1界面中分為3塊,從上到下依次是:TextView ,EditText,SurfaceView;然后在SurfaceView后面還有一個(gè)覆蓋全屏的GestureOverlayView!
圖2界面是在創(chuàng)建好的手勢(shì)中匹配手勢(shì)的界面,這里很清晰看出來(lái),找的很對(duì) ~嘿嘿~
先看下main.xml:
XML/HTML代碼
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/himi_tv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textSize="15sp" android:textColor="#FFFFFF00" /> <EditText android:id="@+id/himi_edit" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1"> <com.himi.MySurfaceView android:id="@+id/view3d" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <android.gesture.GestureOverlayView android:id="@+id/himi_gesture" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0"/> </RelativeLayout> </LinearLayout>
xml中注冊(cè)的有我們自定義的surfaceview,對(duì)此不太熟悉可以去看下Android游戲開(kāi)發(fā)6,不多解釋了。關(guān)于GestureOverlayView這里也只是簡(jiǎn)單的定義了寬高,還有一些重要的屬性設(shè)置在代碼中設(shè)置了,當(dāng)然xml也可以設(shè)置的。
下面看MainActivity.java:
Java代碼
/** *@author Himi *@輸入法手勢(shì)識(shí)別 *@注意: android.gesture這個(gè)類在api-4(SDK1.6)才開(kāi)始支持的! *@提醒:默認(rèn)存到SD卡中,所以別忘記在AndroidMainfest.xml加上SD卡讀寫(xiě)權(quán)限! */ public class MainActivity extends Activity { private GestureOverlayView gov;// 創(chuàng)建一個(gè)手寫(xiě)繪圖區(qū) private Gesture gesture;// 手寫(xiě)實(shí)例 private GestureLibrary gestureLib;//創(chuàng)建一個(gè)手勢(shì)倉(cāng)庫(kù) private TextView tv; private EditText et; private String path;//手勢(shì)文件路徑 private File file;// @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.himi_tv); et = (EditText) findViewById(R.id.himi_edit); gov = (GestureOverlayView) findViewById(R.id.himi_gesture); gov.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);//設(shè)置筆劃類型 // GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE 設(shè)置支持多筆劃 // GestureOverlayView.GESTURE_STROKE_TYPE_SINGLE 僅支持單一筆劃 path = new File(Environment.getExternalStorageDirectory(), "gestures").getAbsolutePath(); //得到默認(rèn)路徑和文件名/sdcard/gestures file = new File(path);//實(shí)例gestures的文件對(duì)象 gestureLib = GestureLibraries.fromFile(path);//實(shí)例手勢(shì)倉(cāng)庫(kù) gov.addOnGestureListener(new OnGestureListener() { // 這里是綁定手寫(xiě)繪圖區(qū) @Override // 以下方法是你剛開(kāi)始畫(huà)手勢(shì)的時(shí)候觸發(fā) public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) { tv.setText("請(qǐng)您在緊湊的時(shí)間內(nèi)用兩筆劃來(lái)完成一個(gè)手勢(shì)!西西~"); } @Override // 以下方法是當(dāng)手勢(shì)完整形成的時(shí)候觸發(fā) public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) { gesture = overlay.getGesture();// 從繪圖區(qū)取出形成的手勢(shì) if (gesture.getStrokesCount() == 2) {//我判定當(dāng)用戶用了兩筆劃 //(強(qiáng)調(diào):如果一開(kāi)始設(shè)置手勢(shì)筆畫(huà)類型是單一筆畫(huà),那你這里始終得到的只是1!) if (event.getAction() == MotionEvent.ACTION_UP) {//判定第兩筆劃離開(kāi)屏幕 //if(gesture.getLength()==100){}//這里是判定長(zhǎng)度達(dá)到100像素 if (et.getText().toString().equals("")) { tv.setText("由于您沒(méi)有輸入手勢(shì)名稱,so~保存失敗啦~"); } else { tv.setText("正在保存手勢(shì)..."); addGesture(et.getText().toString(), gesture);//我自己寫(xiě)的添加手勢(shì)函數(shù) } } } else { tv.setText("請(qǐng)您在緊湊的時(shí)間內(nèi)用兩筆劃來(lái)完成一個(gè)手勢(shì)!西西~"); } } @Override public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) { } @Override public void onGesture(GestureOverlayView overlay, MotionEvent event) { } }); //----這里是在程序啟動(dòng)的時(shí)候進(jìn)行遍歷所有手勢(shì)!------ if (!gestureLib.load()) { tv.setText("Himi提示:手勢(shì)超過(guò)9個(gè)我做了刪除所有手勢(shì)的操作,為了界面整潔一些!" + " 輸入法手勢(shì)練習(xí)~(*^__^*)~ 嘻嘻!/n操作介紹:(畫(huà)手勢(shì)我設(shè)置必須畫(huà)兩筆劃才行哦~)/n1." + "添加手勢(shì):先EditText中輸入名稱,然后在屏幕上畫(huà)出手勢(shì)!/n2.匹配手勢(shì):" + "在EditText輸入/"himi/",然后輸入手勢(shì)即可! "); } else { Set<String> set = gestureLib.getGestureEntries();//取出所有手勢(shì) Object ob[] = set.toArray(); loadAllGesture(set, ob); } } }
這個(gè)就是MainActivity主要代碼了,其中添加手勢(shì)、匹配手勢(shì)、遍歷手勢(shì)、將手勢(shì)轉(zhuǎn)成圖片這些我都單獨(dú)寫(xiě)成了函數(shù),這樣讓各位童鞋更清晰思路一些。
從以上代碼中我們看出在創(chuàng)建手勢(shì)之前,手寫(xiě)繪圖區(qū)(GestureOverlayView)肯定先被創(chuàng)建出來(lái),然后我們就可以在其區(qū)域中進(jìn)行筆劃繪畫(huà)手勢(shì)了,當(dāng)然繪畫(huà)手勢(shì)前,我們也需要設(shè)置了筆劃類型,也就是我一開(kāi)始給大家介紹的,其后最重要的就是手寫(xiě)繪圖區(qū)的手勢(shì)監(jiān)聽(tīng)器綁定,增加OnGestureListener這個(gè)監(jiān)聽(tīng)器重寫(xiě)了四個(gè)函數(shù),這里最重要的就兩個(gè)函數(shù):
onGestureStarted 和 onGestureEnded :手勢(shì)開(kāi)始和手勢(shì)結(jié)束的監(jiān)聽(tīng)函數(shù)。
尤其是手勢(shì)結(jié)束監(jiān)聽(tīng)這個(gè)函數(shù)尤為重要,在其中我設(shè)置好幾個(gè)條件語(yǔ)句,這么幾個(gè)條件一方面是讓大家了解Gesture中一些比較重要常用的方法,另一方面我要提醒各位童鞋:
如果你設(shè)置筆劃類型是多筆劃類型的,那么理想狀態(tài)下,應(yīng)該是在一段緊湊時(shí)間內(nèi),不管你使用了幾筆劃來(lái)繪制手勢(shì),系統(tǒng)都應(yīng)該在判定你在一定短暫時(shí)間內(nèi)沒(méi)有再進(jìn)行筆劃的時(shí)候才應(yīng)該創(chuàng)建手勢(shì),并且系統(tǒng)響應(yīng)此函數(shù);
其實(shí)錯(cuò)了,一開(kāi)始我也這么想,但是發(fā)現(xiàn),不管你設(shè)置的筆劃類型是單一的還是多筆劃當(dāng)你手指離開(kāi)屏幕,不管你當(dāng)前是第幾筆,Android都會(huì)去響應(yīng)這個(gè)完成函數(shù),so~ 我在這里調(diào)用手勢(shì)Gesture類中的getStrokesCount()函數(shù),這個(gè)函數(shù)會(huì)記錄在緊湊時(shí)間內(nèi)你繪制手勢(shì)的筆劃數(shù),那么根據(jù)這個(gè)函數(shù)我們就可以解決手指離開(kāi)屏幕總被響應(yīng)的問(wèn)題了,因?yàn)閱我还P劃類型永遠(yuǎn)這個(gè)值不會(huì)大于1!
而 if (event.getAction() == MotionEvent.ACTION_UP) {}寫(xiě)這個(gè)只是給大家演示第二個(gè)參數(shù)按鍵動(dòng)作該怎么用。
那么我們下面就來(lái)看如何創(chuàng)建一個(gè)手勢(shì):
Java代碼
public void addMyGesture(String name, Gesture gesture) { try { if (name.equals("himi")) { findGesture(gesture); } else { // 關(guān)于兩種方式創(chuàng)建模擬器的SDcard在【Android2D游戲開(kāi)發(fā)之十】有詳解 if (Environment.getExternalStorageState() != null) {// 這個(gè)方法在試探終端是否有sdcard! if (!file.exists()) {// 判定是否已經(jīng)存在手勢(shì)文件 // 不存在文件的時(shí)候我們?nèi)ブ苯影盐覀兊氖謩?shì)文件存入 gestureLib.addGesture(name, gesture); if (gestureLib.save()) {////保存到文件中 gov.clear(true);//清除筆畫(huà) // 注意保存的路徑默認(rèn)是/sdcard/gesture ,so~別忘記AndroidMainfest.xml加上讀寫(xiě)權(quán)限! // 這里抱怨一下,咳咳、其實(shí)昨天就應(yīng)該出這篇博文的,就是因?yàn)檫@里總是異常,今天仔細(xì)看了 // 才發(fā)現(xiàn)不是沒(méi)寫(xiě)權(quán)限,而是我雖然在AndroidMainfest.xml中寫(xiě)了權(quán)限,但是寫(xiě)錯(cuò)了位置..哭死! tv.setText("保存手勢(shì)成功!因?yàn)椴淮嬖谑謩?shì)文件," + "所以第一次保存手勢(shì)成功會(huì)默認(rèn)先創(chuàng)" + "建了一個(gè)手勢(shì)文件!然后將手勢(shì)保存到文件中."); et.setText(""); gestureToImage(gesture); } else { tv.setText("保存手勢(shì)失?。?); } } else {//當(dāng)存在此文件的時(shí)候我們需要先刪除此手勢(shì)然后把新的手勢(shì)放上 //讀取已經(jīng)存在的文件,得到文件中的所有手勢(shì) if (!gestureLib.load()) {//如果讀取失敗 tv.setText("手勢(shì)文件讀取失??!"); } else {//讀取成功 Set<String> set = gestureLib.getGestureEntries();//取出所有手勢(shì) Object ob[] = set.toArray(); boolean isHavedGesture = false; for (int i = 0; i < ob.length; i++) {//這里是遍歷所有手勢(shì)的name if (((String) ob[i]).equals(name)) {//和我們新添的手勢(shì)name做對(duì)比 isHavedGesture = true; } } if (isHavedGesture) {//如果此變量為true說(shuō)明有相同name的手勢(shì) //----備注1-------------------//gestureLib.removeGesture(name, gesture);//刪除與當(dāng)前名字相同的手勢(shì) /*----備注2-----------------*/gestureLib.removeEntry(name); gestureLib.addGesture(name, gesture); } else { gestureLib.addGesture(name, gesture); } if (gestureLib.save()) { gov.clear(true);//清除筆畫(huà) gestureToImage(gesture); tv.setText("保存手勢(shì)成功!當(dāng)前所有手勢(shì)一共有:" + ob.length + "個(gè)"); et.setText(""); } else { tv.setText("保存手勢(shì)失??!"); } ////------- --以下代碼是當(dāng)手勢(shì)超過(guò)9個(gè)就全部清空 操作-------- if (ob.length > 9) { for (int i = 0; i < ob.length; i++) {//這里是遍歷刪除手勢(shì) gestureLib.removeEntry((String) ob[i]); } gestureLib.save(); if (MySurfaceView.vec_bmp != null) { MySurfaceView.vec_bmp.removeAllElements();//刪除放置手勢(shì)圖的容器 } tv.setText("手勢(shì)超過(guò)9個(gè),已全部清空!"); et.setText(""); } ob = null; set = null; } } } else { tv.setText("當(dāng)前模擬器沒(méi)有SD卡 - -。"); } } } catch (Exception e) { tv.setText("操作異常!"); } }
這里也都很好理解,套路類似之前File文件存儲(chǔ)的套路,先判斷SD是否存在,然后是文件是否存在:
如果文件不存在就先直接添加到手勢(shì)到手勢(shì)倉(cāng)庫(kù)中,然后手勢(shì)倉(cāng)調(diào)用gestureLib.save()才算把手勢(shì)存到SD卡的手勢(shì)文件中。
文件存在的話還要去判定是否文件中包含了相同名字的手勢(shì);當(dāng)然這里可以不判定是否有相同手勢(shì)名存在,然后進(jìn)行刪除操作!其實(shí)也可不刪除,直接添加進(jìn)去當(dāng)前新建的手勢(shì);原因看了下面的備注解釋就明白了;
備注1:因?yàn)間estureLib保存的手勢(shì)是個(gè)HashMap, key=手勢(shì)的名字,value=手勢(shì),所以gestureLib.removeGesture(name, gesture);這種刪除方式只是刪除了手勢(shì),該手勢(shì)名字依舊保存在hashmap中,下次還有相同的name手勢(shì)存入的時(shí)候Hashmap就直接覆蓋本條目了。所以根據(jù)Hashmap的特征,我們可以不進(jìn)行刪除操作,可以直接gestureLib.addGesture(name, gesture);因?yàn)槿绻霈F(xiàn)相同的手勢(shì)名字的手勢(shì),Hashmap就會(huì)根據(jù)key(手勢(shì)的名字)直接覆蓋其條目的value(手勢(shì))滴~
備注2:這里也是一種刪除手勢(shì)的方式,但是這種方式跟備注1的不同,這里是將Hashmap中的條目刪除,也就是說(shuō)key和value都被刪去!
下面看下如何把手勢(shì)轉(zhuǎn)成bitmap:
Java代碼
public void gestureToImage(Gesture ges) {//將手勢(shì)轉(zhuǎn)換成Bitmap //把手勢(shì)轉(zhuǎn)成圖片,存到我們SurfaceView中定義的Image容器中,然后都畫(huà)出來(lái)~ if (MySurfaceView.vec_bmp != null) { MySurfaceView.vec_bmp.addElement(ges.toBitmap(100, 100, 12, Color.GREEN)); } }
下面是如何遍歷手勢(shì):
Java代碼
public void loadAllGesture(Set<String> set, Object ob[]) { //遍歷所有的手勢(shì) if (gestureLib.load()) {//讀取最新的手勢(shì)文件 set = gestureLib.getGestureEntries();//取出所有手勢(shì) ob = set.toArray(); for (int i = 0; i < ob.length; i++) { //把手勢(shì)轉(zhuǎn)成Bitmap gestureToImage(gestureLib.getGestures((String) ob[i]).get(0)); //這里是把我們每個(gè)手勢(shì)的名字也保存下來(lái) MySurfaceView.vec_string.addElement((String) ob[i]); } } }
下面最后來(lái)看看手勢(shì)的匹配:
Java代碼
public void findGesture(Gesture gesture) { try { // 關(guān)于兩種方式創(chuàng)建模擬器的SDcard在【Android2D游戲開(kāi)發(fā)之十】有詳解 if (Environment.getExternalStorageState() != null) {// 這個(gè)方法在試探終端是否有sdcard! if (!file.exists()) {// 判定是否已經(jīng)存在手勢(shì)文件 tv.setText("匹配手勢(shì)失敗,因?yàn)槭謩?shì)文件不存在??!"); } else {//當(dāng)存在此文件的時(shí)候我們需要先刪除此手勢(shì)然后把新的手勢(shì)放上 //讀取已經(jīng)存在的文件,得到文件中的所有手勢(shì) if (!gestureLib.load()) {//如果讀取失敗 tv.setText("匹配手勢(shì)失敗,手勢(shì)文件讀取失??!"); } else {//讀取成功 List<Prediction> predictions = gestureLib.recognize(gesture); //recognize()的返回結(jié)果是一個(gè)prediction集合, //包含了所有與gesture相匹配的結(jié)果。 //從手勢(shì)庫(kù)中查詢匹配的內(nèi)容,匹配的結(jié)果可能包括多個(gè)相似的結(jié)果, if (!predictions.isEmpty()) { Prediction prediction = predictions.get(0); //prediction的score屬性代表了與手勢(shì)的相似程度 //prediction的name代表手勢(shì)對(duì)應(yīng)的名稱 //prediction的score屬性代表了與gesture得相似程度(通常情況下不考慮score小于1的結(jié)果)。 if (prediction.score >= 1) { tv.setText("當(dāng)前你的手勢(shì)在手勢(shì)庫(kù)中找到最相似的手勢(shì):name =" + prediction.name); } } } } } else { tv.setText("匹配手勢(shì)失敗,,當(dāng)前模擬器沒(méi)有SD卡 - -。"); } } catch (Exception e) { e.printStackTrace(); tv.setText("由于出現(xiàn)異常,匹配手勢(shì)失敗啦~"); } }
那么最后給各位童鞋說(shuō)一下,其實(shí)輸入法手勢(shì)操作很是適合游戲中使用,不管是觸摸屏手勢(shì)操作還是今天講的輸入法手勢(shì)操作如果加到游戲中那都是相當(dāng)贊的!
以上就是對(duì)Android 自定義手勢(shì)的實(shí)現(xiàn)示例,后續(xù)繼續(xù)整理相關(guān)資料,謝謝大家對(duì)本站的支持!
- Android自定義View接收輸入法輸入的內(nèi)容
- Android 自定義手勢(shì)--輸入法手勢(shì)技術(shù)
- Android 顯示和隱藏輸入法實(shí)現(xiàn)代碼
- Android程序打開(kāi)和對(duì)輸入法的操作(打開(kāi)/關(guān)閉)
- Android中Activity啟動(dòng)默認(rèn)不顯示輸入法解決方法
- Android的文本和輸入之創(chuàng)建輸入法教程
- Android輸入法彈出時(shí)覆蓋輸入框問(wèn)題的解決方法
- Android中系統(tǒng)默認(rèn)輸入法設(shè)置的方法(輸入法的顯示和隱藏)
- Android監(jiān)聽(tīng)輸入法彈窗和關(guān)閉的實(shí)現(xiàn)方法
- 讓Android中RadioGroup不顯示在輸入法上面的辦法
- Android中EditText屏蔽第三方輸入法表情的方法示例
- Android編程實(shí)現(xiàn)自定義輸入法功能示例【輸入密碼時(shí)防止第三方竊取】
相關(guān)文章
自定義toast外形,多次點(diǎn)擊不會(huì)總是彈出toast的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇自定義toast外形,多次點(diǎn)擊不會(huì)總是彈出toast的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04詳解android使用ItemDecoration 懸浮導(dǎo)航欄效果
本篇文章主要介紹了Android 最流行的吸頂效果的實(shí)現(xiàn)及代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2017-01-01Kotlin Select協(xié)程多路復(fù)用的實(shí)現(xiàn)詳解
select是Kotlin 1.6中的特性,即選擇最快的結(jié)果。select與async、Channel結(jié)合使用,可以大大提高程序的響應(yīng)速度,還可以提高程序的靈活性、擴(kuò)展性2022-09-09Android studio實(shí)現(xiàn)簡(jiǎn)易計(jì)算器App功能
這篇文章主要為大家詳細(xì)介紹了Android studio實(shí)現(xiàn)簡(jiǎn)易計(jì)算器App功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05關(guān)于AndroidStudio R文件莫名其妙缺失的快速解決方法
下面小編就為大家?guī)?lái)一篇關(guān)于AndroidStudio R文件莫名其妙缺失的快速解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-035分鐘學(xué)會(huì)Android設(shè)計(jì)模式之策略模式Strategy Pattern教程
這篇文章主要為大家介紹了5分鐘學(xué)會(huì)Android設(shè)計(jì)模式之策略模式Strategy Pattern教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Android Camera是否支持變焦的判斷方法總結(jié)
這篇文章主要介紹了Android Camera是否支持變焦的判斷方法總結(jié),本文總結(jié)了調(diào)節(jié)攝像頭焦距編程中遇到的一些問(wèn)題和解決方法,需要的朋友可以參考下2015-04-04