<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文範例為大家分享了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(); }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45