SoFunction
Updated on 2025-04-10

Android 8.1 Launcher3 implements dynamic pointer clock function

This article mainly implements functions, and there may be unreasonable aspects

First, create a tool to implement functions and directly enter the code:

import ;
import ;
import ;
import ;
import .;
import .;
import .;
import .;
public class DeskClockUtil {
  private OnDeskClockIconChangeListener mListener;
  private ItemInfo mItemInfo;
  private boolean mIsResume;
  private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      (msg);
      if ( == 100) {
        Message msg1 = new Message();
         = 100;
         = ;
        (msg1, 60000);
        if (mListener != null && mItemInfo != null) {
          (((Context) ), 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) {
      ((context), mItemInfo);
    }
    if ((100)) {
      (100);
    }
    Message msg = new Message();
     = 100;
     = context;
    (msg,
        1000 * (60 - (())));
  }
  public void onResume(Context context) {
    mIsResume = true;
    refresh(context);
  }
  public void onPause() {
    mIsResume = false;
    (100);
  }
  public void setListener(OnDeskClockIconChangeListener listener, ItemInfo info, Context context) {
    if (!(info instanceof ShortcutInfo)) {
      return;
    }
    String pkg = null;
    if (() != null && ().getComponent() != null) {
      pkg = ().getComponent().getPackageName();
    }
    if (!"".equals(pkg) ||  == .ITEM_TYPE_DEEP_SHORTCUT) {
      return;
    }
    mListener = listener;
    mItemInfo = info;
    if (mIsResume) {
      refresh(context);
    }
  }
  public interface OnDeskClockIconChangeListener {
    void onChange(Bitmap icon, ItemInfo info);
  }
}

Draw a dynamic clock

import ;
import .*;
import .;
public class IconUtil {
  private static final String TAG = "IconUtil";
  private static Bitmap getBitmap(Context context, int res) {
     options = new ();
     = .ARGB_4444;
    return ((), res, options);
  }
  public static Bitmap getDeskClockIcon(Context context) {
    // Add a background image with a dial    Bitmap empty = getBitmap(context, .icon_time);
    int x = ();
    int y = ();
    Bitmap deskClock = (x, y, .ARGB_4444);
    Canvas canvas = new Canvas(deskClock);
    Paint paint = new Paint();
    (true);
    (empty, 0, 0, paint);
    //Set rounded corners    ();
    (5);
    (().getColor(.deskclock_time));
    // The length of the hour hand    int radius = 35;
    // x y coordinates of the center of the circle    int cx = x / 2;
    int cy = y / 2;
    int hour = (());
    int min = (());
    //The angle of the hour hand, here is the angle of the hour point.  Because 0° starts at 3 points, we can subtract 90° here and calculate the angle from 9 points.    int drgeeHour = hour * 30 - 90;
    if (drgeeHour < 0) {
      drgeeHour += 360;
    }
    // Add the angle between two hour points, one minute is 6° on the minute hand, and min * 6 / 12 on the hour hand    drgeeHour += min * 6 / 12;
    //The x y coordinate of the needle tip is equivalent to the known center coordinates and radius. Find the coordinates at any point on the circle at any point on the circle    int xHour = (int) (cx + radius * (drgeeHour * 3.14 / 180));
    int yHour = (int) (cy + radius * (drgeeHour * 3.14 / 180));
    (xHour, yHour, cx, cy, paint);
    //The length of the minute hand    radius = 45;
    (3);
    ();
    //The angle of the minute hand    int drgeeMin = min * 6 - 90;
    if (drgeeMin < 0) {
      drgeeMin += 360;
    }
    //The x y coordinate of the needle tip    int x1 = (int) (cx + radius * (drgeeMin *  / 180));
    int y1 = (int) (cy + radius * (drgeeMin *  / 180));
    (x1, y1, cx, cy, paint);
    return deskClock;
  }
}

Time Tools

import ;
public class DateUtils {
  public static String getCurrentDay() {
    SimpleDateFormat format = new SimpleDateFormat("dd");
    Long t = new Long(());
    String d = (t);
    return d;
  }
  public static String getCurrentSecond() {
    SimpleDateFormat format = new SimpleDateFormat("ss");
    Long t = new Long(());
    String d = (t);
    return d;
  }
  public static String getCurrentMin() {
    SimpleDateFormat format = new SimpleDateFormat("mm");
    Long t = new Long(());
    String d = (t);
    return d;
  }
  public static String getCurrentHour() {
    SimpleDateFormat format = new SimpleDateFormat("HH");
    Long t = new Long(());
    String d = (t);
    return d;
  }
}

The following is simpler. I am adding listener. I am lazy here. I should create a separate view for the clock and inherit the BubbleTextView.

private void applyIconAndLabel(Bitmap icon, ItemInfo info) {
    /* begin */
    setDeskClockIcon(info);
    /* end */
    applyIcon(icon, info);
    setText();
    if ( != null) {
      setContentDescription(()
          ? getContext().getString(.disabled_app_label, )
          : );
    }
  }
  private void setDeskClockIcon(ItemInfo info) {
    ().setListener(new () {
      @Override
      public void onChange(Bitmap icon, ItemInfo info) {
        applyIcon(icon, info);
      }
    }, info, getContext());
  }
  private void applyIcon(Bitmap icon, ItemInfo info) {
    FastBitmapDrawable iconDrawable = (getContext()).newIcon(icon, info);
    (());
    setIcon(iconDrawable);
  }

Start and pause respectively in onResume() and onPause()

@Override  protected void onResume() {
   ......
    /* begin */
    ().onResume(this);
    /* end */
    if (mLauncherCallbacks != null) {
      ();
    }
  }

@Override
  protected void onPause() {
    // Ensure that items added to Launcher are queued until Launcher returns
    (InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED);
    ();
    mPaused = true;
    ();
    ();
    // We call onHide() aggressively. The custom content callbacks should be able to
    // debounce excess onHide calls.
    if (() != null) {
      ().onHide();
    }
    if (mLauncherCallbacks != null) {
      ();
    }
    /* begin */
    ().onPause();
    /* end */
  }

This is fine. If you want to add a second hand, just draw the second hand in IconUtil.
There are also dynamic icons for calendars that can be implemented in the same way

Summarize

The above is the Android 8.1 Launcher3 that the editor introduced to you to realize the dynamic pointer clock function. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support for my website!