您好,登錄后才能下訂單哦!
這篇文章主要介紹“android如何實現icon動態旋轉效果”,在日常操作中,相信很多人在android如何實現icon動態旋轉效果問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”android如何實現icon動態旋轉效果”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
點擊icon后,前景的icon開始旋轉,背景的icon不動,就是這樣一個效果
通過第三方的方法是不可能實現的,我這里是通過修改系統launcher的代碼來實現。實現思路是在launcher中找到顯示icon圖標代碼,并把這個圖標覆蓋掉。很多第手機的時鐘icon是可以動態變化的,好在公司已經有人實現這個功能,可以借鑒
我這里先把時鐘動態icon的實現說明下,需要的朋友可以參考。
寫一個IconScript的基類繼承Drawable
package com.android.launcher3; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.view.View; import android.util.Log; public class IconScript extends Drawable{ public boolean isRuning = false; public FastBitmapDrawable mFastBitmapDrawable = null; protected Paint mPaint = new Paint(); public IconScript(){ mPaint.setAntiAlias(true); mPaint.setFilterBitmap(true); } public void draw(Canvas canvas){ if(mFastBitmapDrawable != null){ Log.e("fly","IconScript="); canvas.drawBitmap(mFastBitmapDrawable.getBitmap(), null, getBounds(),mPaint);//畫底圖 } } /** * 運行腳本 * @param view */ public void run(View view){ isRuning = true; } /** * 停止腳本 * (未調用,暫留入口) */ public void onStop(){ isRuning = false; } /** * 暫停腳本 * (未調用,暫留入口) */ public void onPause(){ isRuning = false; } /** * 恢復腳本 * (未調用,暫留入口) */ public void onResume(){ isRuning = true; } @Override public int getOpacity() { // TODO Auto-generated method stub return 0; } @Override public void setAlpha(int arg0) { // TODO Auto-generated method stub } @Override public void setColorFilter(ColorFilter arg0) { // TODO Auto-generated method stub } @Override public int getIntrinsicWidth() { int width = getBounds().width(); if (width == 0) { width = mFastBitmapDrawable.getBitmap().getWidth(); } return width; } @Override public int getIntrinsicHeight() { int height = getBounds().height(); if (height == 0) { height = mFastBitmapDrawable.getBitmap().getHeight(); } return height; } @Override public int getMinimumWidth() { return getBounds().width(); } @Override public int getMinimumHeight() { return getBounds().height(); } @Override public void setFilterBitmap(boolean filterBitmap) { mPaint.setFilterBitmap(filterBitmap); mPaint.setAntiAlias(filterBitmap); } public void setFastBitmapDrawable(FastBitmapDrawable drawable){ mFastBitmapDrawable = drawable; } public FastBitmapDrawable setFastBitmapDrawable(){ return mFastBitmapDrawable; } }
核心類ClockScript繼承IconScript
package com.android.launcher3; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.text.format.Time; import android.view.View; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; public class ClockScript extends IconScript { Rect mRect = null; /** * 效果展示目標View */ private View mView; /** * 通知系統更新視圖現成 */ private ClockThread mClockThread = null; /** * 當前是否顯示在屏幕上 */ private boolean mIsShowInScreen = false; Context mContext; public ClockScript(Context context){ super(); mContext = context; } public void run(View view) { mView = view; mRect = getBounds(); if(mClockThread == null){ mClockThread = new ClockThread(); mClockThread.start(); } } @Override public void onPause() { mClockThread.pauseRun(); super.onPause(); } @Override public void onResume() { mClockThread.resumeRun(); super.onResume(); } @Override public void onStop() { mClockThread.stopRun(); super.onStop(); } @Override public void draw(Canvas canvas) { super.draw(canvas); mIsShowInScreen = true; drawIndicator(canvas,mRect.centerX(),mRect.centerY(),mPaint); if(mClockThread.wait){ mClockThread.resumeRun(); } } /** * 畫指針 * @param canvas * @param centerX * @param centerY * @param p */ private void drawIndicator(Canvas canvas,int centerX,int centerY,Paint p){ Bitmap clockIcon = Utilities.createIconBitmap( BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher_clock),mContext); int X = clockIcon.getWidth()/2; int Y = clockIcon.getHeight()/2; canvas.drawBitmap(clockIcon, null, getBounds(),p);//畫底圖 Time t=new Time(); t.setToNow(); p.setAntiAlias(true); p.setStrokeWidth(3); p.setColor(Color.WHITE); p.setStyle(Paint.Style.FILL); //hour canvas.drawLine(X, Y, int)(X + (clockIcon.getWidth()/2-35) * Math.cos((t.hour+(float)t.minute/60) * (Math.PI / 6) - Math.PI / 2)), (int)(Y + (clockIcon.getWidth()/2-35) * Math.sin((t.hour+(float)t.minute/60) * (Math.PI / 6) - Math.PI / 2)), p); //minute canvas.drawLine(X, Y,(int)(X + (clockIcon.getWidth()/2-27) * Math.cos(t.minute * (Math.PI / 30) - Math.PI / 2)),(int)(Y + (clockIcon.getWidth()/2-27) * Math.sin(t.minute * (Math.PI / 30) - Math.PI / 2)),p); //second p.setColor(Color.RED); p.setStrokeWidth(1); p.setStyle(Paint.Style.FILL); canvas.drawLine(X, Y,(int)(X + (clockIcon.getWidth()/2-20) * Math.cos(t.second * (Math.PI / 30) - Math.PI / 2)),(int)(Y + (clockIcon.getWidth()/2-20) * Math.sin(t.second * (Math.PI / 30) - Math.PI / 2)),p); p.setColor(Color.WHITE); canvas.drawCircle(X, Y, 4, p); p.setColor(Color.GRAY); canvas.drawCircle(X, Y, 2, p); } class ClockThread extends Thread { int times = 0; boolean running = true; public boolean wait = false; public void stopRun() { running = false; synchronized (this) { this.notify(); } }; public void pauseRun() { this.wait = true; synchronized (this) { this.notify(); } } public void resumeRun() { this.wait = false; synchronized (this) { this.notify(); } } public void run() { while (running) { synchronized (mView) { mView.postInvalidate(); } if(!mIsShowInScreen){ pauseRun(); } mIsShowInScreen = false; try { Thread.sleep(500); } catch (Exception e) { System.out.println(e); } synchronized (this) { if (wait) { try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } }
接下來就是如何初始化這個ClockScript,在Icon類里面添加代碼
--- a/packages/apps/Launcher3/src/com/android/launcher3/IconCache.java +++ b/packages/apps/Launcher3/src/com/android/launcher3/IconCache.java @@ -84,6 +84,7 @@ public class IconCache { public CharSequence title = ""; public CharSequence contentDescription = ""; public boolean isLowResIcon; + public IconScript script; } private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons = new HashMap<>(); @@ -591,7 +592,17 @@ public class IconCache { if (info != null) { entry.title = info.getLabel(); } - + + Log.e("IconCache ","componentName.getPackageName()="+componentName.getPackageName()); //加了一個系統的屬性來控制 + if(null != entry && componentName.getPackageName().equals("com.android.deskclock") && android.os.SystemProperties.getBoolean("launcher.calender.updateicon", false)) + { + Log.e("IconCache","clock init"); + entry.script = new ClockScript(mContext); + } return entry; } @@ -891,4 +902,20 @@ public class IconCache { return null; } } + public IconScript getScript(Intent intent, UserHandleCompat user){ + synchronized (mCache) { + ComponentName component = intent.getComponent(); + + if (component == null) { + Log.e("IconCache ","component==null"); + return null; + } + LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user); + CacheEntry entry = cacheLocked(component, launcherActInfo,user, false, false); + return entry.script; + } + }
在BubbleTextView類中添加代碼
--- a/packages/apps/Launcher3/src/com/android/launcher3/BubbleTextView.java +++ b/packages/apps/Launcher3/src/com/android/launcher3/BubbleTextView.java @@ -30,6 +30,7 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; +import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.KeyEvent; @@ -38,6 +39,7 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewParent; import android.widget.TextView; +import android.graphics.Rect; import com.android.launcher3.IconCache.IconLoadRequest; import com.android.launcher3.model.PackageItemInfo; @@ -148,12 +150,44 @@ public class BubbleTextView extends TextView public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) { applyFromShortcutInfo(info, iconCache, false); - } + + mScript = info.getScript(iconCache); //zengxiao add + if(mScript!=null){ + if(mScript!=null){ + }else{ + Log.e("rtyre","info.iconResource.packageName ------null"); + } + } + private IconScript mScript; + @Override + public void setCompoundDrawables(Drawable left, Drawable top, + Drawable right, Drawable bottom) { + + if(top != null){ + + if(mScript != null){ + + top = mScript; + Rect rect=new Rect(0,0,LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize,LauncherAppState.getInstanc + mScript.setBounds(rect); + + if(!mScript.isRuning) + { + + mScript.run(this); + } + } + } + + super.setCompoundDrawables(left, top, right, bottom); + } public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache, boolean promiseStateChanged) { Bitmap b = info.getIcon(iconCache); - + mScript = info.getScript(iconCache); FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(b);
--- a/packages/apps/Launcher3/src/com/android/launcher3/ShortcutInfo.java +++ b/packages/apps/Launcher3/src/com/android/launcher3/ShortcutInfo.java @@ -304,5 +304,13 @@ public class ShortcutInfo extends ItemInfo { public boolean isDisabled() { return isDisabled != 0; } + + + public IconScript getScript(IconCache iconCache){ + return iconCache.getScript(promisedIntent != null ? promisedIntent : intent, user); + } + }
把這些代碼添加上功能基本ok.
有了這個基礎,我想要實現的效果就變得很簡單,同樣的定義一個WallpaperScript繼承IconScript
package com.android.launcher3; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.text.format.Time; import android.view.View; import android.util.Log; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.Paint; import java.util.Calendar; import android.graphics.BitmapFactory; import android.graphics.Matrix; public class WallpaperScript extends IconScript { private float mDensity = 1.5f; Time mTime = new Time(); int myCount =0; Context mContext; Boolean isDraw =false; /** * 效果展示目標View */ private View mView; /** * 當前是否顯示在屏幕上 */ private boolean mIsShowInScreen = false; /** * 通知系統更新視圖現成 */ private WallpaperThread mWallpaperThread = null; int[] arr=new int[]{R.drawable.ic_launcher_wallpaper_1,R.drawable.ic_launcher_wallpaper_2,R.drawable.ic_launcher_wallpaper_3, R.drawable.ic_launcher_wallpaper_4,R.drawable.ic_launcher_wallpaper_5,R.drawable.ic_launcher_wallpaper_6 }; int index = 0; public WallpaperScript(Context context) { super(); mContext = context; } public void run(View view) { mView = view; if(mWallpaperThread == null){ //Log.d("WallpaperScript","mWallpaperThread "); mWallpaperThread = new WallpaperThread(); mWallpaperThread.start(); } IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.WallpaperChange"); view.getContext().registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context arg0, Intent arg1) { Log.d("WallpaperScript","onReceive "); isDraw = true; mWallpaperThread.startRun(); mWallpaperThread.start(); // myCount =0; } }, filter); } @Override public void onPause() { mWallpaperThread.pauseRun(); super.onPause(); } @Override public void onResume() { mWallpaperThread.resumeRun(); super.onResume(); } @Override public void onStop() { mWallpaperThread.stopRun(); super.onStop(); } @Override public void draw(Canvas canvas) { super.draw(canvas); Bitmap wallpaperIconfirst = Utilities.createIconBitmap( BitmapFactory.decodeResource(mContext.getResources(), arr[0]),mContext); canvas.drawBitmap(wallpaperIconfirst, null, getBounds(),mPaint);//默認顯示的圖片 if(isDraw){ index = index%6; Bitmap wallpaperIcon = Utilities.createIconBitmap( BitmapFactory.decodeResource(mContext.getResources(), arr[index]),mContext); index = index+1; myCount =myCount+1; canvas.drawBitmap(wallpaperIcon, null, getBounds(),mPaint);//畫底圖 //Log.d("WallpaperScript","WallpaperScript index "+index+" myCount "+myCount); if(myCount==49){ myCount=0; mWallpaperThread.stopRun(); //Log.d("WallpaperScript","WallpaperScript myCount " +myCount); isDraw = false; } } } class WallpaperThread extends Thread { int times = 0; boolean running = true; public boolean wait = false; public void startRun() { running = true; synchronized (this) { this.notify(); } }; public void stopRun() { running = false; synchronized (this) { this.notify(); } }; public void pauseRun() { /*this.wait = true; synchronized (this) { this.notify(); } */ } public void resumeRun() { /*this.wait = false; synchronized (this) { this.notify(); }*/ } public void run() { Log.d("WallpaperScript","WallpaperThread running "+ running); while (running) { synchronized (mView) { Log.d("WallpaperScript","WallpaperThread run()"); mView.postInvalidate(); } try { Thread.sleep(50); } catch (Exception e) { System.out.println(e); } } } } }
把所有的圖片放到一個數組里面,然后輪流去繪制里面的圖片,點擊圖標的時候會發送一個廣播,通過廣播去控制線程的開啟,這樣功能基本上實現。
另外,怎樣去實現沒有界面的app,這個只需要AndroidManifest設置。
android:theme="@android:style/Theme.NoDisplay"
切換鎖屏壁紙和主屏幕壁紙的代碼
WallpaperManager manager = WallpaperManager.getInstance(this); try { manager.setBitmap(bitmap,null, true, WallpaperManager.FLAG_LOCK | WallpaperManager.FLAG_SYSTEM); } catch (Exception e) { e.printStackTrace(); }
到此,關于“android如何實現icon動態旋轉效果”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。