/// <summary> /// Called to draw the watch face /// </summary> /// <param name="canvas"></param> /// <param name="bounds"></param> public override void OnDraw(Canvas canvas, Rect bounds) { _calendar = Calendar.GetInstance(Locale.Default); // Determine the bounds of the drawing surface: var width = bounds.Width(); var height = bounds.Height(); // Determine the center of the drawing surface: var centerX = width / 2.0f; var centerY = height / 2.0f; // set a default background color canvas.DrawColor(Color.Black); // draw the face ticks (if not in ambient mode) if (!IsInAmbientMode) { // Draw the hour ticks: var hticks = new WatchTicks(centerX, centerY, 25, 5, -5) { TickPaint = hTickPaint }; hticks.DrawTicks(canvas, 12); // draw 12 of them. // Draw the minute ticks: var mticks = new WatchTicks(centerX, centerY, 10, 3, -10) { TickPaint = mTickPaint }; mticks.DrawTicks(canvas, 60, 5); // draw 60 of them, but skip every 5th one [60/12 = 5] } var inspectTimerTickRate = _updateRate; // draw the background (scaled to fit) along with Ticks (if not in ambient mode) if (!IsInAmbientMode) { if (backgroundScaledBitmap == null || backgroundScaledBitmap.Width != width || backgroundScaledBitmap.Height != height) { backgroundScaledBitmap = Bitmap.CreateScaledBitmap(backgroundBitmap, width, height, true /* filter */); } canvas.DrawBitmap(backgroundScaledBitmap, 0, 0, null); } else { // AOD if (aodBackgroundScaledBitmap == null || aodBackgroundScaledBitmap.Width != width || aodBackgroundScaledBitmap.Height != height) { aodBackgroundScaledBitmap = Bitmap.CreateScaledBitmap(aodBackgroundBitmap, width, height, true /* filter */); } // half-alpha canvas.DrawBitmap(aodBackgroundScaledBitmap, 0, 0, new Paint() { Alpha = MUTE_ALPHA }); } // draw something with the date (change the color based on AOD) var str = DateTime.Now.ToString("ddd, dd MMM"); var textPaint = new Paint { Alpha = NORMAL_ALPHA, AntiAlias = true, Color = ShouldTimerBeRunning() ? Color.White : Color.Silver, // (change the color based on AOD) TextSize = centerY / 10.0f }; var tf = Typeface.Create("Arial", TypefaceStyle.Bold); textPaint.SetTypeface(tf); // textPaint.SetShadowLayer(1.5f, -1f, -1f, Color.Argb(MUTE_ALPHA, 50, 50, 50)); var dl = new Coords(centerX - 40, centerY + 40); canvas.DrawText(str, dl.X, dl.Y, textPaint); // // draw a central hub //var bhW = (int)(width / 4.0f); //var bhH = (int)(height / 4.0f); //var bhX = centerX - bhW / 2.0f; //var bhY = centerY - bhH / 2.0f; //if (hubScaledBitmap == null) // hubScaledBitmap = Bitmap.CreateScaledBitmap(hubBitmap, bhW, bhH, true /* filter */); //canvas.DrawBitmap(hubScaledBitmap, bhX, bhY, null); var secLength = 40; var minLength = 30; var hrLength = 20; if (!IsInAmbientMode) { //// draw the millisecond tick hand - have to include padding (from outside edge, as neg. in pixels) //var milLength = 10; //var milPad = -10; //milHand = new WatchHand(HandType.MILLISECONDS, HandStyle.OUTSIDE, centerX, centerY, milLength, // milPad) //{ paint = secondPaint }; //milHand.DrawHand(canvas, _calendar); // Draw the second hand only in interactive mode: secHand = new WatchHand(HandType.SECONDS, HandStyle.OUTSIDE, centerX, centerY, (int)secLength, -30) { Paint = secondPaint }; secHand.DrawHand(canvas, _calendar); // Draw the minute hand: minHand = new WatchHand(HandType.MINUTES, HandStyle.OUTSIDE, centerX, centerY, (int)minLength, -30) { Paint = minutePaint }; minHand.DrawHand(canvas, _calendar); // Draw the hour hand: hrHand = new WatchHand(HandType.HOURS, HandStyle.OUTSIDE, centerX, centerY, (int)hrLength, -30) { Paint = hourPaint }; hrHand.DrawHand(canvas, _calendar); } else { // Draw the outline minute hand: var outerMinP = WatchFaceFactory.GetMinuteHand(Color.White, false); outerMinP.StrokeWidth = minutePaint.StrokeWidth + 4; minHand = new WatchHand(HandType.MINUTES, HandStyle.CENTRIC, centerX, centerY, (int)minLength) { Paint = outerMinP }; minHand.DrawHand(canvas, _calendar); // Draw the outline hour hand: var outerHourP = WatchFaceFactory.GetMinuteHand(Color.White, false); outerHourP.StrokeWidth = hourPaint.StrokeWidth + 4; hrHand = new WatchHand(HandType.HOURS, HandStyle.CENTRIC, centerX, centerY, (int)hrLength) { Paint = outerHourP }; hrHand.DrawHand(canvas, _calendar); // Draw the minute hand: var innerMinPaint = WatchFaceFactory.GetMinuteHand(Color.Black, false); minHand = new WatchHand(HandType.MINUTES, HandStyle.CENTRIC, centerX, centerY, (int)minLength) { Paint = innerMinPaint }; minHand.DrawHand(canvas, _calendar); // Draw the hour hand: var innerHourP = WatchFaceFactory.GetHourHand(Color.Black, false); hrHand = new WatchHand(HandType.HOURS, HandStyle.CENTRIC, centerX, centerY, (int)hrLength) { Paint = innerHourP }; hrHand.DrawHand(canvas, _calendar); } }
/// <summary> /// Called to draw the watch face /// To achieve a high frame rate, which results in smooth animations, no intense computations should happen in onDraw /// </summary> /// <param name="canvas"></param> /// <param name="bounds"></param> public override void OnDraw(Canvas canvas, Rect bounds) { // refresh calendar _calendar = Java.Util.Calendar.GetInstance(Java.Util.TimeZone.Default); // check the time to see how long this drawing is going to take long frameStartTimeMs = SystemClock.ElapsedRealtime(); // Determine the bounds of the drawing surface: var width = bounds.Width(); var height = bounds.Height(); // Determine the center of the drawing surface: _centerX = width / 2.0f; _centerY = height / 2.0f; // set a default background color canvas.DrawColor(Color.Black); // canvas.DrawBitmap(_backgroundScaledBitmap, 0, 0, _facePaint); // draw the face ticks (if not in ambient mode) _facePaint.Alpha = IsInAmbientMode ? 100 : 255; var bgToDraw = IsInAmbientMode ? _aodBackgroundScaledBitmap : _backgroundScaledBitmap; canvas.DrawBitmap(bgToDraw, 0, 0, _facePaint); if (!IsInAmbientMode) { // Draw the hour ticks: var hticks = new WatchTicks(_centerX, _centerY, 20, 5, -1) { TickPaint = _tickPaint }; hticks.DrawTicks(canvas, 12); // draw 12 of them. // Draw the minute ticks: var mticks = new WatchTicks(_centerX, _centerY, 10, 3, -10) { TickPaint = _minuteTickPaint }; mticks.DrawTicks(canvas, 60, 5); // draw 60 of them, but skip every 5th one [60/12 = 5] } // draw something with the date (change the color based on AOD) var dt = _dateTimeAdapter.Now.Date; var str = dt.ToString("ddd, dd MMM"); // TUES, 08 APR _datePaint.Color = ShouldTimerBeRunning() ? Color.Black : Color.Silver; // (change the color based on AOD) _datePaint.TextSize = _centerY / 10.0f; var tf = Typeface.Create("Arial", TypefaceStyle.Bold); _datePaint.SetTypeface(tf); _datePaint.SetShadowLayer(1.5f, -1f, -1f, Color.Argb(100, 50, 50, 50)); var dateLocation = new Coords(_centerX * 1.10f, _centerY * 1.25f); canvas.DrawText(str, dateLocation.X, dateLocation.Y, _datePaint); // draw a central hub (bullet hole?) var bhW = (int)(width / 4.0f); var bhH = (int)(height / 4.0f); var bhX = _centerX - bhW / 2.0f; var bhY = _centerY - bhH / 2.0f; if (_hubScaledBitmap == null) { _hubScaledBitmap = Bitmap.CreateScaledBitmap(_hubBitmap, bhW, bhH, true /* filter */); } canvas.DrawBitmap(_hubScaledBitmap, bhX, bhY, null); // set these lengths in the OnSurfaceChanged //var minLength = centerX - 40; //var hrLength = centerX - 80; if (!IsInAmbientMode) { // Draw the second hand only in interactive mode: _secHand = new WatchHand(HandType.SECONDS, HandStyle.CENTRIC, _centerX, _centerY, (int)_secLength) { paint = _secondPaint }; _secHand.DrawHand(canvas, _calendar); // draw the millisecond tick hand - have to include padding (from outside edge, as neg. in pixels) var milLength = 10; var milPad = -10; _milHand = new WatchHand(HandType.MILLISECONDS, HandStyle.OUTSIDE, _centerX, _centerY, milLength, milPad) { paint = _secondPaint }; _milHand.DrawHand(canvas, _calendar); // Draw the minute hand: _minHand = new WatchHand(HandType.MINUTES, HandStyle.CENTRIC, _centerX, _centerY, (int)_minLength) { paint = _minutePaint }; _minHand.DrawHand(canvas, _calendar, HAND_END_CAP_RADIUS); // Draw the hour hand: _hrHand = new WatchHand(HandType.HOURS, HandStyle.CENTRIC, _centerX, _centerY, (int)_hrLength) { paint = _hourPaint }; _hrHand.DrawHand(canvas, _calendar); } else { // Draw the outline minute hand: var outerMinP = WatchFaceFactory.GetMinuteHand(Color.White, false); outerMinP.StrokeWidth = _minutePaint.StrokeWidth + 4; _minHand = new WatchHand(HandType.MINUTES, HandStyle.CENTRIC, _centerX, _centerY, (int)_minLength) { paint = outerMinP }; _minHand.DrawHand(canvas, _calendar); // Draw the outline hour hand: var outerHourP = WatchFaceFactory.GetMinuteHand(Color.White, false); outerHourP.StrokeWidth = _hourPaint.StrokeWidth + 4; _hrHand = new WatchHand(HandType.HOURS, HandStyle.CENTRIC, _centerX, _centerY, (int)_hrLength) { paint = outerHourP }; _hrHand.DrawHand(canvas, _calendar); // Draw the minute hand: var innerMinPaint = WatchFaceFactory.GetMinuteHand(Color.Black, false); _minHand = new WatchHand(HandType.MINUTES, HandStyle.CENTRIC, _centerX, _centerY, (int)_minLength) { paint = innerMinPaint }; _minHand.DrawHand(canvas, _calendar); // Draw the hour hand: var innerHourP = WatchFaceFactory.GetHourHand(Color.Black, false); _hrHand = new WatchHand(HandType.HOURS, HandStyle.CENTRIC, _centerX, _centerY, (int)_hrLength) { paint = innerHourP }; _hrHand.DrawHand(canvas, _calendar); } // kick off the timer again... maybe if (ShouldTimerBeRunning()) { // recheck the time, and if drawing is taking too long, skip the next tick long delayMs = SystemClock.ElapsedRealtime() - frameStartTimeMs; if (delayMs > INTERACTIVE_UPDATE_RATE_MS) { // This scenario occurs when drawing all of the components takes longer than an actual frame. // It may be helpful to log how many times this happens, so you can fix it when it occurs. if (Log.IsLoggable(Tag, LogPriority.Warn)) { Log.Warn(Tag, "OnDraw: long running draw (delayMs=" + delayMs + " > updateRateMs=" + INTERACTIVE_UPDATE_RATE_MS + ")"); } // In general, you don't want to redraw immediately, but on the next appropriate frame (else block below). delayMs = 0; } else { // Sets the delay as close as possible to the intended framerate. // Note that the recommended interactive update rate is 1 frame per second. // However, if you want to include the sweeping hand gesture, set the // interactive update rate up to 30 frames per second. delayMs = INTERACTIVE_UPDATE_RATE_MS - delayMs; } _mUpdateTimeHandler.SendEmptyMessageDelayed(MSG_UPDATE_TIME, delayMs); } }