




已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀
版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
2D動態(tài)壁紙我之前已經(jīng)詳細分析過了,關于項目成果也放出來了,從這一篇文章開始我們自己動手寫出這樣的一個2D動態(tài)壁紙即項目演練二 開發(fā)2D動態(tài)壁紙DiceWallPaper。 之所以強調(diào)這是一個2D壁紙,這是區(qū)別于我接下來要介紹的一個3D動態(tài)壁紙開發(fā)項目。DiceWallPaper組織框架代碼組織框架 界面用戶配置頁面 壁紙Service程序 該Service程序分析詳見:Android動態(tài)壁紙分析DiceWallPaper主要包和類 包名:org.ourunix.android.dicewallpaper 主要類: DiceService.java 壁紙主要的服務程序; DiceSettings.java 壁紙用戶配置頁面; Constants.java及Utils.java是常量及工具類。開發(fā)難點及重點 1、壁紙程序動態(tài)改變 壁紙程序需要動態(tài)改變,使用線程來主動更新前臺界面。 2、用戶配置界面 壁紙程序可以提供用戶自選配置,壁紙程序需要監(jiān)聽配置改變并做響應的顯示。 3、多功能 多功能是指DiceWallPaper程序?qū)诤下曇?、震動等Android特色開發(fā)。壁紙的Service框架在Android動態(tài)壁紙分析已經(jīng)詳細的介紹過了,DiceWallPaper就來示例這個WallpaperService框架,真正做到學以致用,理論與實踐結合。WallpaperService框架 DiceWallPaper繼承自WallpaperService,我們不必要去一一實現(xiàn)這個Service里面所有方法,但是至少要實現(xiàn)onCreateEngine方法,這個方法是支撐整個壁紙運轉(zhuǎn)的核心,當然你也可以一一實現(xiàn)諸如onCreate、onDestroy等方法,可以做些初始化和銷毀的代碼。 DiceWallPaper只實現(xiàn)了onCreateEngine方法,代碼如下:Java代碼1. publicclassDiceServiceextendsWallpaperService2. 3. Override4. publicvoidonCreate()5. /TODOAuto-generatedmethodstub6. super.onCreate();7. 8. 9. Override10. publicEngineonCreateEngine()11. /TODOAuto-generatedmethodstub12. returnnewDiceEngine();13. 14. 15. Override16. publicvoidonDestroy()17. /TODOAuto-generatedmethodstub18. super.onDestroy();19. 20. 在onCreateEngine方法中,我們返回的是一個自己寫的DiceEngine實例,所以我們看到了我們將來所有的代碼都是圍繞DiceEngine類。壁紙引擎DiceEngine 在DiceEngine中,我們需要像在Android動態(tài)壁紙分析分析的一樣,重寫一些重要的方法。 這些方法包括:onCreate、onSurfaceCreated、onSurfaceChanged、onVisibilityChanged、onOffsetsChanged、onSurfaceDestroyed、onDestroy,當然我們也不是完全有必須重寫這么多方法,我們的DiceWallPaper程序只需重寫onVisibilityChanged、onOffsetsChanged。所以我們就好好看看這個兩個方法的實現(xiàn)吧。 onVisibilityChanged方法是顯示/不顯示壁紙時調(diào)用的,所以如果不顯示壁紙即壁紙被桌面上其他程序擋住時,我們可以在這個方法中做些讓壁紙休息的程序,然后一旦其他程序移除了壁紙需要立即顯示出來就用此方法再次工作。DiceWallPaper的onVisibilityChanged代碼如下:Java代碼1. Override2. publicvoidonVisibilityChanged(booleanvisible)3. /TODOAuto-generatedmethodstub4. super.onVisibilityChanged(visible);5. if(visible)6. initOthers();7. initBack();8. mHandler.postDelayed(diceThread,50);9. else10. mHandler.removeCallbacks(diceThread);11. picCount=0;12. release();13. 14. 我在壁紙顯示時調(diào)用一個線程去更新壁紙(其實是一個Canvas),壁紙不顯示時移除這個線程并釋放相關資源,需要注意的是我們一般不在線程中更新UI,但是壁紙程序不一樣,我們是在某一個線程中直接更新界面的底層Canvas,這個要區(qū)分好。 我們接著上一次onVisibilityChanged方法來寫更新壁紙的線程,其大致思路是這樣的:在onVisibilityChanged方法中,判斷壁紙是不是顯式的,如果是則啟動線程,隱式的則移除線程,這個我們還得接著是用Looper-Handler機制來控制。 首先定義一個Handler,代碼如下:Java代碼1. privateHandlermHandler=newHandler(getMainLooper(); 初始化時我們用的是主線程的Looper,當然你也可以直接new Handler不帶參數(shù)的。接著再創(chuàng)建一個線程:Java代碼1. privateThreaddiceThread=newThread()2. publicvoidrun()3. draw();4. 5. ; 如果讓線程走就調(diào)用mHandler.postDelayed;移除就使用mHandler.removeCallbacks方法;所以onVisibilityChanged方法代碼如下:Java代碼1. Override2. publicvoidonVisibilityChanged(booleanvisible)3. /TODOAuto-generatedmethodstub4. super.onVisibilityChanged(visible);5. if(visible)6. initOthers();7. initBack();8. mHandler.postDelayed(diceThread,50);9. else10. mHandler.removeCallbacks(diceThread);11. picCount=0;12. release();13. 14. 當然我在這個方法中,還做了一些初始化的代碼即initOthers()和initBack(),另外在移除時還做了一些釋放相關的代碼,這個都不是特別重要的。需要說明的是我使用postDelayed方法主要是延遲線程工作的,因為桌面上的動態(tài)壁紙時刻都有變化,所以我要確保我的線程走完之后需要線程繼續(xù)走下去并去作一些動作變化,所以線程結束之后得繼續(xù)調(diào)用,代碼我們看diceThread 這個線程中的draw方法:Java代碼1. /*2. *所有在屏幕上畫圖的操作都是在這個方法中完成3. */4. publicvoiddraw()5. SurfaceHolderholder=getSurfaceHolder();6. Canvascanvas=holder.lockCanvas();7. canvas.drawBitmap(backBmp,xoffset,0,null);8. if(!sensorUsed)9. canvas.drawBitmap(diceStopLeftBmps,0,210,null);10. canvas.drawBitmap(diceStopRightBmps,0,210,null);11. else12. drawDiceAnim(canvas);13. 14. holder.unlockCanvasAndPost(canvas);15. mHandler.postDelayed(diceThread,50);16. 這個方法就是更新屏幕上的壁紙的,并在最后結束的時候再一次調(diào)用自己這個線程,確保實時刷新。下面我們就來接著講解這個壁紙的描繪過程:首先通過getSurfaceHolder();獲得Surface容器,并拿到底層的canvas畫布,然后鎖定這個畫布就開始畫畫,最后釋放這個畫布。關于畫布上畫畫的具體動作我都寫在drawDiceAnim(canvas)方法,時間不早了,好了,本篇就來重點描述整個壁紙的繪畫過程,在前面的壁紙更新線程中,我們已經(jīng)知道DiceWallPaper壁紙的描述過程是通過一個線程來完成的,diceThread這個線程就是DiceWallPaper壁紙更新的線程。所以本篇的重點就是來講解這個線程。初始化壁紙資源 在講解線程之前,我們是否還記得我們的壁紙程序最核心的東東是那個壁紙程序引擎DiceEngine,我們在返回這個引擎的時候用initDiceRes()方法初始化了整個壁紙程序所需的資源,該方法如下:Java代碼1. /*2. *初始化圖片資源3. */4. publicvoidinitDiceRes()5. /back6. backPic=newintR.drawable.background1,R.drawable.background2;7. initBack();8. 9. /dice10. dicePics=newintR.drawable.dice_roll_01,R.drawable.dice_roll_02,11. R.drawable.dice_roll_03,R.drawable.dice_roll_04,12. R.drawable.dice_roll_05,R.drawable.dice_roll_06,13. R.drawable.dice_roll_07,R.drawable.dice_roll_08,14. R.drawable.dice_roll_09,R.drawable.dice_roll_10,15. R.drawable.dice_roll_11,R.drawable.dice_roll_12,16. R.drawable.dice_roll_13,R.drawable.dice_roll_14,17. R.drawable.dice_roll_15,R.drawable.dice_roll_16,;18. 19. diceBmps=newBitmapdicePics.length;20. 21. for(inti=0,j=dicePics.length;ij;i+)22. diceBmpsi=readBmp(dicePicsi);23. 24. 25. picCount=0;26. 27. 28. /dicestopleft29. diceStopLeftPics=newintR.drawable.dice_left_01,R.drawable.dice_left_02,30. R.drawable.dice_left_03,R.drawable.dice_left_04,31. R.drawable.dice_left_05,R.drawable.dice_left_06,;32. 33. /dicestopright34. diceStopRightPics=newintR.drawable.dice_right_01,R.drawable.dice_right_02,35. R.drawable.dice_right_03,R.drawable.dice_right_04,36. R.drawable.dice_right_05,R.drawable.dice_right_06,;37. 38. initStop();39. 40. SharedPreferenceslocalPrefs1=prefs;41. SharedPreferenceslocalPrefs2=localPrefs1;42. onSharedPreferenceChanged(localPrefs2,null);43. localPrefs2.registerOnSharedPreferenceChangeListener(this);44. 45. voiceSwith=true;46. vibraSwith=true;47. 我在該代碼中主要做了下面幾件事情:1、使用initBack()方法來初始化整個壁紙的大環(huán)境;2、初始化骰子圖片資源,我把骰子圖片分別用左右兩類來歸類其資源id號;3、使用initStop()來初始化骰子轉(zhuǎn)停之后的圖片,這是用來給用戶看的最后一張圖片;4、注冊SharedPreferences ,監(jiān)測用戶對壁紙程序的改變設置;5、打開聲音voiceSwith及骰子轉(zhuǎn)動時震動的開關vibraSwith。初始化可設置資源 可設置資源是指用戶可以通過配置文件來改變的資源,比如壁紙的大圖片,壁紙是否有聲音和骰子是否震動和作弊等等,因為這些配置是可變的,所以我們在在上述第4點注冊SharedPreferences,需要說明的因為這些是隨用戶可變的,所以我就將這些可設置資源放在onVisibilityChanged顯示壁紙中,當然有初始就有釋放,所以onVisibilityChanged隱藏壁紙中。代碼如下:Java代碼1. Override2. publicvoidonVisibilityChanged(booleanvisible)3. /TODOAuto-generatedmethodstub4. super.onVisibilityChanged(visible);5. if(visible)6. initOthers();7. initBack();8. mHandler.postDelayed(diceThread,50);9. else10. mHandler.removeCallbacks(diceThread);11. picCount=0;12. release();13. 14. 因為這是個演示程序,我對代碼的優(yōu)化不是很多,在這邊可以看出代碼執(zhí)行效率并不是特別的高,所以讀者可以通過設置全局靜態(tài)變量的方法來做到提高優(yōu)化執(zhí)行效率,大體的方式是當檢測到用戶設置改變了就改寫這個靜態(tài)變量,當這個監(jiān)測變量有改變時再去讀取,這個讀者可以試試,下面就看看initOthers()、initBack()、release()的代碼吧。initOthers()方法:Java代碼1. /*2. *初始化其他資源3. */4. publicvoidinitOthers()5. mSensorManager=(SensorManager)getSystemService(Service.SENSOR_SERVICE);6. mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);7. startSensor();8. if(voiceSwith)9. initMediaPlayer();10. 11. if(vibraSwith)12. initVibrator();13. 14. 可以看到initOthers()是判斷用戶是否晃動手機、管理播放聲音、管理震動的一個方法。initBack()方法:Java代碼1. /*2. *背景圖片3. */4. publicvoidinitBack()5. if(backBmp!=null)6. if(!backBmp.isRecycled()7. backBmp.recycle();8. 9. 10. backBmp=readBmp(backPicbackNum);11. 這個方法就是直接更換程序壁紙的。release()方法是釋放所有資源的:Java代碼1. /*2. *釋放3. */4. publicvoidrelease()5. stopSensor();6. mMediaPlayer.release();7. mVibrator.cancel();8. 該方法釋放了sensor傳感器、聲音、震動等資源代碼。壁紙的畫布操作 現(xiàn)在還回到diceThread這個線程里面,線程代碼很簡單:Java代碼1. /handler和線程,這個線程主要用來畫圖2. privateHandlermHandler=newHandler(getMainLooper();3. privateThreaddiceThread=newThread()4. publicvoidrun()5. draw();6. 7. ; 所有的壁紙更新配合操作都是在draw()方法中,我們看draw()方法:Java代碼1. /*2. *所有在屏幕上畫圖的操作都是在這個方法中完成3. */4. publicvoiddraw()5. SurfaceHolderholder=getSurfaceHolder();6. Canvascanvas=holder.lockCanvas();7. canvas.drawBitmap(backBmp,xoffset,0,null);8. if(!sensorUsed)9. canvas.drawBitmap(diceStopLeftBmps,0,210,null);10. canvas.drawBitmap(diceStopRightBmps,0,210,null);11. else12. drawDiceAnim(canvas);13. 14. holder.unlockCanvasAndPost(canvas);15. mHandler.postDelayed(diceThread,50);16. 該方法主要做了下面幾件事:1、獲得SurfaceHolder,然后拿到底層的Canvas,然后開始我們的作品“繪畫”;2、繪制底層的背景即大環(huán)境壁紙,這是使用canvas.drawBitmap(backBmp,xoffset,0,null); 方法,這個方法中第一個參數(shù)是我們的可供用戶選擇的壁紙背景,第二個參數(shù)是我們從onOffsetsChanged方法獲取的,這個主要是壁紙移動的一個參數(shù),界面用戶滑動Launcher的時候就會調(diào)用這個方法,xoffset就是滑動變量。3、是骰子停止狀態(tài),這邊主要是用來顯示骰子最后呈現(xiàn)給玩家的一個數(shù)字畫面;4、drawDiceAnim方法是繪制用戶晃動手機,手機壁紙中骰子滾動的畫面;5、釋放canvas并繼續(xù)調(diào)用這個繪制線程diceThread。這樣整個畫面就連在一起了,利用人眼的視覺停留就覺得骰子在一直轉(zhuǎn)動一樣。drawDiceAnim(canvas);代碼如下:Java代碼1. publicvoiddrawDiceAnim(Canvascanvas)2. if(sensorUsed)3. if(picCount+dicePics.length-1)4. canvas.drawBitmap(diceBmpspicCount,0,210,null);5. return;6. else7. canvas.drawBitmap(diceStopLeftBmps,0,210,null);8. canvas.drawBitmap(diceStopRightBmps,0,210,null);9. Log.i(Tag,iLeft:+iLeft+iRight:+iRight);10. picCount=0;11. sensorUsed=false;12. 13. 14. 這個繪制方式是和繪制大背景一樣的,好了本騙文章代碼比較多,下一篇文章預報:講解壁紙程序的配置頁面。 本篇主要介紹DiceWallPaper壁紙程序的配置頁面,一個程序如果有用戶自主配置頁面會給用戶覺得本程序更加專業(yè)的感覺,會給程序加分的,另外再從程序的多功能性來看也是有利的,所以我們?yōu)镈iceWallPaper壁紙程序加上用戶配置頁面。 Android自帶的很多應用程序都是具有配置頁面的,一些大型的軟件也都是具備用戶可控可調(diào)性的,這些都是使用Android中自帶的PreferenceActivity來完成的。關于PreferenceActivity的介紹,彎柚博客中有專門的介紹:用戶配置界面PreferenceActivity的使用,所以這邊不會再去介紹如何使用PreferenceActivity,而是介紹如何為DiceWallPaper壁紙程序設計配置頁面。 效果圖如下:配置選項的考慮 我們?yōu)镈iceWallPaper壁紙程序的配置分為基本設置和高級設置兩組,如下:開始碼代碼 現(xiàn)在開始使用PreferenceActivity,由于我們分了基本設置、高級設置,所以我們需要PreferenceCategory來歸類,其中播放聲音、震動交互、去除廣告及推薦應用是使用的CheckBoxPreference,骰子的背景及骰子作弊是使用的ListPreference。 java代碼方面,繼承自PreferenceActivity的頁面叫做DiceSettings,OnCreate方法代碼如下:Java代碼1. protectedvoidonCreate(BundlesavedInstanceState)2. /TODOAuto-generatedmethodstub3. super.onCreate(savedInstanceState);4. getPreferenceManager().setSharedPreferencesName(wallpaper_setting);5. addPreferencesFromResource(R.xml.preferences);6. prefs=getSharedPreferences(wallpaper_setting,0);7. initPref();8. 9. 其中initPref()方法代碼如下:Java代碼1. publicvoidinitPref()2. voiceCheck=(CheckBoxPreference)findPreference(getString(R.string.preference_voice_key).toString();3. voiceCheck.setChecked(getVoiceSwitch();4. 5. vibraCheck=(CheckBoxPreference)findPreference(getString(R.string.preference_vibrator_key).toString();6. vibraCheck.setChecked(getVibraSwitch();7. 8. backSelect=(ListPreference)findPreference(getString(R.string.preference_background_key);9. backSelect.setValueIndex(getBackSelect();10. 11. /*12. cheatSelect=(ListPreference)findPreference(getString(R.string.preference_cheat_key);13. cheatSelect.setValueIndex(getCheatSelect();14. 15. adCheck=(CheckBoxPreference)findPreference(getString(R.string.preference_ad_key);16. adCheck.setChecked(getAdCheck();17. 18. adPref=(CheckBoxPreference)findPreference(getString(R.string.preference_setting_more_check_key).toString();19. adPref.setChecked(getAdSwitch();20. 21. adPref.setOnPreferenceClickListener(newOnPreferenceClickListener()22. 23. Override24. publicbooleanonPreferenceClick(Preferencepreference)25. /TODOAuto-generatedmethodstub26. AppConnect.getInstance(mContext).getPoints(newUpdatePointsNotifier()27. 28. Override29. publicvoidgetUpdatePointsFailed(Stringarg0)30. /TODOAuto-generatedmethodstub31. 32. 33. Override34. publicvoidgetUpdatePoints(Stringarg0,intarg1)35. /TODOAuto-generatedmethodstub36. Log.i(xxxxxxxxxxxxxx,arg0:+arg0+arg1:+arg1);37. money=arg1;38. 39. );40. adFlag=prefs.getBoolean(adflag,false);41. if(adFlag)42. startMoreSetting();43. else44. adPref.setChecked(false);45. showAdDialog(money);46. 47. /顯示推薦應用列表(Offer).48. AppConnect.getInstance(mContext).showOffers(mContext);49. returntrue;50. 51. );52. 這里主要是初始化了整個配置界面的起始環(huán)境,這邊初始化之后,我們在還回到壁紙主程序DiceService類中,在該類中的我們自己寫的Engine中實現(xiàn)了OnSharedPreferenceChangeListener接口,該接口就是會監(jiān)-聽配置文件的改變情況:XML/HTML代碼1. /*2. *配置文件改變時調(diào)用3. */4. 5. Override6. publicvoidonSharedPreferenceChanged(7. SharedPreferencessharedPreferences,Stringkey)8. /TODOAuto-generatedmethodstub9. voiceSwith=sharedPreferences.getBoolean(getString(R.string.preference_voice_key).toString(),true);10. vibraSwith=sharedPreferences.getBoolean(getString(R.string.preference_vibrator_key).toString(),true);11. 12. Stringtemp=prefs.getString(mContext.getString(R.string.preference_background_key).toString(),Constants.backgroud_select_01);13. if(temp.equals(Constants.backgroud_select_01)14. backNum=0;15. elseif(temp.equals(Constants.backgroud_select_02)16. backNum=1;17. 18. 19. StringtempCheat=prefs.getString(mContext.getString(R.string.preference_cheat_key).toString(),Constants.cheat_select_00);20. if(tempCheat.equals(Constants.cheat_select_00)21. cheatFlag=0;22. elseif(tempCheat.equals(Constants.cheat_select_01)23. cheatFlag=1;24. elseif(tempCheat.equals(Constants.cheat_select_02)25. cheatFlag=2;26. elseif(tempCheat.equals(Constants.cheat_select_03)27. cheatFlag=3;28. elseif(tempCheat.equals(Constants.cheat_select_04)29. cheatFlag=4;30. elseif(tempCheat.equals(Constants.cheat_select_05)31. cheatFlag=5;32. elseif(tempCheat.equals(Constants.cheat_select_06)33. cheatFlag=6;34. 35. 36. adSwitch=sharedPreferences.getBoolean(mContext.getString(R.string.preference_setting_more_check_key).toString(),false);37. 38. 監(jiān)-聽到變化之后,然后壁紙程序再做相應的處理,自此DiceWallPaper壁紙程序的配置頁面就結束了。其他說明 壁紙程序中使用了廣告推送和積分強調(diào)的代碼,這是萬普世紀提供的移動廣告服務。上一篇開發(fā)2D動態(tài)壁紙五 DiceWallPaper壁紙程序的配置頁面已經(jīng)介紹
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年藝術市場數(shù)字化交易平臺藝術市場交易稅收優(yōu)惠政策研究報告
- 八年級期初家長會課件
- 安全專項試題及答案
- 新型農(nóng)業(yè)經(jīng)營主體2025年農(nóng)業(yè)科技園區(qū)建設與培育策略研究報告
- 員工安全培訓課件
- 中國功夫說課稿課件博客
- 中國剪紙美術課件學習指南
- 腫瘤患者心理癥狀分析與干預
- 中國農(nóng)業(yè)銀行課件
- 八年級暑假家長會課件
- 砼回彈強度自動計算表
- 果汁飲料加工廠可行性研究方案
- 中小學校長招聘考試試題
- 2024年腫瘤內(nèi)科護理理論考試試題
- 醫(yī)務人員手衛(wèi)生規(guī)范(國家)
- 主題:現(xiàn)代戰(zhàn)爭與軍事科技課件
- 上海華東師范大學附屬東昌中學南校重點中學初一語文自主招生試卷模擬試題(5套帶答案)
- 化工企業(yè)適用-法律法規(guī)文件清單
- 貴州省黔東南苗族侗族自治州2022-2023學年七年級下學期期末生物試題(含答案)
- 工業(yè)催化原理及應用
- 新修訂《土地管理法》考試題庫及答案
評論
0/150
提交評論