@Override protected boolean drawBubble(Canvas canvas) { if (messageLayout == null) { requestLayout(); return false; } boolean isAnimated = false; if (messageLayout.isForwarded) { canvas.drawText("Forwarded message", 0, getPx(16), messageLayout.forwardingPaint); canvas.drawText("From", 0, getPx(35), messageLayout.forwardingPaint); canvas.drawText( messageLayout.forwarderNameMeasured, messageLayout.forwardOffset, getPx(35), messageLayout.senderPaint); canvas.save(); canvas.translate(0, getPx(19) * 2); messageLayout.layout.draw(canvas); canvas.restore(); } else { if (!messageLayout.isOut & messageLayout.isGroup) { canvas.drawText(messageLayout.senderNameMeasured, 0, getPx(16), messageLayout.senderPaint); canvas.save(); canvas.translate(0, getPx(19)); messageLayout.layout.draw(canvas); canvas.restore(); } else { messageLayout.layout.draw(canvas); } } if (messageLayout.showState) { if (state == MessageState.PENDING) { canvas.save(); canvas.translate( messageLayout.layoutRealWidth - getPx(12), messageLayout.layoutHeight - getPx(12) - getPx(3)); canvas.drawCircle(getPx(6), getPx(6), getPx(6), clockIconPaint); double time = (System.currentTimeMillis() / 15.0) % (12 * 60); double angle = (time / (6 * 60)) * Math.PI; int x = (int) (Math.sin(-angle) * getPx(4)); int y = (int) (Math.cos(-angle) * getPx(4)); canvas.drawLine(getPx(6), getPx(6), getPx(6) + x, getPx(6) + y, clockIconPaint); x = (int) (Math.sin(-angle * 12) * getPx(5)); y = (int) (Math.cos(-angle * 12) * getPx(5)); canvas.drawLine(getPx(6), getPx(6), getPx(6) + x, getPx(6) + y, clockIconPaint); canvas.restore(); clockOutPaint.setColor(COLOR_NORMAL); isAnimated = true; } else if (state == MessageState.READED && prevState == MessageState.SENT && (SystemClock.uptimeMillis() - stateChangeTime < STATE_ANIMATION_TIME)) { long animationTime = SystemClock.uptimeMillis() - stateChangeTime; float progress = easeStateFade(animationTime / (float) STATE_ANIMATION_TIME); int offset = (int) (getPx(5) * progress); int alphaNew = (int) (progress * 255); bounds( stateSent, messageLayout.layoutRealWidth - stateSent.getIntrinsicWidth() - offset, messageLayout.layoutHeight - stateSent.getIntrinsicHeight() - getPx(3)); stateSent.setAlpha(255); stateSent.draw(canvas); bounds( stateHalfCheck, messageLayout.layoutRealWidth - stateHalfCheck.getIntrinsicWidth() + getPx(5) - offset, messageLayout.layoutHeight - stateHalfCheck.getIntrinsicHeight() - getPx(3)); stateHalfCheck.setAlpha(alphaNew); stateHalfCheck.draw(canvas); clockOutPaint.setColor(COLOR_NORMAL); isAnimated = true; } else { Drawable stateDrawable = getStateDrawable(state); bounds( stateDrawable, messageLayout.layoutRealWidth - stateDrawable.getIntrinsicWidth(), messageLayout.layoutHeight - stateDrawable.getIntrinsicHeight() - getPx(3)); stateDrawable.setAlpha(255); stateDrawable.draw(canvas); if (state == MessageState.READED) { bounds( stateSent, messageLayout.layoutRealWidth - stateSent.getIntrinsicWidth() - getPx(5), messageLayout.layoutHeight - stateDrawable.getIntrinsicHeight() - getPx(3)); stateSent.setAlpha(255); stateSent.draw(canvas); } if (state == MessageState.FAILURE) { clockOutPaint.setColor(COLOR_ERROR); } else { clockOutPaint.setColor(COLOR_NORMAL); } } } else { clockOutPaint.setColor(COLOR_IN); } canvas.drawText( wireframe.date, messageLayout.layoutRealWidth - messageLayout.timeWidth + getPx(6), messageLayout.layoutHeight - getPx(4), clockOutPaint); return isAnimated; }
@Override protected void onDraw(Canvas canvas) { if (layout == null) { requestLayout(); return; } if (description == null) { return; } if (needNewUpdateTyping) { updateTyping(); } if (layout.isEncrypted) { bounds(secureIcon, layout.layoutEncryptedLeft, layout.layoutEncryptedTop); secureIcon.draw(canvas); } if (layout.titleLayout != null) { canvas.save(); canvas.translate(layout.layoutTitleLeft, layout.layoutTitleLayoutTop); layout.titleLayout.draw(canvas); canvas.restore(); } else if (layout.titleString != null) { TextPaint paint = layout.isEncrypted ? titleEncryptedPaint : (layout.isHighlighted ? titleHighlightPaint : titlePaint); canvas.drawText(layout.titleString, layout.layoutTitleLeft, layout.layoutTitleTop, paint); } if (state != MessageState.FAILURE && description.getSenderId() == currentUserUid) { switch (state) { default: case MessageState.PENDING: bound(statePending, layout.layoutClockLeft, layout.layoutClockTop); statePending.draw(canvas); break; case MessageState.SENT: bound(stateSent, layout.layoutStateLeft, layout.layoutStateTop); stateSent.draw(canvas); break; case MessageState.READED: bound(stateSent, layout.layoutStateLeftDouble, layout.layoutStateTop); stateSent.draw(canvas); bound(stateHalfCheck, layout.layoutStateLeft, layout.layoutStateTop); stateHalfCheck.draw(canvas); break; } } TextPaint timePaint = HIGHLIGHT_UNDEAD ? (layout.isUnreadIn ? unreadClockPaint : readClockPaint) : readClockPaint; canvas.drawText(layout.time, layout.layoutTimeLeft, layout.layoutTimeTop, timePaint); if (typingLayout != null) { canvas.save(); canvas.translate(layout.layoutMainLeft, layout.layoutMainContentTop); typingLayout.draw(canvas); canvas.restore(); } else if (layout.bodyLayout != null) { canvas.save(); canvas.translate(layout.layoutMainLeft, layout.layoutMainContentTop); layout.bodyLayout.draw(canvas); canvas.restore(); } else if (layout.bodyString != null) { // canvas.save(); // canvas.translate(layout.layoutMainLeft, layout.layoutMainTop); // layout.bodyLayout.draw(canvas); // canvas.restore(); canvas.drawText(layout.bodyString, layout.layoutMainLeft, layout.layoutMainTop, bodyPaint); } if (avatarHolder != null) { long time = SystemClock.uptimeMillis() - avatarAppearTime; if (time > AVATAR_FADE_TIME || !AVATAR_FADE) { avatarPaint.setAlpha(255); canvas.drawBitmap( avatarHolder.getBitmap(), layout.layoutAvatarLeft, layout.layoutAvatarTop, avatarPaint); } else { drawPlaceHolder(canvas); float alpha = time / (float) AVATAR_FADE_TIME; avatarPaint.setAlpha((int) (255 * alpha)); canvas.drawBitmap( avatarHolder.getBitmap(), layout.layoutAvatarLeft, layout.layoutAvatarTop, avatarPaint); inavalidateForAnimation(); } } else { drawPlaceHolder(canvas); } if (description.isErrorState() || (state == MessageState.FAILURE && description.getSenderId() == currentUserUid)) { bound(stateFailure, layout.layoutMarkLeft, layout.layoutMarkTop); stateFailure.draw(canvas); } else if (description.getUnreadCount() > 0) { canvas.drawRoundRect( layout.layoutMarkRect, layout.layoutMarkRadius, layout.layoutMarkRadius, counterPaint); canvas.drawText( layout.unreadCountText, layout.layoutMarkLeft + layout.layoutMarkTextLeft, layout.layoutMarkTextTop, counterTitlePaint); } }