我在这篇文章中将描述我如何整理动态壁纸。



要创建动态壁纸,您需要设置以下内容
-
一个扩展
WallpaperService
并进一步实现扩展Engine
类的嵌套类的类。该类负责调用绘图代码。 - 显示壁纸设置列表的活动。(可选)。在这里,我发现了Android Preference API,它可以轻松地为应用程序创建设置
- xml 文件夹中壁纸的XML定义。
- 用于动态壁纸和偏好活动的AndroidManifest.xml条目。
入门
1.要创建动态壁纸,您必须在课程类中WallpaperService
找到有关课程的更多信息,请访问https://developer.android.com/reference/android/service/wallpaper/WallpaperService.html
该类必须覆盖onCreateEngine()
返回Engine
类 对象的 方法方法
此外,此类必须具有扩展Engine
类的嵌套类。(我不知道为什么)
要创建下降动画,我需要连续绘制表面。之前在使用canvas视图invalidate()
方法时调用了更新视图。但是在Engine
课堂上没有这样的方法。要首先绘制效果,您需要从中获取画布getSurfaceHolder();
之后,以特定间隔运行线程以更新绘图表面。
以下是动态skeleton
壁纸的类。

package matrixlw.app.skd.wa; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.preference.PreferenceManager; import android.service.wallpaper.WallpaperService; import android.util.Log; import android.view.SurfaceHolder; import com.enrico.colorpicker.colorDialog; import java.util.Random; /** * Created by sapan on 1/10/2017. */ public class matrixWall extends WallpaperService { private boolean mVisible; // visible flag Canvas canvas; // canvas reference int Drawspeed=10; // thread call delay time Context mcontext; //reference to the current context @Override public Engine onCreateEngine() { //set the Preference default value mcontext = this; //set the current context //return the Engine Class return new LiveWall(); // this calls contain the wallpaper code } /* * this class extends the engine for the live wallpaper * THis class implements all the draw calls required to draw the wallpaper * This call is to neseted inside the wallpaper service class to function properly * don't know why though :( */ public class LiveWall extends Engine { final Handler mHandler = new Handler(); // this is to handle the thread //the tread responsibe for drawing this thread get calls every time // drawspeed vars set the execution speed private final Runnable mDrawFrame = new Runnable() { public void run() { // This method get called each time to drwaw thw frame // Engine class does not provide any invlidate methods // as used in canvas // set your draw call here drawFrame(); } }; //Called when the surface is created @Override public void onSurfaceCreated(SurfaceHolder holder) { super.onSurfaceCreated(holder); //call the draw method // this is where you must call your draw code drawFrame(); } // remove thread @Override public void onDestroy() { super.onDestroy(); mHandler.removeCallbacks(mDrawFrame); } //called when varaible changed @Override public void onVisibilityChanged(boolean visible) { mVisible = visible; if (visible) { //call the drawFunction drawFrame(); } else { //this is necessay to remove the call back mHandler.removeCallbacks(mDrawFrame); } } //called when surface destroyed @Override public void onSurfaceDestroyed(SurfaceHolder holder) { super.onSurfaceDestroyed(holder); mVisible = false; //this is necessay to remove the call back mHandler.removeCallbacks(mDrawFrame); } // my function which contain the code to draw //this function contain the the main draw call /// this function need to call every time the code is executed // the thread call this functioin with some delay "drawspeed" public void drawFrame() { //getting the surface holder final SurfaceHolder holder = getSurfaceHolder(); canvas = null; // canvas try { canvas = holder.lockCanvas(); //get the canvas if (canvas != null) { // draw something // my draw code } } finally { if (canvas != null) holder.unlockCanvasAndPost(canvas); } // Reschedule the next redraw // this is the replacement for the invilidate funtion // every time call the drawFrame to draw the matrix mHandler.removeCallbacks(mDrawFrame); if (mVisible) { // set the execution delay mHandler.postDelayed(mDrawFrame, Drawspeed); } } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height); // update when surface changed } } }
2.创建xml定义。
作为壁纸服务,必须在mywallpaper.xml等xml文件夹中创建xml文件
<?xml version="1.0" encoding="UTF-8"?>
<wallpaper
xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="@mipmap/ic_launcher"
android:settingsActivity="matrixlw.app.skd.wa.SettingsActivity"/>
这里android:settingsActivity="matrixlw.app.skd.wa.SettingsActivity"/>
指向在动态壁纸预览屏幕上单击设置按钮时调用的设置活动
3. 必须正确设置android AndroidManifest.xml 以获取运行此文件的动态壁纸。
-
设置功能
隐藏 复制代码
<uses-feature android:name="android.software.live_wallpaper" />
-
添加壁纸和资源xml文件的服务。
隐藏 复制代码
<service android:name=".matrixWall" android:enabled="true" android:label="MATRIX RAIN" android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService" /> </intent-filter> <meta-data android:name="android.service.wallpaper" android:resource="@xml/mywallpaper"></meta-data> </service>
-
添加设置活动
隐藏 复制代码
<activity android:name=".SettingsActivity" android:label="@string/title_activity_settings" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
android:exported="true"
必须设置此处,否则单击设置按钮时将不会打开此活动
3.创建设置活动
“设置”活动包含用于自定义动态壁纸属性的UI。首选项活动是使用android首选项API创建的,这提供了一种创建首选项API的简便方法
有关详细信息,请访问:https://developer.android.com/guide/topics/ui/settings.html
Color Picker是使用richocid创建的库
参考:https://github.com/enricocid/Color-picker-library
我正在跳过设置活动。设置活动的文件和布局是SettingsActivity.java和xml / preferences。
4.整理动态壁纸:
矩阵雨效应将是我在我之前的文章中解释过的动态壁纸。
ref - 下面是该项目的抽奖代码

// ======== MATRIX LIVE WALLPAPER VARS int background_color= Color.parseColor("#FF000000"); int text_color=Color.parseColor("#FF8BFF4A"); int width = 1000000; //default initial width int height = 100; //default initial height int fontSize = 15; //font size of the text which will fall int columnSize = width/fontSize; //column size ; no of digit required to fill the screen int parentWidth; String text = "MATRIXRAIN"; // Text which need to be drawn char[] textChar = text.toCharArray(); // split the character of the text int textLength = textChar.length; //length of the length text Random rand = new Random(); //random generater int[] textPosition; // contain the position which will help to draw the text //====================== //old matrix effect code void drawText() { //Set up the paint Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(text_color); paint.setTextSize(15); //loop and paint for(int i =0 ;i<textPosition.length;i++) { // draw the text at the random position canvas.drawText(""+textChar[rand.nextInt(textLength)+0],i*fontSize,textPosition[i]*fontSize,paint); // check if text has reached bottom or not if(textPosition[i]*fontSize > height && Math.random() > 0.975) textPosition[i] = 0; // change text position to zero when 0 when text is at the bottom textPosition[i]++; //increment the position array } } //old martix effect code public void canvasDraw() { Log.d("canvas ","drawing"); //set the paint for the canvas Paint paint = new Paint(); paint.setColor(background_color); paint.setAlpha(5); paint.setStyle(Paint.Style.FILL); canvas.drawRect(0, 0, width, height, paint);//draw rect to clear the canvas drawText(); // draw the canvas }
现在上面的代码需要插入到骨架壁纸服务代码中。在skeleton类中,DrawFrame()
方法用于调用draw语句。

package matrixlw.app.skd.wa; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.preference.PreferenceManager; import android.service.wallpaper.WallpaperService; import android.util.Log; import android.view.SurfaceHolder; import com.enrico.colorpicker.colorDialog; import java.util.Random; /** * Created by sapan on 1/10/2017. */ public class matrixWall extends WallpaperService { private boolean mVisible; // visible flag Canvas canvas; // canvas reference int Drawspeed=10; // thread call delay time Context mcontext; //reference to the current context // ======== MATRIX LIVE WALLPAPER VARS int background_color= Color.parseColor("#FF000000"); int text_color=Color.parseColor("#FF8BFF4A"); int width = 1000000; //default initial width int height = 100; //default initial height int fontSize = 15; //font size of the text which will fall int columnSize = width/fontSize; //column size ; no of digit required to fill the screen int parentWidth; String text = "MATRIXRAIN"; // Text which need to be drawn char[] textChar = text.toCharArray(); // split the character of the text int textLength = textChar.length; //length of the length text Random rand = new Random(); //random generater int[] textPosition; // contain the position which will help to draw the text //====================== @Override public Engine onCreateEngine() { //set the Preference default value mcontext = this; //set the current context //Initalise and read the preference PreferenceManager.setDefaultValues(this, R.xml.preferences, false); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); text = sharedPref.getString("matrix_scroll_text", "MATRIX"); Drawspeed = Integer.parseInt(sharedPref.getString("matrix_falling_speed","10")); fontSize = Integer.parseInt(sharedPref.getString("matrix_font_size","15")); background_color = colorDialog.getPickerColor(getBaseContext(), 1); text_color =colorDialog.getPickerColor(getBaseContext(), 2); //Some loggers Commnet or remove if you want Log.d("back_color",""+background_color); Log.d("text_color",""+text_color); textChar = text.toCharArray(); // split the character of the text textLength = textChar.length; columnSize = width/fontSize; //return the Engine Class return new LiveWall(); // this calls contain the wallpaper code } /* * this class extends the engine for the live wallpaper * THis class implements all the draw calls required to draw the wallpaper * This call is to neseted inside the wallpaper service class to function properly * don't know why though :( */ public class LiveWall extends Engine { final Handler mHandler = new Handler(); // this is to handle the thread //the tread responsibe for drawing this thread get calls every time // drawspeed vars set the execution speed private final Runnable mDrawFrame = new Runnable() { public void run() { //Matrix code to the color when changed // callback can also be used but I havent background_color = colorDialog.getPickerColor(getBaseContext(), 1); text_color =colorDialog.getPickerColor(getBaseContext(), 2); // ^^^^^^^^ // This method get called each time to drwaw thw frame // Engine class does not provide any invlidate methods // as used in canvas // set your draw call here drawFrame(); } }; //Called when the surface is created @Override public void onSurfaceCreated(SurfaceHolder holder) { super.onSurfaceCreated(holder); //update the matrix variables width = getDesiredMinimumWidth(); height = getDesiredMinimumHeight(); columnSize = width/fontSize; //initalise the textposiotn to zero textPosition = new int[columnSize+1]; //add one more drop for(int x = 0; x < columnSize; x++) { textPosition[x] = 1; } //^^^^^^^^^^^^^^^ //call the draw method // this is where you must call your draw code drawFrame(); } // remove thread @Override public void onDestroy() { super.onDestroy(); mHandler.removeCallbacks(mDrawFrame); } //called when varaible changed @Override public void onVisibilityChanged(boolean visible) { mVisible = visible; if (visible) { SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mcontext); text = sharedPref.getString("matrix_scroll_text", "MATRIX"); Drawspeed = Integer.parseInt(sharedPref.getString("matrix_falling_speed","10")); fontSize = Integer.parseInt(sharedPref.getString("matrix_font_size","15")); background_color = colorDialog.getPickerColor(getBaseContext(), 1); text_color =colorDialog.getPickerColor(getBaseContext(), 2); textChar = text.toCharArray(); // split the character of the text textLength = textChar.length; columnSize = width/fontSize; drawFrame(); } else { SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mcontext); text = sharedPref.getString("matrix_scroll_text", "MATRIX"); Drawspeed = Integer.parseInt(sharedPref.getString("matrix_falling_speed","10")); fontSize = Integer.parseInt(sharedPref.getString("matrix_font_size","15")); background_color = colorDialog.getPickerColor(getBaseContext(), 1); text_color =colorDialog.getPickerColor(getBaseContext(), 2); textChar = text.toCharArray(); // split the character of the text textLength = textChar.length; columnSize = width/fontSize; //this is necessay to remove the call back mHandler.removeCallbacks(mDrawFrame); } } //called when surface destroyed @Override public void onSurfaceDestroyed(SurfaceHolder holder) { super.onSurfaceDestroyed(holder); mVisible = false; //this is necessay to remove the call back mHandler.removeCallbacks(mDrawFrame); } //this function contain the the main draw call /// this function need to call every time the code is executed // the thread call this functioin with some delay "drawspeed" public void drawFrame() { //getting the surface holder final SurfaceHolder holder = getSurfaceHolder(); canvas = null; // canvas try { canvas = holder.lockCanvas(); //get the canvas if (canvas != null) { // draw something // canvas matrix draw code canvasDraw(); //^^^^ } } finally { if (canvas != null) holder.unlockCanvasAndPost(canvas); } // Reschedule the next redraw // this is the replacement for the invilidate funtion // every time call the drawFrame to draw the matrix mHandler.removeCallbacks(mDrawFrame); if (mVisible) { // set the execution delay mHandler.postDelayed(mDrawFrame, Drawspeed); } } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height); // some matrix variable // though not needed Paint paint = new Paint(); paint.setColor(background_color); paint.setAlpha(255); //set the alpha paint.setStyle(Paint.Style.FILL); canvas.drawRect(0, 0, width, height, paint); } } //old matrix effect code void drawText() { //Set up the paint Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); paint.setColor(text_color); paint.setTextSize(15); //loop and paint for(int i =0 ;i<textPosition.length;i++) { // draw the text at the random position canvas.drawText(""+textChar[rand.nextInt(textLength)+0],i*fontSize,textPosition[i]*fontSize,paint); // check if text has reached bottom or not if(textPosition[i]*fontSize > height && Math.random() > 0.975) textPosition[i] = 0; // change text position to zero when 0 when text is at the bottom textPosition[i]++; //increment the position array } } //old martix effect code public void canvasDraw() { Log.d("canvas ","drawing"); //set the paint for the canvas Paint paint = new Paint(); paint.setColor(background_color); paint.setAlpha(5); paint.setStyle(Paint.Style.FILL); canvas.drawRect(0, 0, width, height, paint);//draw rect to clear the canvas drawText(); // draw the canvas } }
这里使用以下方法来设置表面
public void onSurfaceCreated(SurfaceHolder holder) public void onVisibilityChanged(boolean visible) public void onSurfaceDestroyed(SurfaceHolder holder) public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height)
现在你有完整的工作动态壁纸代码。
获取源表单:https://github.com/sapandang/Matrix-Rain-Live-Wallpaper