系统方向学习总结5--Launcher3实现动态指针时钟功能
Posted 怀化纱厂杨二狗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了系统方向学习总结5--Launcher3实现动态指针时钟功能相关的知识,希望对你有一定的参考价值。
活动地址:CSDN21天学习挑战赛
最近跟着CSDN大佬,参与一个 21天打卡的活动
Android framework开发者带你参加21天学习挑战赛活动_安卓兼职framework应用工程师的博客-CSDN博客
这是第4次的内容 Android 9.0 10.0 Launcher3 时钟动态图标的定制化(时钟动态图标)_安卓兼职framework应用工程师的博客-CSDN博客
主要实现功能,可能有不合理的地方
首先创建一个实现功能的工具里,直接上代码:
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.util.LogUtil;
public class DeskClockUtil
private OnDeskClockIconChangeListener mListener;
private ItemInfo mItemInfo;
private boolean mIsResume;
private Handler mHandler = new Handler()
@Override
public void handleMessage(Message msg)
super.handleMessage(msg);
if (msg.what == 100)
Message msg1 = new Message();
msg1.what = 100;
msg1.obj = msg.obj;
mHandler.sendMessageDelayed(msg1, 60000);
if (mListener != null && mItemInfo != null)
mListener.onChange(IconUtil.getDeskClockIcon((Context) msg.obj), mItemInfo);
;
private static DeskClockUtil sInstance;
private DeskClockUtil()
public static DeskClockUtil getInstance()
if (sInstance == null)
sInstance = new DeskClockUtil();
return sInstance;
private void refresh(Context context)
if (mListener != null && mItemInfo != null)
mListener.onChange(IconUtil.getDeskClockIcon(context), mItemInfo);
if (mHandler.hasMessages(100))
mHandler.removeMessages(100);
Message msg = new Message();
msg.what = 100;
msg.obj = context;
mHandler.sendMessageDelayed(msg,
1000 * (60 - Integer.parseInt(DateUtils.getCurrentSecond())));
public void onResume(Context context)
mIsResume = true;
refresh(context);
public void onPause()
mIsResume = false;
mHandler.removeMessages(100);
public void setListener(OnDeskClockIconChangeListener listener, ItemInfo info, Context context)
if (!(info instanceof ShortcutInfo))
return;
String pkg = null;
if (info.getIntent() != null && info.getIntent().getComponent() != null)
pkg = info.getIntent().getComponent().getPackageName();
if (!"com.android.deskclock".equals(pkg) || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
return;
mListener = listener;
mItemInfo = info;
if (mIsResume)
refresh(context);
public interface OnDeskClockIconChangeListener
void onChange(Bitmap icon, ItemInfo info);
画出动态时钟
import android.content.Context;
import android.graphics.*;
import com.android.launcher3.R;
public class IconUtil
private static final String TAG = "IconUtil";
private static Bitmap getBitmap(Context context, int res)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
return BitmapFactory.decodeResource(context.getResources(), res, options);
public static Bitmap getDeskClockIcon(Context context)
// 添加一个带表盘的背景图
Bitmap empty = getBitmap(context, R.drawable.icon_time);
int x = empty.getWidth();
int y = empty.getHeight();
Bitmap deskClock = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(deskClock);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(empty, 0, 0, paint);
//设置圆角
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
paint.setColor(context.getResources().getColor(R.color.deskclock_time));
// 时针的长度
int radius = 35;
// 圆心的x y 坐标
int cx = x / 2;
int cy = y / 2;
int hour = Integer.parseInt(DateUtils.getCurrentHour());
int min = Integer.parseInt(DateUtils.getCurrentMin());
//时针的角度,这里是整点的角度。因为0°是从3点开始,所以这里减90°,从9点开始计算角度
int drgeeHour = hour * 30 - 90;
if (drgeeHour < 0)
drgeeHour += 360;
// 加上时针在两个整点之间的角度,一分钟在分针上是6°,在时针上是min * 6 / 12
drgeeHour += min * 6 / 12;
//时针 针尖的x y坐标,相当于已知圆心坐标和半径,求圆上任意一点的坐标
int xHour = (int) (cx + radius * Math.cos(drgeeHour * 3.14 / 180));
int yHour = (int) (cy + radius * Math.sin(drgeeHour * 3.14 / 180));
canvas.drawLine(xHour, yHour, cx, cy, paint);
//分针的长度
radius = 45;
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
//分针的角度
int drgeeMin = min * 6 - 90;
if (drgeeMin < 0)
drgeeMin += 360;
//分针 针尖的x y坐标
int x1 = (int) (cx + radius * Math.cos(drgeeMin * Math.PI / 180));
int y1 = (int) (cy + radius * Math.sin(drgeeMin * Math.PI / 180));
canvas.drawLine(x1, y1, cx, cy, paint);
return deskClock;
时间工具类
import java.text.SimpleDateFormat;
public class DateUtils
public static String getCurrentDay()
SimpleDateFormat format = new SimpleDateFormat("dd");
Long t = new Long(System.currentTimeMillis());
String d = format.format(t);
return d;
public static String getCurrentSecond()
SimpleDateFormat format = new SimpleDateFormat("ss");
Long t = new Long(System.currentTimeMillis());
String d = format.format(t);
return d;
public static String getCurrentMin()
SimpleDateFormat format = new SimpleDateFormat("mm");
Long t = new Long(System.currentTimeMillis());
String d = format.format(t);
return d;
public static String getCurrentHour()
SimpleDateFormat format = new SimpleDateFormat("HH");
Long t = new Long(System.currentTimeMillis());
String d = format.format(t);
return d;
下面就比较简单了,我是在BubbleTextView.java中添加listener,我这里偷懒了,应该给时钟单独创建一个view,继承BubbleTextView。
private void applyIconAndLabel(Bitmap icon, ItemInfo info)
/* begin */
setDeskClockIcon(info);
/* end */
applyIcon(icon, info);
setText(info.title);
if (info.contentDescription != null)
setContentDescription(info.isDisabled()
? getContext().getString(R.string.disabled_app_label, info.contentDescription)
: info.contentDescription);
private void setDeskClockIcon(ItemInfo info)
DeskClockUtil.getInstance().setListener(new DeskClockUtil.OnDeskClockIconChangeListener()
@Override
public void onChange(Bitmap icon, ItemInfo info)
applyIcon(icon, info);
, info, getContext());
private void applyIcon(Bitmap icon, ItemInfo info)
FastBitmapDrawable iconDrawable = DrawableFactory.get(getContext()).newIcon(icon, info);
iconDrawable.setIsDisabled(info.isDisabled());
setIcon(iconDrawable);
在Launcher.java的onResume()和onPause()中分别开始和暂停
@Override protected void onResume()
......
/* begin */
DeskClockUtil.getInstance().onResume(this);
/* end */
if (mLauncherCallbacks != null)
mLauncherCallbacks.onResume();
@Override
protected void onPause()
// Ensure that items added to Launcher are queued until Launcher returns
InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED);
super.onPause();
mPaused = true;
mDragController.cancelDrag();
mDragController.resetLastGestureUpTime();
// We call onHide() aggressively. The custom content callbacks should be able to
// debounce excess onHide calls.
if (mWorkspace.getCustomContentCallbacks() != null)
mWorkspace.getCustomContentCallbacks().onHide();
if (mLauncherCallbacks != null)
mLauncherCallbacks.onPause();
/* begin */
DeskClockUtil.getInstance().onPause();
/* end */
这样就可以了,如果想要加秒针,在IconUtil中再把秒针画出来就行。
还有日历的动态图标也可以用同样的方法实现
以上是关于系统方向学习总结5--Launcher3实现动态指针时钟功能的主要内容,如果未能解决你的问题,请参考以下文章