本文实例为大家分享了android实现icon动态旋转效果的具体代码,供大家参考,具体内容如下
碰到客户的这样一个需求,点击icon后,前景的icon开始旋转,背景的icon不动,就是这样一个效果

通过第三方的方法是不可能实现的,我这里是通过修改系统launcher的代码来实现。实现思路是在launcher中找到显示icon图标代码,并把这个图标覆盖掉。很多第手机的时钟icon是可以动态变化的,好在公司已经有人实现这个功能,可以借鉴
我这里先把时钟动态icon的实现说明下,需要的朋友可以参考。
写一个IconScript的基类继承Drawable
核心类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();
- }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。