android 蕾姆gif動態桌布 demo
阿新 • • 發佈:2019-01-26
效果圖
部落格地址:http://write.blog.csdn.net/postedit
下載地址:https://github.com/Aiushtha/RemWallpaper/tree/master
在別的地方看到類似的效果 自己仿做了一個 。預設是雙擊觸發動畫播放!!
研究大致實現的原理 ,用最近大熱的動漫人物作主題
素材是網上找的,感覺還可以做很多有趣的東西(大霧)
gif播放參考gitView核心程式碼--
/** * Calculate current animation time */ public void updateAnimationTime() { long now = android.os.SystemClock.uptimeMillis(); if (mMovieStart == 0) { mMovieStart = now; } int dur = movie.duration(); if (dur == 0) { dur = DEFAULT_MOVIE_VIEW_DURATION; } numberOfRemainingPlay = numberOfPlayCount - (now - mMovieStart) / dur; mCurrentAnimationTime = (int) ((now - mMovieStart) % dur); } /** * Draw current GIF frame */ public void drawMovieFrame(Canvas canvas) { if (numberOfRemainingPlay > 0) { updateAnimationTime(); mMovieStart = android.os.SystemClock.uptimeMillis() - mCurrentAnimationTime; movie.setTime(mCurrentAnimationTime); canvas.save(Canvas.MATRIX_SAVE_FLAG); canvas.scale(mScale, mScale); movie.draw(canvas, mLeft / mScale, mTop / mScale); canvas.restore(); } else { movie.setTime(movie.duration()); } }
通過喚醒執行緒來控制播放 桌布核心程式碼:
package priv.lxz.wallpaper.rem; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Movie; import android.graphics.PorterDuff; import android.media.MediaPlayer; import android.os.Handler; import android.service.wallpaper.WallpaperService; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.widget.Toast; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import de.greenrobot.event.EventBus; import share.DataShare; public class WallpaperSwitcher extends WallpaperService { private int mWidth; private int mHeight; public Handler handler = new Handler(); GifCanvas gitCanvas; private boolean isVisible; private boolean isDestop; private boolean isPause; ReentrantLock lock; private Condition condition; Thread thread; //系統狀態列高度 private int system_bar_height; private GifShowOption option; private Wallpaper wallpaper; private DataShare dataShare; private MediaPlayer player; private boolean isLog=false; public void onEventMainThread(AppMessageEvent event) { option = (GifShowOption) event.getObj(); wallpaper.effect(option); } public void showLog(String str) { if(isLog) { Toast.makeText(getBaseContext(), "onCreate", Toast.LENGTH_LONG); } } @Override public Engine onCreateEngine() { // TODO Auto-generated method stub showLog("onCreate"); initOption(); if (!EventBus.getDefault().isRegistered(this)) { EventBus.getDefault().register(this); } gitCanvas = new GifCanvas(getResources(), R.raw.rem); player = MediaPlayer.create(this, R.raw.music_b); player.setLooping(false); if(condition!=null) { isDestop = true; //當重新選擇桌布時銷燬執行緒 { lock.lock(); condition.signalAll(); lock.unlock(); //直到執行緒被銷燬 while (thread != null) { } isDestop = false; } } lock = new ReentrantLock(); condition = lock.newCondition(); system_bar_height = getStatusHeight(getBaseContext()); return wallpaper = new Wallpaper(); } private void initOption() { dataShare = DataShare.getInstance(getBaseContext()); option = new GifShowOption(); option = dataShare.getData(GifShowOption.class); if (option == null) option = GifShowOption.getDefault(); } @Override public void onDestroy() { super.onDestroy(); isDestop = true; lock.lock(); condition.signalAll(); lock.unlock(); EventBus.getDefault().unregister(this); player.release(); lock=null; condition=null; showLog("Destroy"); } /** * 獲得狀態列的高度 * * @param context * @return */ public static int getStatusHeight(Context context) { int statusHeight = -1; try { Class clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } class Wallpaper extends Engine implements GestureDetector.OnGestureListener { private GestureDetector gestureScanner; public Wallpaper() { thread = new Thread() { @Override public void run() { while (!isDestop) { try { if (isVisible && gitCanvas.getNumberOfRemainingPlay() > 0) { Canvas canvas = null; try { canvas = getSurfaceHolder().lockCanvas(); if (canvas != null) { canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); gitCanvas.drawMovieFrame(canvas); setCanvasARGB(canvas); } } finally { if (canvas != null && !isDestop) getSurfaceHolder().unlockCanvasAndPost(canvas); } ; } else { if (!isDestop) { show(); lock.lock(); try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock(); } } } catch (Exception e) { e.printStackTrace(); } } thread = null; } }; thread.start(); } public void checkPlayMusic() { if (gitCanvas.getNumberOfRemainingPlay() <= 0) { if (option.isPlaySound) { player.start(); } } } private void tiggerCheck(int mode) { switch (mode) { case GifShowOption.TRIGGER_MODE_CHECK_SINGLE: if (option.trigger_mode == GifShowOption.TRIGGER_MODE_CHECK_SINGLE) { checkPlayMusic(); gitCanvas.resetPlayNumbierOfOne(); play(); } break; case GifShowOption.TRIGGER_MODE_CHECK_LONG: if (option.trigger_mode == GifShowOption.TRIGGER_MODE_CHECK_SINGLE) { checkPlayMusic(); gitCanvas.resetPlayNumbierOfOne(); play(); } break; case GifShowOption.TRIGGER_MODE_CHECK_DOUBLE: if (option.trigger_mode == GifShowOption.TRIGGER_MODE_CHECK_DOUBLE) { checkPlayMusic(); gitCanvas.resetPlayNumbierOfOne(); play(); } break; } } /** * 計算比例 */ private void setCanvasScale(GifCanvas gitCanvas, int mWidth, int mHeight, Movie movie) { if (option != null) { if (option.isAdaptiveHeight) { gitCanvas.setScale(1.0f * mHeight / gitCanvas.getMovie().height()); } else if (option.isAdaptiveWidth) { gitCanvas.setScale(1.0f * mWidth / gitCanvas.getMovie().width()); } else if (option.isAdaptiveCustomRatio) { gitCanvas.setScale(option.scale); } } } private void setCanvasARGB(Canvas canvas) { if (option != null) { canvas.drawARGB((int) (255 - option.brightness * 0.01f * 255), 0, 0, 0); } } private void effect(GifShowOption option) { if (getSurfaceHolder() != null) { if (mHeight != 0 && mWidth != 0) { if (option.isAdaptiveHeight) { gitCanvas.setScale(1.0f * mHeight / gitCanvas.getMovie().height()); } else if (option.isAdaptiveWidth) { gitCanvas.setScale(1.0f * mWidth / gitCanvas.getMovie().width()); } else if (option.isAdaptiveCustomRatio) { gitCanvas.setScale(option.scale); } } } float offectTop = option.upperOffset; float offectLeft = option.leftOffset; if (option.isCalculationBarheight) { gitCanvas.setMoveTop(offectTop + system_bar_height); } else { gitCanvas.setMoveTop(offectTop); } gitCanvas.setMoveLeft(offectLeft); show(); } @Override public void onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub super.onTouchEvent(event); gestureScanner.onTouchEvent(event); } @Override public void onSurfaceCreated(SurfaceHolder holder) { super.onSurfaceCreated(holder); gestureScanner = new GestureDetector(this); } @Override public void onSurfaceDestroyed(SurfaceHolder holder) { super.onSurfaceDestroyed(holder); } boolean isFristChang = false; @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (!isFristChang) { mHeight = height; mWidth = width; setCanvasScale(gitCanvas, mWidth, mHeight, gitCanvas.getMovie()); ; show(); } isFristChang = true; super.onSurfaceChanged(holder, format, width, height); } @Override public void onVisibilityChanged(boolean visible) { isVisible = visible; if (visible) { play(); } else { } } void show() { Canvas canvas = null; try { canvas = getSurfaceHolder().lockCanvas(); if (canvas != null) { canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); gitCanvas.drawMovieFrame(canvas, 0); setCanvasARGB(canvas); } } finally { try { if (canvas != null && !isDestop) getSurfaceHolder().unlockCanvasAndPost(canvas); } catch (Exception e) { } } } public int isDoubleClick = 0; @Override public boolean onDown(MotionEvent motionEvent) { tiggerCheck(GifShowOption.TRIGGER_MODE_CHECK_SINGLE); isDoubleClick++; if (isDoubleClick >= 2) { tiggerCheck(GifShowOption.TRIGGER_MODE_CHECK_DOUBLE); } handler.postDelayed(new Runnable() { @Override public void run() { isDoubleClick = 0; } }, 250); return false; } public void play() { lock.lock(); condition.signalAll(); lock.unlock(); } @Override public void onShowPress(MotionEvent motionEvent) { } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return false; } @Override public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { return false; } @Override public void onLongPress(MotionEvent motionEvent) { gitCanvas.resetPlayNumbierOfOne(); play(); } @Override public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { return false; } } }