Example usage for android.graphics Canvas drawRoundRect

List of usage examples for android.graphics Canvas drawRoundRect

Introduction

In this page you can find the example usage for android.graphics Canvas drawRoundRect.

Prototype

public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) 

Source Link

Document

Draw the specified round-rect using the specified paint.

Usage

From source file:com.leeon.blank.widget.RangeBarNew.java

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    final int length = mTextArray.length;

    /*** Draw text marks ***/
    mPaint.setTextSize(mTextSize);//  www .j a  v a2s  .  c  o m
    mPaint.setColor(mTextColorNormal);
    for (int i = 0; i < length; i++) {
        final String text2draw = mTextArray[i] == -1 ? "" : mTextArray[i] + "";
        final float textWidth = mTextWidthArray[i];
        float textDrawLeft;
        // The last text mark's draw location should be adjust.
        if (i == length - 1) {
            textDrawLeft = mRangeBarRect.right - textWidth / 2;
        } else {
            textDrawLeft = mRangeBarRect.left + i * mPartLength - textWidth / 2;
        }
        canvas.drawText(text2draw, textDrawLeft, mRangeBarRect.top - 24 - mMarginBetween, mPaint);

        //draw lines
        float lineDrawLeft = mRangeBarRect.left + i * mPartLength;
        canvas.drawLine(lineDrawLeft, mRangeBarRect.top, lineDrawLeft, mRangeBarRect.top - 24, mPaint);

        //draw short lines
        if (i != length - 1) {
            for (int j = 1; j < 5; j++) {
                float lineDrawLeft_short = lineDrawLeft + j * mTinyPartLength;
                canvas.drawLine(lineDrawLeft_short, mRangeBarRect.top, lineDrawLeft_short,
                        mRangeBarRect.top - 18, mPaint);
            }
        }
    }

    /*** Draw seekBar ***/
    final float radius = mRangeBarHeight / 4f;
    mRangeBarRectSelected.left = mRangeBarRect.left + mTinyPartLength * mLeftCursorIndex;
    mRangeBarRectSelected.right = mRangeBarRect.left + mTinyPartLength * mRightCursorIndex;
    // If whole of seekbar is selected, just draw seekbar with selectedcolor.
    if (mLeftCursorIndex == 0 && mRightCursorIndex == (length - 1) * 5) {
        mPaint.setColor(mRangeBarColorSelected);
        canvas.drawRoundRect(mRangeBarRect, radius, radius, mPaint);
    } else {
        // Draw background first.
        mPaint.setColor(mRangeBarColorNormal);
        canvas.drawRoundRect(mRangeBarRect, radius, radius, mPaint);

        // Draw selected part.
        mPaint.setColor(mRangeBarColorSelected);
        // Can draw rounded rectangle, but original rectangle is enough.
        // Because edges of selected part will be covered by cursors.
        canvas.drawRect(mRangeBarRectSelected, mPaint);
    }

    /*** Draw cursors ***/
    // left cursor first
    final int leftWidth = mLeftCursorBG.getIntrinsicWidth();
    final int leftHeight = mLeftCursorBG.getIntrinsicHeight();
    final int leftLeft = (int) (mRangeBarRectSelected.left - leftWidth / 2f);
    final int leftTop = (int) (mRangeBarRect.bottom + mMarginBetween);
    mLeftCursorRect.left = leftLeft;
    mLeftCursorRect.top = leftTop;
    mLeftCursorRect.right = leftLeft + leftWidth;
    mLeftCursorRect.bottom = leftTop + leftHeight;
    mLeftCursorBG.setBounds(mLeftCursorRect);
    mLeftCursorBG.draw(canvas);

    // right cursor second
    final int rightWidth = mRightCursorBG.getIntrinsicWidth();
    final int rightHeight = mRightCursorBG.getIntrinsicHeight();
    final int rightLeft = (int) (mRangeBarRectSelected.right - rightWidth / 2f);
    final int rightTop = (int) (mRangeBarRect.bottom + mMarginBetween);
    mRightCursorRect.left = rightLeft;
    mRightCursorRect.top = rightTop;
    mRightCursorRect.right = rightLeft + rightWidth;
    mRightCursorRect.bottom = rightTop + rightHeight;
    mRightCursorBG.setBounds(mRightCursorRect);
    mRightCursorBG.draw(canvas);

    //Draw indicators
    final int indicatorWidth = Math.max(indicatorDrawable.getIntrinsicWidth(), (int) mPaint.measureText("888"));
    if (mLeftHit && mLeftPointerID != -1) {
        final int indicatorLeft = (int) (mRangeBarRectSelected.left - (float) indicatorWidth / 2);
        final int indicatorTop = mPaddingRect.top;
        mLeftIndicatorRect.left = indicatorLeft;
        mLeftIndicatorRect.top = indicatorTop;
        mLeftIndicatorRect.right = indicatorLeft + indicatorWidth;
        mLeftIndicatorRect.bottom = indicatorTop + indicatorHeight;
        indicatorDrawable.setBounds(mLeftIndicatorRect);
        indicatorDrawable.draw(canvas);
        mPaint.setColor(Color.WHITE);
        mValueLeft = getValueByIndex(mLeftCursorIndex);
        canvas.drawText(mValueLeft + "", mLeftIndicatorRect.centerX() - mPaint.measureText(mValueLeft + "") / 2,
                mLeftIndicatorRect.centerY() + mTextSize / 4, mPaint);
    }

    if (mRightHit && mRightPointerID != -1) {
        final int indicatorRightLeft = (int) (mRangeBarRectSelected.right - (float) rightWidth / 2);
        final int indicatorRightTop = mPaddingRect.top;
        mRightIndicatorRect.left = indicatorRightLeft;
        mRightIndicatorRect.top = indicatorRightTop;
        mRightIndicatorRect.right = indicatorRightLeft + indicatorWidth;
        mRightIndicatorRect.bottom = indicatorRightTop + indicatorHeight;
        indicatorDrawable.setBounds(mRightIndicatorRect);
        indicatorDrawable.draw(canvas);
        mPaint.setColor(Color.WHITE);
        mValueRight = getValueByIndex(mRightCursorIndex);
        if (mValueRight == -1) {
            canvas.drawText("", mRightIndicatorRect.centerX() - mPaint.measureText("") / 2,
                    mRightIndicatorRect.centerY() + mTextSize / 4, mPaint);
        } else {
            canvas.drawText(mValueRight + "",
                    mRightIndicatorRect.centerX() - mPaint.measureText(mValueRight + "") / 2,
                    mRightIndicatorRect.centerY() + mTextSize / 4, mPaint);
        }
    }

    triggerCallback();
}

From source file:com.lovejjfg.blogdemo.ui.indicator.RectPageIndicator.java

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (mViewPager == null) {
        return;//from ww w.  j  a va2  s.  co  m
    }
    final int count = mViewPager.getAdapter().getCount();
    if (count == 0) {
        return;
    }

    if (mCurrentPage >= count) {
        setCurrentItem(count - 1);
        return;
    }

    int longSize;
    int longPaddingBefore;
    int longPaddingAfter;
    int shortPaddingBefore;
    if (mOrientation == HORIZONTAL) {
        longSize = getWidth();
        longPaddingBefore = getPaddingLeft();
        longPaddingAfter = getPaddingRight();
        shortPaddingBefore = getPaddingTop();
    } else {
        longSize = getHeight();
        longPaddingBefore = getPaddingTop();
        longPaddingAfter = getPaddingBottom();
        shortPaddingBefore = getPaddingLeft();
    }

    final float mHalfRectWidth = mRectWidth / 2.0f;
    final float rectOffset = mRectWidth * mRadiusRatio;
    final float shortOffset = shortPaddingBefore + mHalfRectWidth;
    float longOffset = longPaddingBefore + mHalfRectWidth;
    if (mCentered) {
        longOffset += (longSize - longPaddingBefore - longPaddingAfter - (count * mRectWidth)
                - (count - 1) * rectOffset) / 2.0f;
    }

    float dX;
    float dY;

    float pageFillRadius = mHalfRectWidth;
    if (mPaintStroke.getStrokeWidth() > 0) {
        pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f;
    }

    //Draw stroked circles
    for (int iLoop = 0; iLoop < count; iLoop++) {
        float drawLong = longOffset + (iLoop * (mRectWidth + rectOffset));
        if (mOrientation == HORIZONTAL) {
            dX = drawLong;
            dY = shortOffset;
        } else {
            dX = shortOffset;
            dY = drawLong;
        }
        RectF rectF = new RectF(dX - pageFillRadius, dY - pageFillRadius, dX + pageFillRadius,
                dY + pageFillRadius);
        // Only paint fill if not completely transparent
        if (mPaintPageFill.getAlpha() > 0) {
            //                canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill);
            canvas.drawRoundRect(rectF, 2, 2, mPaintPageFill);
        }

        // Only paint stroke if a stroke width was non-zero
        if (pageFillRadius != mHalfRectWidth) {
            rectF.intersect(dX - mHalfRectWidth, dY - mHalfRectWidth, dX + mHalfRectWidth, dY + mHalfRectWidth);
            canvas.drawRoundRect(rectF, 2, 2, mPaintPageFill);
        }
    }

    //Draw the filled circle according to the current scroll
    float cx = (mSnap ? mSnapPage : mCurrentPage) * (rectOffset + mRectWidth);
    if (!mSnap) {
        cx += mPageOffset * (rectOffset + mRectWidth);
    }
    if (mOrientation == HORIZONTAL) {
        dX = longOffset + cx;
        dY = shortOffset;
    } else {
        dX = shortOffset;
        dY = longOffset + cx;
    }
    RectF rectF = new RectF(dX - mHalfRectWidth, dY - mHalfRectWidth, dX + mHalfRectWidth, dY + mHalfRectWidth);
    canvas.drawRoundRect(rectF, 2, 2, mPaintFill);
}

From source file:com.android.mms.ui.MessageUtils.java

public static Bitmap getCircularBitmap(Bitmap bitmap) {
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final int color = 0xff424242;
    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
    final RectF rectF = new RectF(rect);
    final float roundPx = bitmap.getWidth() / 2;

    paint.setAntiAlias(true);/*from   ww w .j  av a 2  s .c om*/
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, paint);
    return output;
}

From source file:com.google.android.apps.forscience.whistlepunk.RunReviewOverlay.java

/**
 * Draw a flag above a specific timestamp with a given value, but make sure the flag starts
 * after the given flagXToDrawAfter or that the flag is raised up to avoid intersecting it.
 * @param canvas The canvas to use/*from   ww w  .ja va2  s  .c  om*/
 * @param pointData The point data to use
 * @param flagMeasurements This set of measurements will be updated in-place to hold the bounds
 *                         of the flag.
 * @param flagXToDrawAfter The x position past which the flag may not draw. If the flag needs
 *                       this space, it must draw itself higher.
 */
private void drawFlagAfter(Canvas canvas, OverlayPointData pointData, FlagMeasurements flagMeasurements,
        float flagXToDrawAfter, boolean drawStem) {
    if (pointData.label == null) {
        pointData.label = "";
    }
    float labelWidth = mTextPaint.measureText(pointData.label);
    String timeLabel = mTimeFormat.formatToTenths(pointData.timestamp - mExternalAxis.getRecordingStartTime());
    float timeWidth = mTimePaint.measureText(timeLabel);

    // Ascent returns the distance above (negative) the baseline (ascent). Since it is negative,
    // negate it again to get the text height.
    float textSize = -1 * mTextPaint.ascent();

    flagMeasurements.boxTop = mHeight - mChartHeight - mPaddingBottom - textSize;
    flagMeasurements.boxBottom = flagMeasurements.boxTop + textSize + mLabelPadding * 2 + 5;
    float width = mIntraLabelPadding + 2 * mLabelPadding + timeWidth + labelWidth;
    // Ideal box layout
    flagMeasurements.boxStart = pointData.screenPoint.x - width / 2;
    flagMeasurements.boxEnd = pointData.screenPoint.x + width / 2;

    // Adjust it if the ideal doesn't work
    boolean isRaised = false;
    if (flagMeasurements.boxStart < flagXToDrawAfter + mCropFlagBufferX) {
        // See if we can simply offset the flag, if it doesn't cause the notch to be drawn
        // off the edge of the flag.
        if (flagXToDrawAfter + mCropFlagBufferX < pointData.screenPoint.x - mNotchHeight * SQRT_2_OVER_2
                - mCornerRadius) {
            flagMeasurements.boxStart = flagXToDrawAfter + mCropFlagBufferX;
            flagMeasurements.boxEnd = flagMeasurements.boxStart + width;
        } else {
            // We need to move the flag up!
            moveUpToAvoid(flagMeasurements, textSize);
            isRaised = true;
        }
    }
    if (flagMeasurements.boxEnd > mWidth) {
        flagMeasurements.boxEnd = mWidth;
        flagMeasurements.boxStart = flagMeasurements.boxEnd - width;
        if (!isRaised && flagXToDrawAfter + mCropFlagBufferX > flagMeasurements.boxStart) {
            // We need to move the flag up!
            moveUpToAvoid(flagMeasurements, textSize);
            isRaised = true;
        }
    }
    flagMeasurements.notchBottom = flagMeasurements.boxBottom + mNotchHeight;

    pointData.labelRect.set(flagMeasurements.boxStart, flagMeasurements.boxTop, flagMeasurements.boxEnd,
            flagMeasurements.boxBottom);
    canvas.drawRoundRect(pointData.labelRect, mCornerRadius, mCornerRadius, mPaint);

    mPath.reset();
    mPath.moveTo((int) (pointData.screenPoint.x - mNotchHeight * SQRT_2_OVER_2), flagMeasurements.boxBottom);
    mPath.lineTo(pointData.screenPoint.x, flagMeasurements.boxBottom + mNotchHeight);
    mPath.lineTo((int) (pointData.screenPoint.x + mNotchHeight * SQRT_2_OVER_2), flagMeasurements.boxBottom);
    canvas.drawPath(mPath, mPaint);

    float textBase = flagMeasurements.boxTop + mLabelPadding + textSize;
    canvas.drawText(timeLabel, flagMeasurements.boxStart + mLabelPadding, textBase, mTimePaint);
    canvas.drawText(pointData.label, flagMeasurements.boxEnd - labelWidth - mLabelPadding, textBase,
            mTextPaint);

    float center = flagMeasurements.boxStart + mLabelPadding + timeWidth + mIntraLabelPadding / 2;
    canvas.drawLine(center, flagMeasurements.boxTop + mLabelPadding, center,
            flagMeasurements.boxBottom - mLabelPadding, mCenterLinePaint);

    if (drawStem) {
        // Draws a vertical line to the flag notch from the base.
        // If there is a flag to draw after, does not overlap that flag.
        if (pointData.screenPoint.x < flagXToDrawAfter) {
            canvas.drawLine(pointData.screenPoint.x, mHeight, pointData.screenPoint.x,
                    mFlagMeasurements.boxBottom - 5 + textSize + 3 * mLabelPadding, mCropVerticalLinePaint);
        } else {
            canvas.drawLine(pointData.screenPoint.x, mHeight, pointData.screenPoint.x,
                    mFlagMeasurements.notchBottom - 5, mCropVerticalLinePaint);
        }
    }
}

From source file:cn.oddcloud.www.navigationtabbar.ntb.NavigationTabBar.java

@SuppressWarnings("ConstantConditions")
@Override//from  ww w .j ava2s. c o  m
protected void onDraw(final Canvas canvas) {
    // Get height of NTB with badge on nor
    final int mBadgedHeight = (int) (mBounds.height() + mBadgeMargin);

    // Set main canvas
    if (mBitmap == null || mBitmap.isRecycled()) {
        mBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmap);
    }
    // Set pointer canvas
    if (mPointerBitmap == null || mPointerBitmap.isRecycled()) {
        mPointerBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mPointerCanvas.setBitmap(mPointerBitmap);
    }
    // Set icons canvas
    if (mIconsBitmap == null || mIconsBitmap.isRecycled()) {
        mIconsBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mIconsCanvas.setBitmap(mIconsBitmap);
    }
    // Set titles canvas
    if (mIsTitled) {
        if (mTitlesBitmap == null || mTitlesBitmap.isRecycled()) {
            mTitlesBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
            mTitlesCanvas.setBitmap(mTitlesBitmap);
        }
    } else
        mTitlesBitmap = null;

    // Reset and clear canvases
    mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mPointerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mIconsCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    if (mIsTitled)
        mTitlesCanvas.drawColor(0, PorterDuff.Mode.CLEAR);

    if (mCornersRadius == 0)
        canvas.drawRect(mBgBounds, mBgPaint);
    else
        canvas.drawRoundRect(mBgBounds, mCornersRadius, mCornersRadius, mBgPaint);

    // Get pointer badge margin for gravity
    final float barBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : 0.0F;

    // Draw our model colors
    for (int i = 0; i < mModels.size(); i++) {
        mPaint.setColor(mModels.get(i).getColor());

        if (mIsHorizontalOrientation) {
            final float left = mModelSize * i;
            final float right = left + mModelSize;
            mCanvas.drawRect(left, barBadgeMargin, right, mBounds.height() + barBadgeMargin, mPaint);
        } else {
            final float top = mModelSize * i;
            final float bottom = top + mModelSize;
            mCanvas.drawRect(0.0F, top, mBounds.width(), bottom, mPaint);
        }
    }

    // Set bound of pointer
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, barBadgeMargin, mPointerRightBottom,
                mBounds.height() + barBadgeMargin);
    else
        mPointerBounds.set(0.0F, mPointerLeftTop, mBounds.width(), mPointerRightBottom);

    // Draw pointer for model colors
    if (mCornersRadius == 0)
        mPointerCanvas.drawRect(mPointerBounds, mPaint);
    else
        mPointerCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mPaint);

    // Draw pointer into main canvas
    mCanvas.drawBitmap(mPointerBitmap, 0.0F, 0.0F, mPointerPaint);

    // Set vars for icon when model with title or without
    final float iconMarginTitleHeight = mIconSize + mTitleMargin + mModelTitleSize;

    // Draw model icons
    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Variables to center our icons
        final float leftOffset;
        final float topOffset;
        final float matrixCenterX;
        final float matrixCenterY;

        // Set offset to titles
        final float leftTitleOffset = (mModelSize * i) + (mModelSize * 0.5F);
        final float topTitleOffset = mBounds.height() - (mBounds.height() - iconMarginTitleHeight) * 0.5F;

        if (mIsHorizontalOrientation) {
            leftOffset = (mModelSize * i) + (mModelSize - model.mIcon.getWidth()) * 0.5F;
            topOffset = (mBounds.height() - model.mIcon.getHeight()) * 0.5F;
        } else {
            leftOffset = (mBounds.width() - (float) model.mIcon.getWidth()) * 0.5F;
            topOffset = (mModelSize * i) + (mModelSize - (float) model.mIcon.getHeight()) * 0.5F;
        }

        matrixCenterX = leftOffset + (float) model.mIcon.getWidth() * 0.5F;
        matrixCenterY = topOffset + (float) model.mIcon.getHeight() * 0.5F;

        // Title translate position
        final float titleTranslate = topOffset - model.mIcon.getHeight() * TITLE_MARGIN_SCALE_FRACTION;

        // Translate icon to model center
        model.mIconMatrix.setTranslate(leftOffset,
                (mIsTitled && mTitleMode == TitleMode.ALL) ? titleTranslate : topOffset);

        // Get interpolated fraction for left last and current models
        final float interpolation = mResizeInterpolator.getResizeInterpolation(mFraction, true);
        final float lastInterpolation = mResizeInterpolator.getResizeInterpolation(mFraction, false);

        // Scale value relative to interpolation
        final float matrixScale = model.mActiveIconScaleBy * (mIsScaled ? interpolation : NON_SCALED_FRACTION);
        final float matrixLastScale = model.mActiveIconScaleBy
                * (mIsScaled ? lastInterpolation : (MAX_FRACTION - NON_SCALED_FRACTION));

        // Get title alpha relative to interpolation
        final int titleAlpha = (int) (MAX_ALPHA * interpolation);
        final int titleLastAlpha = MAX_ALPHA - (int) (MAX_ALPHA * lastInterpolation);
        // Get title scale relative to interpolation
        final float titleScale = MAX_FRACTION
                + ((mIsScaled ? interpolation : NON_SCALED_FRACTION) * TITLE_ACTIVE_SCALE_BY);
        final float titleLastScale = mIsScaled
                ? (MAX_FRACTION + TITLE_ACTIVE_SCALE_BY) - (lastInterpolation * TITLE_ACTIVE_SCALE_BY)
                : titleScale;

        mIconPaint.setAlpha(MAX_ALPHA);
        if (model.mSelectedIcon != null)
            mSelectedIconPaint.setAlpha(MAX_ALPHA);

        // Check if we handle models from touch on NTB or from ViewPager
        // There is a strange logic
        // of ViewPager onPageScrolled method, so it is
        if (mIsSetIndexFromTabBar) {
            if (mIndex == i)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (mLastIndex == i)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, titleScale, matrixScale, matrixCenterX,
                        matrixCenterY);
        } else {
            if (i == mIndex + 1)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (i == mIndex)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, titleScale, matrixScale, matrixCenterX,
                        matrixCenterY);
        }

        // Draw original model icon
        if (model.mSelectedIcon == null) {
            if (model.mIcon != null && !model.mIcon.isRecycled())
                mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        } else {
            if (mIconPaint.getAlpha() != MIN_ALPHA && model.mIcon != null && !model.mIcon.isRecycled())
                // Draw original icon when is visible
                mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        }
        // Draw selected icon when exist and visible
        if (mSelectedIconPaint.getAlpha() != MIN_ALPHA && model.mSelectedIcon != null
                && !model.mSelectedIcon.isRecycled())
            mIconsCanvas.drawBitmap(model.mSelectedIcon, model.mIconMatrix, mSelectedIconPaint);

        if (mIsTitled)
            mTitlesCanvas.drawText(isInEditMode() ? PREVIEW_TITLE : model.getTitle(), leftTitleOffset,
                    topTitleOffset, mModelTitlePaint);
    }

    // Reset pointer bounds for icons and titles
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, 0.0F, mPointerRightBottom, mBounds.height());
    if (mCornersRadius == 0) {
        if (mIsTinted)
            mIconsCanvas.drawRect(mPointerBounds, mIconPointerPaint);
        if (mIsTitled)
            mTitlesCanvas.drawRect(mPointerBounds, mIconPointerPaint);
    } else {
        if (mIsTinted)
            mIconsCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);
        if (mIsTitled)
            mTitlesCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);
    }

    // Draw general bitmap
    canvas.drawBitmap(mBitmap, 0.0F, 0.0F, null);
    // Draw icons bitmap on top
    canvas.drawBitmap(mIconsBitmap, 0.0F, barBadgeMargin, null);
    // Draw titles bitmap on top
    if (mIsTitled)
        canvas.drawBitmap(mTitlesBitmap, 0.0F, barBadgeMargin, null);

    // If is not badged, exit
    if (!mIsBadged)
        return;

    // Model badge margin and offset relative to gravity mode
    final float modelBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : mBounds.height();
    final float modelBadgeOffset = mBadgeGravity == BadgeGravity.TOP ? 0.0F : mBounds.height() - mBadgeMargin;

    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Set preview badge title
        if (isInEditMode() || TextUtils.isEmpty(model.getBadgeTitle()))
            model.setBadgeTitle(PREVIEW_BADGE);

        // Set badge title bounds
        mBadgePaint.setTextSize(mBadgeTitleSize * model.mBadgeFraction);
        mBadgePaint.getTextBounds(model.getBadgeTitle(), 0, model.getBadgeTitle().length(), mBadgeBounds);

        // Get horizontal and vertical padding for bg
        final float horizontalPadding = mBadgeTitleSize * BADGE_HORIZONTAL_FRACTION;
        final float verticalPadding = horizontalPadding * BADGE_VERTICAL_FRACTION;

        // Set horizontal badge offset
        final float badgeBoundsHorizontalOffset = (mModelSize * i)
                + (mModelSize * mBadgePosition.mPositionFraction);

        // If is badge title only one char, so create circle else round rect
        final float badgeMargin = mBadgeMargin * model.mBadgeFraction;
        if (model.getBadgeTitle().length() == 1) {
            mBgBadgeBounds.set(badgeBoundsHorizontalOffset - badgeMargin, modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset + badgeMargin, modelBadgeMargin + badgeMargin);
        } else
            mBgBadgeBounds.set(
                    badgeBoundsHorizontalOffset
                            - Math.max(badgeMargin, mBadgeBounds.centerX() + horizontalPadding),
                    modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset
                            + Math.max(badgeMargin, mBadgeBounds.centerX() + horizontalPadding),
                    modelBadgeOffset + (verticalPadding * 2.0F) + mBadgeBounds.height());

        // Set color and alpha for badge bg
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else
            mBadgePaint.setColor(mBadgeBgColor == AUTO_COLOR ? mActiveColor : mBadgeBgColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set corners to round rect for badge bg and draw
        final float cornerRadius = mBgBadgeBounds.height() * 0.5F;
        canvas.drawRoundRect(mBgBadgeBounds, cornerRadius, cornerRadius, mBadgePaint);

        // Set color and alpha for badge title
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else //noinspection ResourceAsColor
            mBadgePaint.setColor(mBadgeTitleColor == AUTO_COLOR ? model.getColor() : mBadgeTitleColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set badge title center position and draw title
        final float badgeHalfHeight = mBadgeBounds.height() * 0.5F;
        float badgeVerticalOffset = (mBgBadgeBounds.height() * 0.5F) + badgeHalfHeight - mBadgeBounds.bottom
                + modelBadgeOffset;
        canvas.drawText(model.getBadgeTitle(), badgeBoundsHorizontalOffset,
                badgeVerticalOffset + mBadgeBounds.height() - (mBadgeBounds.height() * model.mBadgeFraction),
                mBadgePaint);
    }
}

From source file:com.simon.dribbble.widget.navigationbar.NavigationTabBar.java

@SuppressWarnings("ConstantConditions")
@Override/* w  w w.  j  a v  a2 s. c o m*/
protected void onDraw(final Canvas canvas) {
    // Get height of NTB with badge on nor
    final int mBadgedHeight = (int) (mBounds.height() + mBadgeMargin);

    // Set home canvas
    if (mBitmap == null || mBitmap.isRecycled()) {
        mBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmap);
    }
    // Set pointer canvas
    if (mPointerBitmap == null || mPointerBitmap.isRecycled()) {
        mPointerBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mPointerCanvas.setBitmap(mPointerBitmap);
    }
    // Set icons canvas
    if (mIconsBitmap == null || mIconsBitmap.isRecycled()) {
        mIconsBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mIconsCanvas.setBitmap(mIconsBitmap);
    }
    // Set titles canvas
    if (mIsTitled) {
        if (mTitlesBitmap == null || mTitlesBitmap.isRecycled()) {
            mTitlesBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
            mTitlesCanvas.setBitmap(mTitlesBitmap);
        }
    } else
        mTitlesBitmap = null;

    // Reset and clear canvases
    mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mPointerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mIconsCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    if (mIsTitled)
        mTitlesCanvas.drawColor(0, PorterDuff.Mode.CLEAR);

    if (mCornersRadius == 0)
        canvas.drawRect(mBgBounds, mBgPaint);
    else
        canvas.drawRoundRect(mBgBounds, mCornersRadius, mCornersRadius, mBgPaint);

    // Get pointer badge margin for gravity
    final float barBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : 0.0F;

    // Draw our model colors
    for (int i = 0; i < mModels.size(); i++) {
        mPaint.setColor(mModels.get(i).getColor());

        if (mIsHorizontalOrientation) {
            final float left = mModelSize * i;
            final float right = left + mModelSize;
            mCanvas.drawRect(left, barBadgeMargin, right, mBounds.height() + barBadgeMargin, mPaint);
        } else {
            final float top = mModelSize * i;
            final float bottom = top + mModelSize;
            mCanvas.drawRect(0.0F, top, mBounds.width(), bottom, mPaint);
        }
    }

    // Set bound of pointer
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, barBadgeMargin, mPointerRightBottom,
                mBounds.height() + barBadgeMargin);
    else
        mPointerBounds.set(0.0F, mPointerLeftTop, mBounds.width(), mPointerRightBottom);

    // Draw pointer for model colors
    if (mCornersRadius == 0)
        mPointerCanvas.drawRect(mPointerBounds, mPaint);
    else
        mPointerCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mPaint);

    // Draw pointer into home canvas
    mCanvas.drawBitmap(mPointerBitmap, 0.0F, 0.0F, mPointerPaint);

    // Set vars for icon when model with title or without
    final float iconMarginTitleHeight = mIconSize + mTitleMargin + mModelTitleSize;

    // Draw model icons
    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Variables to center our icons
        final float leftOffset;
        final float topOffset;
        final float matrixCenterX;
        final float matrixCenterY;

        // Set offset to titles
        final float leftTitleOffset = (mModelSize * i) + (mModelSize * 0.5F);
        final float topTitleOffset = mBounds.height() - (mBounds.height() - iconMarginTitleHeight) * 0.5F;

        if (mIsHorizontalOrientation) {
            leftOffset = (mModelSize * i) + (mModelSize - model.mIcon.getWidth()) * 0.5F;
            topOffset = (mBounds.height() - model.mIcon.getHeight()) * 0.5F;
        } else {
            leftOffset = (mBounds.width() - (float) model.mIcon.getWidth()) * 0.5F;
            topOffset = (mModelSize * i) + (mModelSize - (float) model.mIcon.getHeight()) * 0.5F;
        }

        matrixCenterX = leftOffset + (float) model.mIcon.getWidth() * 0.5F;
        matrixCenterY = topOffset + (float) model.mIcon.getHeight() * 0.5F;

        // Title translate position
        final float titleTranslate = topOffset - model.mIcon.getHeight() * TITLE_MARGIN_SCALE_FRACTION;

        // Translate icon to model center
        model.mIconMatrix.setTranslate(leftOffset,
                (mIsTitled && mTitleMode == TitleMode.ALL) ? titleTranslate : topOffset);

        // Get interpolated fraction for left last and current models
        final float interpolation = mResizeInterpolator.getResizeInterpolation(mFraction, true);
        final float lastInterpolation = mResizeInterpolator.getResizeInterpolation(mFraction, false);

        // Scale value relative to interpolation
        final float matrixScale = model.mActiveIconScaleBy * (mIsScaled ? interpolation : NON_SCALED_FRACTION);
        final float matrixLastScale = model.mActiveIconScaleBy
                * (mIsScaled ? lastInterpolation : (MAX_FRACTION - NON_SCALED_FRACTION));

        // Get title alpha relative to interpolation
        final int titleAlpha = (int) (MAX_ALPHA * interpolation);
        final int titleLastAlpha = MAX_ALPHA - (int) (MAX_ALPHA * lastInterpolation);
        // Get title scale relative to interpolation
        final float titleScale = MAX_FRACTION
                + ((mIsScaled ? interpolation : NON_SCALED_FRACTION) * TITLE_ACTIVE_SCALE_BY);
        final float titleLastScale = mIsScaled
                ? (MAX_FRACTION + TITLE_ACTIVE_SCALE_BY) - (lastInterpolation * TITLE_ACTIVE_SCALE_BY)
                : titleScale;

        mIconPaint.setAlpha(MAX_ALPHA);
        if (model.mSelectedIcon != null)
            mSelectedIconPaint.setAlpha(MAX_ALPHA);

        // Check if we handle models from touch on NTB or from ViewPager
        // There is a strange logic
        // of ViewPager onPageScrolled method, so it is
        if (mIsSetIndexFromTabBar) {
            if (mIndex == i)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (mLastIndex == i)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, titleScale, matrixScale, matrixCenterX,
                        matrixCenterY);
        } else {
            if (i == mIndex + 1)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (i == mIndex)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, titleScale, matrixScale, matrixCenterX,
                        matrixCenterY);
        }

        // Draw original model icon
        if (model.mSelectedIcon == null) {
            if (model.mIcon != null && !model.mIcon.isRecycled())
                mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        } else {
            if (mIconPaint.getAlpha() != MIN_ALPHA && model.mIcon != null && !model.mIcon.isRecycled())
                // Draw original icon when is visible
                mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        }
        // Draw selected icon when exist and visible
        if (mSelectedIconPaint.getAlpha() != MIN_ALPHA && model.mSelectedIcon != null
                && !model.mSelectedIcon.isRecycled())
            mIconsCanvas.drawBitmap(model.mSelectedIcon, model.mIconMatrix, mSelectedIconPaint);

        if (mIsTitled)
            mTitlesCanvas.drawText(isInEditMode() ? PREVIEW_TITLE : model.getTitle(), leftTitleOffset,
                    topTitleOffset, mModelTitlePaint);
    }

    // Reset pointer bounds for icons and titles
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, 0.0F, mPointerRightBottom, mBounds.height());
    if (mCornersRadius == 0) {
        if (mIsTinted)
            mIconsCanvas.drawRect(mPointerBounds, mIconPointerPaint);
        if (mIsTitled)
            mTitlesCanvas.drawRect(mPointerBounds, mIconPointerPaint);
    } else {
        if (mIsTinted)
            mIconsCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);
        if (mIsTitled)
            mTitlesCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);
    }

    // Draw general bitmap
    canvas.drawBitmap(mBitmap, 0.0F, 0.0F, null);
    // Draw icons bitmap on top
    canvas.drawBitmap(mIconsBitmap, 0.0F, barBadgeMargin, null);
    // Draw titles bitmap on top
    if (mIsTitled)
        canvas.drawBitmap(mTitlesBitmap, 0.0F, barBadgeMargin, null);

    // If is not badged, exit
    if (!mIsBadged)
        return;

    // Model badge margin and offset relative to gravity mode
    final float modelBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : mBounds.height();
    final float modelBadgeOffset = mBadgeGravity == BadgeGravity.TOP ? 0.0F : mBounds.height() - mBadgeMargin;

    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Set preview badge title
        if (isInEditMode() || TextUtils.isEmpty(model.getBadgeTitle()))
            model.setBadgeTitle(PREVIEW_BADGE);

        // Set badge title bounds
        mBadgePaint.setTextSize(mBadgeTitleSize * model.mBadgeFraction);
        mBadgePaint.getTextBounds(model.getBadgeTitle(), 0, model.getBadgeTitle().length(), mBadgeBounds);

        // Get horizontal and vertical padding for bg
        final float horizontalPadding = mBadgeTitleSize * BADGE_HORIZONTAL_FRACTION;
        final float verticalPadding = horizontalPadding * BADGE_VERTICAL_FRACTION;

        // Set horizontal badge offset
        final float badgeBoundsHorizontalOffset = (mModelSize * i)
                + (mModelSize * mBadgePosition.mPositionFraction);

        // If is badge title only one char, so create circle else round rect
        final float badgeMargin = mBadgeMargin * model.mBadgeFraction;
        if (model.getBadgeTitle().length() == 1) {
            mBgBadgeBounds.set(badgeBoundsHorizontalOffset - badgeMargin, modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset + badgeMargin, modelBadgeMargin + badgeMargin);
        } else
            mBgBadgeBounds.set(
                    badgeBoundsHorizontalOffset
                            - Math.max(badgeMargin, mBadgeBounds.centerX() + horizontalPadding),
                    modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset
                            + Math.max(badgeMargin, mBadgeBounds.centerX() + horizontalPadding),
                    modelBadgeOffset + (verticalPadding * 2.0F) + mBadgeBounds.height());

        // Set color and alpha for badge bg
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else
            mBadgePaint.setColor(mBadgeBgColor == AUTO_COLOR ? mActiveColor : mBadgeBgColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set corners to round rect for badge bg and draw
        final float cornerRadius = mBgBadgeBounds.height() * 0.5F;
        canvas.drawRoundRect(mBgBadgeBounds, cornerRadius, cornerRadius, mBadgePaint);

        // Set color and alpha for badge title
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else //noinspection ResourceAsColor
            mBadgePaint.setColor(mBadgeTitleColor == AUTO_COLOR ? model.getColor() : mBadgeTitleColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set badge title center position and draw title
        final float badgeHalfHeight = mBadgeBounds.height() * 0.5F;
        float badgeVerticalOffset = (mBgBadgeBounds.height() * 0.5F) + badgeHalfHeight - mBadgeBounds.bottom
                + modelBadgeOffset;
        canvas.drawText(model.getBadgeTitle(), badgeBoundsHorizontalOffset,
                badgeVerticalOffset + mBadgeBounds.height() - (mBadgeBounds.height() * model.mBadgeFraction),
                mBadgePaint);
    }
}

From source file:devlight.io.library.ntb.NavigationTabBar.java

@SuppressWarnings("ConstantConditions")
@Override/*from w ww .  j a  v a  2  s  .  co m*/
protected void onDraw(final Canvas canvas) {
    // Get height of NTB with badge on nor
    final int mBadgedHeight = (int) (mBounds.height() + mBadgeMargin);

    // Set main canvas
    if (mBitmap == null || mBitmap.isRecycled()) {
        mBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBitmap);
    }
    // Set pointer canvas
    if (mPointerBitmap == null || mPointerBitmap.isRecycled()) {
        mPointerBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mPointerCanvas.setBitmap(mPointerBitmap);
    }
    // Set icons canvas
    if (mIconsBitmap == null || mIconsBitmap.isRecycled()) {
        mIconsBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
        mIconsCanvas.setBitmap(mIconsBitmap);
    }
    // Set titles canvas
    if (mIsTitled) {
        if (mTitlesBitmap == null || mTitlesBitmap.isRecycled()) {
            mTitlesBitmap = Bitmap.createBitmap((int) mBounds.width(), mBadgedHeight, Bitmap.Config.ARGB_8888);
            mTitlesCanvas.setBitmap(mTitlesBitmap);
        }
    } else
        mTitlesBitmap = null;

    // Reset and clear canvases
    mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mPointerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mIconsCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    if (mIsTitled)
        mTitlesCanvas.drawColor(0, PorterDuff.Mode.CLEAR);

    if (mCornersRadius == 0)
        canvas.drawRect(mBgBounds, mBgPaint);
    else
        canvas.drawRoundRect(mBgBounds, mCornersRadius, mCornersRadius, mBgPaint);

    // Get pointer badge margin for gravity
    final float barBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : 0.0F;

    // Draw our model colors
    for (int i = 0; i < mModels.size(); i++) {
        mPaint.setColor(mModels.get(i).getColor());

        if (mIsHorizontalOrientation) {
            final float left = mModelSize * i;
            final float right = left + mModelSize;
            mCanvas.drawRect(left, barBadgeMargin, right, mBounds.height() + barBadgeMargin, mPaint);
        } else {
            final float top = mModelSize * i;
            final float bottom = top + mModelSize;
            mCanvas.drawRect(0.0F, top, mBounds.width(), bottom, mPaint);
        }
    }

    // Set bound of pointer
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, barBadgeMargin, mPointerRightBottom,
                mBounds.height() + barBadgeMargin);
    else
        mPointerBounds.set(0.0F, mPointerLeftTop, mBounds.width(), mPointerRightBottom);

    // Draw pointer for model colors
    if (mCornersRadius == 0)
        mPointerCanvas.drawRect(mPointerBounds, mPaint);
    else
        mPointerCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mPaint);

    // Draw pointer into main canvas
    mCanvas.drawBitmap(mPointerBitmap, 0.0F, 0.0F, mPointerPaint);

    // Set vars for icon when model with title or without
    final float iconMarginTitleHeight = mIconSize + mTitleMargin + mModelTitleSize;

    // Draw model icons
    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Variables to center our icons
        final float leftOffset;
        final float topOffset;
        final float matrixCenterX;
        final float matrixCenterY;

        // Set offset to titles
        final float leftTitleOffset;
        final float topTitleOffset;
        if (mIsHorizontalOrientation) {
            leftOffset = (mModelSize * i) + (mModelSize - model.mIcon.getWidth()) * 0.5F;
            topOffset = (mBounds.height() - model.mIcon.getHeight()) * 0.5F;

            // Set offset to titles
            leftTitleOffset = (mModelSize * i) + (mModelSize * 0.5F);
            topTitleOffset = mBounds.height() - (mBounds.height() - iconMarginTitleHeight) * 0.5F;

        } else {
            leftOffset = (mBounds.width() - (float) model.mIcon.getWidth()) * 0.5F;
            topOffset = (mModelSize * i) + (mModelSize - (float) model.mIcon.getHeight()) * 0.5F;

            // Set offset to titles
            leftTitleOffset = leftOffset + (float) model.mIcon.getWidth() * 0.5F;
            topTitleOffset = topOffset + (model.mIcon.getHeight() + iconMarginTitleHeight) * 0.5f;
        }

        matrixCenterX = leftOffset + (float) model.mIcon.getWidth() * 0.5F;
        matrixCenterY = topOffset + (float) model.mIcon.getHeight() * 0.5F;

        // Title translate position
        final float titleTranslate = topOffset - model.mIcon.getHeight() * TITLE_MARGIN_SCALE_FRACTION;

        // Translate icon to model center
        model.mIconMatrix.setTranslate(leftOffset,
                (mIsTitled && mTitleMode == TitleMode.ALL) ? titleTranslate : topOffset);

        // Get interpolated fraction for left last and current models
        final float interpolation = mResizeInterpolator.getResizeInterpolation(mFraction, true);
        final float lastInterpolation = mResizeInterpolator.getResizeInterpolation(mFraction, false);

        // Scale value relative to interpolation
        final float matrixScale = model.mActiveIconScaleBy * interpolation;
        final float matrixLastScale = model.mActiveIconScaleBy * lastInterpolation;

        // Get title alpha relative to interpolation
        final int titleAlpha = (int) (MAX_ALPHA * interpolation);
        final int titleLastAlpha = MAX_ALPHA - (int) (MAX_ALPHA * lastInterpolation);
        // Get title scale relative to interpolation
        final float titleScale = mIsScaled ? MAX_FRACTION + interpolation * TITLE_ACTIVE_SCALE_BY
                : MAX_FRACTION;
        final float titleLastScale = mIsScaled
                ? (MAX_FRACTION + TITLE_ACTIVE_SCALE_BY) - (lastInterpolation * TITLE_ACTIVE_SCALE_BY)
                : titleScale;

        mIconPaint.setAlpha(MAX_ALPHA);
        if (model.mSelectedIcon != null)
            mSelectedIconPaint.setAlpha(MAX_ALPHA);

        // Check if we handle models from touch on NTB or from ViewPager
        // There is a strange logic
        // of ViewPager onPageScrolled method, so it is
        if (mIsSetIndexFromTabBar) {
            if (mIndex == i)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (mLastIndex == i)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, titleScale, matrixScale, matrixCenterX,
                        matrixCenterY);
        } else {
            if (i == mIndex + 1)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (i == mIndex)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, titleScale, matrixScale, matrixCenterX,
                        matrixCenterY);
        }

        // Draw original model icon
        if (model.mSelectedIcon == null) {
            if (model.mIcon != null && !model.mIcon.isRecycled())
                mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        } else if (mIconPaint.getAlpha() != MIN_ALPHA && model.mIcon != null && !model.mIcon.isRecycled())
            // Draw original icon when is visible
            mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        // Draw selected icon when exist and visible
        if (mSelectedIconPaint.getAlpha() != MIN_ALPHA && model.mSelectedIcon != null
                && !model.mSelectedIcon.isRecycled())
            mIconsCanvas.drawBitmap(model.mSelectedIcon, model.mIconMatrix, mSelectedIconPaint);
        if (mIsTitled)
            mTitlesCanvas.drawText(isInEditMode() ? PREVIEW_TITLE : model.getTitle(), leftTitleOffset,
                    topTitleOffset, mModelTitlePaint);
    }

    // Reset pointer bounds for icons and titles
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, 0.0F, mPointerRightBottom, mBounds.height());
    if (mCornersRadius == 0) {
        if (mIsTinted)
            mIconsCanvas.drawRect(mPointerBounds, mIconPointerPaint);
        if (mIsTitled)
            mTitlesCanvas.drawRect(mPointerBounds, mIconPointerPaint);
    } else {
        if (mIsTinted)
            mIconsCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);
        if (mIsTitled)
            mTitlesCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);
    }

    // Draw general bitmap
    canvas.drawBitmap(mBitmap, 0.0F, 0.0F, null);
    // Draw icons bitmap on top
    canvas.drawBitmap(mIconsBitmap, 0.0F, barBadgeMargin, null);
    // Draw titles bitmap on top
    if (mIsTitled)
        canvas.drawBitmap(mTitlesBitmap, 0.0F, barBadgeMargin, null);

    // If is not badged, exit
    if (!mIsBadged)
        return;

    // Model badge margin and offset relative to gravity mode
    final float modelBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : mBounds.height();
    final float modelBadgeOffset = mBadgeGravity == BadgeGravity.TOP ? 0.0F : mBounds.height() - mBadgeMargin;

    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Set preview badge title
        if (isInEditMode() || TextUtils.isEmpty(model.getBadgeTitle()))
            model.setBadgeTitle(PREVIEW_BADGE);

        // Set badge title bounds
        mBadgePaint.setTextSize(mBadgeTitleSize * model.mBadgeFraction);
        mBadgePaint.getTextBounds(model.getBadgeTitle(), 0, model.getBadgeTitle().length(), mBadgeBounds);

        // Get horizontal and vertical padding for bg
        final float horizontalPadding = mBadgeTitleSize * BADGE_HORIZONTAL_FRACTION;
        final float verticalPadding = horizontalPadding * BADGE_VERTICAL_FRACTION;

        // Set horizontal badge offset
        final float badgeBoundsHorizontalOffset = (mModelSize * i)
                + (mModelSize * mBadgePosition.mPositionFraction);

        // If is badge title only one char, so create circle else round rect
        final float badgeMargin = mBadgeMargin * model.mBadgeFraction;
        if (model.getBadgeTitle().length() == 1) {
            mBgBadgeBounds.set(badgeBoundsHorizontalOffset - badgeMargin, modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset + badgeMargin, modelBadgeMargin + badgeMargin);
        } else
            mBgBadgeBounds.set(
                    badgeBoundsHorizontalOffset
                            - Math.max(badgeMargin, mBadgeBounds.centerX() + horizontalPadding),
                    modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset
                            + Math.max(badgeMargin, mBadgeBounds.centerX() + horizontalPadding),
                    modelBadgeOffset + (verticalPadding * 2.0F) + mBadgeBounds.height());

        // Set color and alpha for badge bg
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else
            mBadgePaint.setColor(mBadgeBgColor == AUTO_COLOR ? mActiveColor : mBadgeBgColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set corners to round rect for badge bg and draw
        final float cornerRadius = mBgBadgeBounds.height() * 0.5F;
        canvas.drawRoundRect(mBgBadgeBounds, cornerRadius, cornerRadius, mBadgePaint);

        // Set color and alpha for badge title
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else //noinspection ResourceAsColor
            mBadgePaint.setColor(mBadgeTitleColor == AUTO_COLOR ? model.getColor() : mBadgeTitleColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set badge title center position and draw title
        final float badgeHalfHeight = mBadgeBounds.height() * 0.5F;
        float badgeVerticalOffset = (mBgBadgeBounds.height() * 0.5F) + badgeHalfHeight - mBadgeBounds.bottom
                + modelBadgeOffset;
        canvas.drawText(model.getBadgeTitle(), badgeBoundsHorizontalOffset,
                badgeVerticalOffset + mBadgeBounds.height() - (mBadgeBounds.height() * model.mBadgeFraction),
                mBadgePaint);
    }
}

From source file:com.pdftron.pdf.tools.Tool.java

public void onDraw(Canvas canvas, android.graphics.Matrix tfm) {
    // Draw page number
    if (mShowPageNum && mPageNumberIndicatorVisible) {
        int width = mPDFView.getWidth();
        int height = mPDFView.getHeight();
        int page_num = mPDFView.getCurrentPage();
        boolean restore = false;
        float yOffset = 0;

        try {/*  w ww  .  j  a v  a  2s . com*/
            // During page sliding, PDFViewCtrl might apply extra transformation
            // matrix to Canvas for animation. However, page number should not
            // move; hence applying the inverse to offset it.
            if (!tfm.isIdentity()) {
                canvas.save();
                restore = true;
                tfm.invert(mTempMtx1);
                canvas.getMatrix(mTempMtx2);
                mTempMtx2.postConcat(mTempMtx1);
                canvas.setMatrix(mTempMtx2);

                // Workaround for bug found in Android > ICS with hardware acceleration turned
                // ON. See http://code.google.com/p/android/issues/detail?id=24517 for more info
                if (Build.VERSION.SDK_INT >= 14
                        /*Build.VERSION_CODES.ICE_CREAM_SANDWICH*/ && mPDFView.isHardwareAccelerated()) {
                    Rect rectangle = new Rect();
                    ((android.app.Activity) mPDFView.getContext()).getWindow().getDecorView()
                            .getWindowVisibleDisplayFrame(rectangle);
                    yOffset = rectangle.top;
                }
            }

            int page_count = mPDFView.getDoc().getPageCount();
            String str = String.format(getStringFromResId(R.string.tools_misc_pagerange), page_num, page_count);

            Rect r = new Rect();
            mPaint4PageNum.getTextBounds(str, 0, str.length(), r);
            float str_width = r.width();
            float str_height = r.height();

            float margin = str_height / 1.5f;
            float left = width - str_width * 1.5f - margin + mPDFView.getScrollX();

            float top = mPDFView.getScrollY() + height - mPageNumPosAdjust - str_height * 3.0f + yOffset;

            float right = left + str_width + margin * 2;
            float bottom = top + str_height + margin * 2;

            mTempPageDrawingRectF.set(left, top, right, bottom);
            mPaint4PageNum.setColor(
                    mPDFView.getContext().getResources().getColor(R.color.tools_pageindicator_background));
            canvas.drawRoundRect(mTempPageDrawingRectF, margin, margin, mPaint4PageNum);

            mPaint4PageNum
                    .setColor(mPDFView.getContext().getResources().getColor(R.color.tools_pageindicator_text));
            left += margin;
            top += str_height / 2 + margin + mPaint4PageNum.descent();

            canvas.drawText(str, left, top - 0.5f, mPaint4PageNum);

        } catch (Exception e) {

        } finally {
            if (restore) {
                canvas.restore();
            }
        }
    }
}

From source file:org.telegram.ui.Components.AudioPlayerAlert.java

public AudioPlayerAlert(final Context context) {
    super(context, true);

    MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
    if (messageObject != null) {
        currentAccount = messageObject.currentAccount;
    } else {/* w w w .j  a  v a  2  s .c  o  m*/
        currentAccount = UserConfig.selectedAccount;
    }

    parentActivity = (LaunchActivity) context;
    noCoverDrawable = context.getResources().getDrawable(R.drawable.nocover).mutate();
    noCoverDrawable.setColorFilter(
            new PorterDuffColorFilter(Theme.getColor(Theme.key_player_placeholder), PorterDuff.Mode.MULTIPLY));

    TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
    NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset);
    NotificationCenter.getInstance(currentAccount).addObserver(this,
            NotificationCenter.messagePlayingPlayStateChanged);
    NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidStart);
    NotificationCenter.getInstance(currentAccount).addObserver(this,
            NotificationCenter.messagePlayingProgressDidChanged);
    NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.musicDidLoad);

    shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate();
    shadowDrawable.setColorFilter(
            new PorterDuffColorFilter(Theme.getColor(Theme.key_player_background), PorterDuff.Mode.MULTIPLY));
    paint.setColor(Theme.getColor(Theme.key_player_placeholderBackground));

    containerView = new FrameLayout(context) {

        private boolean ignoreLayout = false;

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY
                    && placeholderImageView.getTranslationX() == 0) {
                dismiss();
                return true;
            }
            return super.onInterceptTouchEvent(ev);
        }

        @Override
        public boolean onTouchEvent(MotionEvent e) {
            return !isDismissed() && super.onTouchEvent(e);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int height = MeasureSpec.getSize(heightMeasureSpec);
            int contentSize = AndroidUtilities.dp(178) + playlist.size() * AndroidUtilities.dp(56)
                    + backgroundPaddingTop + ActionBar.getCurrentActionBarHeight()
                    + AndroidUtilities.statusBarHeight;
            int padding;
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
            if (searching) {
                padding = AndroidUtilities.dp(178) + ActionBar.getCurrentActionBarHeight()
                        + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
            } else {
                if (contentSize < height) {
                    padding = height - contentSize;
                } else {
                    padding = (contentSize < height ? 0 : height - (height / 5 * 3));
                }
                padding += ActionBar.getCurrentActionBarHeight()
                        + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
            }
            if (listView.getPaddingTop() != padding) {
                ignoreLayout = true;
                listView.setPadding(0, padding, 0, AndroidUtilities.dp(8));
                ignoreLayout = false;
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            inFullSize = getMeasuredHeight() >= height;
            int availableHeight = height - ActionBar.getCurrentActionBarHeight()
                    - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)
                    - AndroidUtilities.dp(120);
            int maxSize = Math.max(availableHeight, getMeasuredWidth());
            thumbMaxX = (getMeasuredWidth() - maxSize) / 2 - AndroidUtilities.dp(17);
            thumbMaxY = AndroidUtilities.dp(19);
            panelEndTranslation = getMeasuredHeight() - playerLayout.getMeasuredHeight();
            thumbMaxScale = maxSize / (float) placeholderImageView.getMeasuredWidth() - 1.0f;

            endTranslation = ActionBar.getCurrentActionBarHeight() + AndroidUtilities.dp(5);
            int scaledHeight = (int) Math
                    .ceil(placeholderImageView.getMeasuredHeight() * (1.0f + thumbMaxScale));
            if (scaledHeight > availableHeight) {
                endTranslation -= (scaledHeight - availableHeight);
            }
        }

        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            int y = actionBar.getMeasuredHeight();
            shadow.layout(shadow.getLeft(), y, shadow.getRight(), y + shadow.getMeasuredHeight());
            updateLayout();

            setFullAnimationProgress(fullAnimationProgress);
        }

        @Override
        public void requestLayout() {
            if (ignoreLayout) {
                return;
            }
            super.requestLayout();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            shadowDrawable.setBounds(0,
                    Math.max(actionBar.getMeasuredHeight(), scrollOffsetY) - backgroundPaddingTop,
                    getMeasuredWidth(), getMeasuredHeight());
            shadowDrawable.draw(canvas);
        }
    };
    containerView.setWillNotDraw(false);
    containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);

    actionBar = new ActionBar(context);
    actionBar.setBackgroundColor(Theme.getColor(Theme.key_player_actionBar));
    actionBar.setBackButtonImage(R.drawable.ic_ab_back);
    actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), false);
    actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_player_actionBarSelector), false);
    actionBar.setTitleColor(Theme.getColor(Theme.key_player_actionBarTitle));
    actionBar.setSubtitleColor(Theme.getColor(Theme.key_player_actionBarSubtitle));
    actionBar.setAlpha(0.0f);
    actionBar.setTitle("1");
    actionBar.setSubtitle("1");
    actionBar.getTitleTextView().setAlpha(0.0f);
    actionBar.getSubtitleTextView().setAlpha(0.0f);
    avatarContainer = new ChatAvatarContainer(context, null, false);
    avatarContainer.setEnabled(false);
    avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle),
            Theme.getColor(Theme.key_player_actionBarSubtitle));
    if (messageObject != null) {
        long did = messageObject.getDialogId();
        int lower_id = (int) did;
        int high_id = (int) (did >> 32);
        if (lower_id != 0) {
            if (lower_id > 0) {
                TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id);
                if (user != null) {
                    avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
                    avatarContainer.setUserAvatar(user);
                }
            } else {
                TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id);
                if (chat != null) {
                    avatarContainer.setTitle(chat.title);
                    avatarContainer.setChatAvatar(chat);
                }
            }
        } else {
            TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount)
                    .getEncryptedChat(high_id);
            if (encryptedChat != null) {
                TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id);
                if (user != null) {
                    avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
                    avatarContainer.setUserAvatar(user);
                }
            }
        }
    }
    avatarContainer.setSubtitle(LocaleController.getString("AudioTitle", R.string.AudioTitle));
    actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT,
            LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0));

    ActionBarMenu menu = actionBar.createMenu();
    menuItem = menu.addItem(0, R.drawable.ic_ab_other);
    menuItem.addSubItem(1, LocaleController.getString("Forward", R.string.Forward));
    menuItem.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile));
    //menuItem.addSubItem(3, LocaleController.getString("Delete", R.string.Delete));
    menuItem.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat));
    menuItem.setTranslationX(AndroidUtilities.dp(48));
    menuItem.setAlpha(0.0f);

    searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true)
            .setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() {
                @Override
                public void onSearchCollapse() {
                    avatarContainer.setVisibility(View.VISIBLE);
                    if (hasOptions) {
                        menuItem.setVisibility(View.INVISIBLE);
                    }
                    if (searching) {
                        searchWas = false;
                        searching = false;
                        setAllowNestedScroll(true);
                        listAdapter.search(null);
                    }
                }

                @Override
                public void onSearchExpand() {
                    searchOpenPosition = layoutManager.findLastVisibleItemPosition();
                    View firstVisView = layoutManager.findViewByPosition(searchOpenPosition);
                    searchOpenOffset = ((firstVisView == null) ? 0 : firstVisView.getTop())
                            - listView.getPaddingTop();

                    avatarContainer.setVisibility(View.GONE);
                    if (hasOptions) {
                        menuItem.setVisibility(View.GONE);
                    }
                    searching = true;
                    setAllowNestedScroll(false);
                    listAdapter.notifyDataSetChanged();
                }

                @Override
                public void onTextChanged(EditText editText) {
                    if (editText.length() > 0) {
                        listAdapter.search(editText.getText().toString());
                    } else {
                        searchWas = false;
                        listAdapter.search(null);
                    }
                }
            });
    EditTextBoldCursor editText = searchItem.getSearchField();
    editText.setHint(LocaleController.getString("Search", R.string.Search));
    editText.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
    editText.setHintTextColor(Theme.getColor(Theme.key_player_time));
    editText.setCursorColor(Theme.getColor(Theme.key_player_actionBarTitle));

    if (!AndroidUtilities.isTablet()) {
        actionBar.showActionModeTop();
        actionBar.setActionModeTopColor(Theme.getColor(Theme.key_player_actionBarTop));
    }
    actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
        @Override
        public void onItemClick(int id) {
            if (id == -1) {
                dismiss();
            } else {
                onSubItemClick(id);
            }
        }
    });

    shadow = new View(context);
    shadow.setAlpha(0.0f);
    shadow.setBackgroundResource(R.drawable.header_shadow);

    shadow2 = new View(context);
    shadow2.setAlpha(0.0f);
    shadow2.setBackgroundResource(R.drawable.header_shadow);

    playerLayout = new FrameLayout(context);
    playerLayout.setBackgroundColor(Theme.getColor(Theme.key_player_background));

    placeholderImageView = new BackupImageView(context) {

        private RectF rect = new RectF();

        @Override
        protected void onDraw(Canvas canvas) {
            if (hasNoCover == 1 || hasNoCover == 2
                    && (!getImageReceiver().hasBitmapImage() || getImageReceiver().getCurrentAlpha() != 1.0f)) {
                rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
                canvas.drawRoundRect(rect, getRoundRadius(), getRoundRadius(), paint);
                float plusScale = thumbMaxScale / getScaleX() / 3;
                int s = (int) (AndroidUtilities.dp(63)
                        * Math.max(plusScale / thumbMaxScale, 1.0f / thumbMaxScale));
                int x = (int) (rect.centerX() - s / 2);
                int y = (int) (rect.centerY() - s / 2);
                noCoverDrawable.setBounds(x, y, x + s, y + s);
                noCoverDrawable.draw(canvas);
            }
            if (hasNoCover != 1) {
                super.onDraw(canvas);
            }
        }
    };
    placeholderImageView.setRoundRadius(AndroidUtilities.dp(20));
    placeholderImageView.setPivotX(0);
    placeholderImageView.setPivotY(0);
    placeholderImageView.setOnClickListener(view -> {
        if (animatorSet != null) {
            animatorSet.cancel();
            animatorSet = null;
        }
        animatorSet = new AnimatorSet();
        if (scrollOffsetY <= actionBar.getMeasuredHeight()) {
            animatorSet.playTogether(ObjectAnimator.ofFloat(AudioPlayerAlert.this, "fullAnimationProgress",
                    isInFullMode ? 0.0f : 1.0f));
        } else {
            animatorSet.playTogether(
                    ObjectAnimator.ofFloat(AudioPlayerAlert.this, "fullAnimationProgress",
                            isInFullMode ? 0.0f : 1.0f),
                    ObjectAnimator.ofFloat(actionBar, "alpha", isInFullMode ? 0.0f : 1.0f),
                    ObjectAnimator.ofFloat(shadow, "alpha", isInFullMode ? 0.0f : 1.0f),
                    ObjectAnimator.ofFloat(shadow2, "alpha", isInFullMode ? 0.0f : 1.0f));
        }

        animatorSet.setInterpolator(new DecelerateInterpolator());
        animatorSet.setDuration(250);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (animation.equals(animatorSet)) {
                    if (!isInFullMode) {
                        listView.setScrollEnabled(true);
                        if (hasOptions) {
                            menuItem.setVisibility(View.INVISIBLE);
                        }
                        searchItem.setVisibility(View.VISIBLE);
                    } else {
                        if (hasOptions) {
                            menuItem.setVisibility(View.VISIBLE);
                        }
                        searchItem.setVisibility(View.INVISIBLE);
                    }
                    animatorSet = null;
                }
            }
        });
        animatorSet.start();
        if (hasOptions) {
            menuItem.setVisibility(View.VISIBLE);
        }
        searchItem.setVisibility(View.VISIBLE);
        isInFullMode = !isInFullMode;
        listView.setScrollEnabled(false);
        if (isInFullMode) {
            shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(20 + 48));
        } else {
            shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(10));
        }
    });

    titleTextView = new TextView(context);
    titleTextView.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
    titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
    titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
    titleTextView.setEllipsize(TextUtils.TruncateAt.END);
    titleTextView.setSingleLine(true);
    playerLayout.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
            LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 72, 18, 60, 0));

    authorTextView = new TextView(context);
    authorTextView.setTextColor(Theme.getColor(Theme.key_player_time));
    authorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
    authorTextView.setEllipsize(TextUtils.TruncateAt.END);
    authorTextView.setSingleLine(true);
    playerLayout.addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
            LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 72, 40, 60, 0));

    optionsButton = new ActionBarMenuItem(context, null, 0, Theme.getColor(Theme.key_player_actionBarItems));
    optionsButton.setLongClickEnabled(false);
    optionsButton.setIcon(R.drawable.ic_ab_other);
    optionsButton.setAdditionalOffset(-AndroidUtilities.dp(120));
    playerLayout.addView(optionsButton,
            LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.RIGHT, 0, 19, 10, 0));
    optionsButton.addSubItem(1, LocaleController.getString("Forward", R.string.Forward));
    optionsButton.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile));
    //optionsButton.addSubItem(3, LocaleController.getString("Delete", R.string.Delete));
    optionsButton.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat));
    optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu());
    optionsButton.setDelegate(this::onSubItemClick);

    seekBarView = new SeekBarView(context);
    seekBarView.setDelegate(progress -> MediaController.getInstance()
            .seekToProgress(MediaController.getInstance().getPlayingMessageObject(), progress));
    playerLayout.addView(seekBarView,
            LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.TOP | Gravity.LEFT, 8, 62, 8, 0));

    progressView = new LineProgressView(context);
    progressView.setVisibility(View.INVISIBLE);
    progressView.setBackgroundColor(Theme.getColor(Theme.key_player_progressBackground));
    progressView.setProgressColor(Theme.getColor(Theme.key_player_progress));
    playerLayout.addView(progressView,
            LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.TOP | Gravity.LEFT, 20, 78, 20, 0));

    timeTextView = new SimpleTextView(context);
    timeTextView.setTextSize(12);
    timeTextView.setText("0:00");
    timeTextView.setTextColor(Theme.getColor(Theme.key_player_time));
    playerLayout.addView(timeTextView,
            LayoutHelper.createFrame(100, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 20, 92, 0, 0));

    durationTextView = new TextView(context);
    durationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
    durationTextView.setTextColor(Theme.getColor(Theme.key_player_time));
    durationTextView.setGravity(Gravity.CENTER);
    playerLayout.addView(durationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT,
            LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.RIGHT, 0, 90, 20, 0));

    FrameLayout bottomView = new FrameLayout(context) {
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            int dist = ((right - left) - AndroidUtilities.dp(8 + 48 * 5)) / 4;
            for (int a = 0; a < 5; a++) {
                int l = AndroidUtilities.dp(4 + 48 * a) + dist * a;
                int t = AndroidUtilities.dp(9);
                buttons[a].layout(l, t, l + buttons[a].getMeasuredWidth(), t + buttons[a].getMeasuredHeight());
            }
        }
    };
    playerLayout.addView(bottomView,
            LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 66, Gravity.TOP | Gravity.LEFT, 0, 106, 0, 0));

    buttons[0] = shuffleButton = new ActionBarMenuItem(context, null, 0, 0);
    shuffleButton.setLongClickEnabled(false);
    shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(10));
    bottomView.addView(shuffleButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    shuffleButton.setOnClickListener(v -> shuffleButton.toggleSubMenu());

    TextView textView = shuffleButton.addSubItem(1,
            LocaleController.getString("ReverseOrder", R.string.ReverseOrder));
    textView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(16), 0);
    playOrderButtons[0] = context.getResources().getDrawable(R.drawable.music_reverse).mutate();
    textView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
    textView.setCompoundDrawablesWithIntrinsicBounds(playOrderButtons[0], null, null, null);

    textView = shuffleButton.addSubItem(2, LocaleController.getString("Shuffle", R.string.Shuffle));
    textView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(16), 0);
    playOrderButtons[1] = context.getResources().getDrawable(R.drawable.pl_shuffle).mutate();
    textView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
    textView.setCompoundDrawablesWithIntrinsicBounds(playOrderButtons[1], null, null, null);

    shuffleButton.setDelegate(id -> {
        MediaController.getInstance().toggleShuffleMusic(id);
        updateShuffleButton();
        listAdapter.notifyDataSetChanged();
    });

    ImageView prevButton;
    buttons[1] = prevButton = new ImageView(context);
    prevButton.setScaleType(ImageView.ScaleType.CENTER);
    prevButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_previous,
            Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
    bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    prevButton.setOnClickListener(v -> MediaController.getInstance().playPreviousMessage());

    buttons[2] = playButton = new ImageView(context);
    playButton.setScaleType(ImageView.ScaleType.CENTER);
    playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_play,
            Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
    bottomView.addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    playButton.setOnClickListener(v -> {
        if (MediaController.getInstance().isDownloadingCurrentMessage()) {
            return;
        }
        if (MediaController.getInstance().isMessagePaused()) {
            MediaController.getInstance().playMessage(MediaController.getInstance().getPlayingMessageObject());
        } else {
            MediaController.getInstance().pauseMessage(MediaController.getInstance().getPlayingMessageObject());
        }
    });

    ImageView nextButton;
    buttons[3] = nextButton = new ImageView(context);
    nextButton.setScaleType(ImageView.ScaleType.CENTER);
    nextButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_next,
            Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
    bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
    nextButton.setOnClickListener(v -> MediaController.getInstance().playNextMessage());

    buttons[4] = repeatButton = new ImageView(context);
    repeatButton.setScaleType(ImageView.ScaleType.CENTER);
    repeatButton.setPadding(0, 0, AndroidUtilities.dp(8), 0);
    bottomView.addView(repeatButton, LayoutHelper.createFrame(50, 48, Gravity.LEFT | Gravity.TOP));
    repeatButton.setOnClickListener(v -> {
        SharedConfig.toggleRepeatMode();
        updateRepeatButton();
    });

    listView = new RecyclerListView(context) {

        boolean ignoreLayout;

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);

            if (searchOpenPosition != -1 && !actionBar.isSearchFieldVisible()) {
                ignoreLayout = true;
                layoutManager.scrollToPositionWithOffset(searchOpenPosition, searchOpenOffset);
                super.onLayout(false, l, t, r, b);
                ignoreLayout = false;
                searchOpenPosition = -1;
            } else if (scrollToSong) {
                scrollToSong = false;
                boolean found = false;
                MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
                if (playingMessageObject != null) {
                    int count = listView.getChildCount();
                    for (int a = 0; a < count; a++) {
                        View child = listView.getChildAt(a);
                        if (child instanceof AudioPlayerCell) {
                            if (((AudioPlayerCell) child).getMessageObject() == playingMessageObject) {
                                if (child.getBottom() <= getMeasuredHeight()) {
                                    found = true;
                                }
                                break;
                            }
                        }
                    }
                    if (!found) {
                        int idx = playlist.indexOf(playingMessageObject);
                        if (idx >= 0) {
                            ignoreLayout = true;
                            if (SharedConfig.playOrderReversed) {
                                layoutManager.scrollToPosition(idx);
                            } else {
                                layoutManager.scrollToPosition(playlist.size() - idx);
                            }
                            super.onLayout(false, l, t, r, b);
                            ignoreLayout = false;
                        }
                    }
                }
            }
        }

        @Override
        public void requestLayout() {
            if (ignoreLayout) {
                return;
            }
            super.requestLayout();
        }

        @Override
        protected boolean allowSelectChildAtPosition(float x, float y) {
            float p = playerLayout.getY() + playerLayout.getMeasuredHeight();
            return playerLayout == null || y > playerLayout.getY() + playerLayout.getMeasuredHeight();
        }

        @Override
        public boolean drawChild(Canvas canvas, View child, long drawingTime) {
            canvas.save();
            canvas.clipRect(0,
                    (actionBar != null ? actionBar.getMeasuredHeight() : 0) + AndroidUtilities.dp(50),
                    getMeasuredWidth(), getMeasuredHeight());
            boolean result = super.drawChild(canvas, child, drawingTime);
            canvas.restore();
            return result;
        }
    };
    listView.setPadding(0, 0, 0, AndroidUtilities.dp(8));
    listView.setClipToPadding(false);
    listView.setLayoutManager(
            layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
    listView.setHorizontalScrollBarEnabled(false);
    listView.setVerticalScrollBarEnabled(false);
    containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
            LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
    listView.setAdapter(listAdapter = new ListAdapter(context));
    listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow));
    listView.setOnItemClickListener((view, position) -> {
        if (view instanceof AudioPlayerCell) {
            ((AudioPlayerCell) view).didPressedButton();
        }
    });
    listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            if (newState == RecyclerView.SCROLL_STATE_DRAGGING && searching && searchWas) {
                AndroidUtilities.hideKeyboard(getCurrentFocus());
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            updateLayout();
        }
    });

    playlist = MediaController.getInstance().getPlaylist();
    listAdapter.notifyDataSetChanged();

    containerView.addView(playerLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 178));
    containerView.addView(shadow2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
    containerView.addView(placeholderImageView,
            LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.LEFT, 17, 19, 0, 0));
    containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
    containerView.addView(actionBar);

    updateTitle(false);
    updateRepeatButton();
    updateShuffleButton();
}

From source file:com.gigamole.library.NavigationTabBar.java

@Override
protected void onDraw(final Canvas canvas) {
    if (mCanvas == null || mPointerCanvas == null || mIconsCanvas == null)
        return;/*www .jav  a2 s .c o m*/

    // Reset and clear canvases
    mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mPointerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    mIconsCanvas.drawColor(0, PorterDuff.Mode.CLEAR);

    // Get pointer badge margin for gravity
    final float pointerBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : 0.0f;

    // Draw our model colors
    for (int i = 0; i < mModels.size(); i++) {
        mPaint.setColor(mModels.get(i).getColor());

        if (mIsHorizontalOrientation) {
            final float left = mModelSize * i;
            final float right = left + mModelSize;
            mCanvas.drawRect(left, pointerBadgeMargin, right, mBounds.height() + pointerBadgeMargin, mPaint);
        } else {
            final float top = mModelSize * i;
            final float bottom = top + mModelSize;
            mCanvas.drawRect(0.0f, top, mBounds.width(), bottom, mPaint);
        }
    }

    // Set bound of pointer
    if (mIsHorizontalOrientation)
        mPointerBounds.set(mPointerLeftTop, pointerBadgeMargin, mPointerRightBottom,
                mBounds.height() + pointerBadgeMargin);
    else
        mPointerBounds.set(0.0f, mPointerLeftTop, mBounds.width(), mPointerRightBottom);

    // Draw pointer for model colors
    if (mCornersRadius == 0)
        mPointerCanvas.drawRect(mPointerBounds, mPaint);
    else
        mPointerCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mPaint);

    // Draw pointer into main canvas
    mCanvas.drawBitmap(mPointerBitmap, 0.0f, 0.0f, mPointerPaint);

    // Draw model icons
    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Variables to center our icons
        final float leftOffset;
        final float topOffset;
        final float matrixCenterX;
        final float matrixCenterY;

        // Set vars for icon when model with title or without
        final float iconMarginTitleHeight = mIconSize + mTitleMargin + mModelTitleSize;
        final float leftTitleOffset = (mModelSize * i) + (mModelSize * 0.5f);
        final float topTitleOffset = mBounds.height() - (mBounds.height() - iconMarginTitleHeight) * 0.5f;

        if (mIsHorizontalOrientation) {
            leftOffset = (mModelSize * i) + (mModelSize - model.mIcon.getWidth()) * 0.5f;
            topOffset = (mBounds.height() - model.mIcon.getHeight()) * 0.5f;

            matrixCenterX = leftOffset + model.mIcon.getWidth() * 0.5f;
            matrixCenterY = topOffset + model.mIcon.getHeight() * 0.5f
                    + (mIsTitled && mTitleMode == TitleMode.ALL ? mTitleMargin * 0.5f : 0.0f);
        } else {
            leftOffset = (mBounds.width() - model.mIcon.getWidth()) * 0.5f;
            topOffset = (mModelSize * i) + (mModelSize - model.mIcon.getHeight()) * 0.5f;

            matrixCenterX = leftOffset + model.mIcon.getWidth() * 0.5f;
            matrixCenterY = topOffset + model.mIcon.getHeight() * 0.5f;
        }

        // Title translate position
        final float titleTranslate = -model.mIcon.getHeight() + topTitleOffset - mTitleMargin * 0.5f;

        // Translate icon to model center
        model.mIconMatrix.setTranslate(leftOffset,
                (mIsTitled && mTitleMode == TitleMode.ALL) ? titleTranslate : topOffset);

        // Get interpolated fraction for left last and current models
        final float interpolation = mResizeInterpolator.getResizeInterpolation(mFraction, true);
        final float lastInterpolation = mResizeInterpolator.getResizeInterpolation(mFraction, false);

        // Scale value relative to interpolation
        final float matrixScale = model.mActiveIconScaleBy * interpolation;
        final float matrixLastScale = model.mActiveIconScaleBy * lastInterpolation;

        // Get title alpha relative to interpolation
        final int titleAlpha = (int) (MAX_ALPHA * interpolation);
        final int titleLastAlpha = MAX_ALPHA - (int) (MAX_ALPHA * lastInterpolation);
        // Get title scale relative to interpolation
        final float titleScale = MAX_FRACTION + (interpolation * TITLE_ACTIVE_SCALE_BY);
        final float titleLastScale = (MAX_FRACTION + TITLE_ACTIVE_SCALE_BY)
                - (lastInterpolation * TITLE_ACTIVE_SCALE_BY);

        // Check if we handle models from touch on NTP or from ViewPager
        // There is a strange logic of ViewPager onPageScrolled method, so it is
        if (mIsSetIndexFromTabBar) {
            if (mIndex == i)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (mLastIndex == i)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
            else
                updateInactiveModel(model, leftOffset, topOffset, matrixCenterX, matrixCenterY);
        } else {
            if (i != mIndex && i != mIndex + 1)
                updateInactiveModel(model, leftOffset, topOffset, matrixCenterX, matrixCenterY);
            else if (i == mIndex + 1)
                updateCurrentModel(model, leftOffset, topOffset, titleTranslate, interpolation, matrixCenterX,
                        matrixCenterY, matrixScale, titleScale, titleAlpha);
            else if (i == mIndex)
                updateLastModel(model, leftOffset, topOffset, titleTranslate, lastInterpolation, matrixCenterX,
                        matrixCenterY, matrixLastScale, titleLastScale, titleLastAlpha);
        }

        // Draw model icon
        mIconsCanvas.drawBitmap(model.mIcon, model.mIconMatrix, mIconPaint);
        if (mIsTitled)
            mIconsCanvas.drawText(isInEditMode() ? PREVIEW_TITLE : model.getTitle(), leftTitleOffset,
                    topTitleOffset, mModelTitlePaint);
    }

    // Draw pointer with active color to wrap out active icon
    if (mCornersRadius == 0)
        mIconsCanvas.drawRect(mPointerBounds, mIconPointerPaint);
    else
        mIconsCanvas.drawRoundRect(mPointerBounds, mCornersRadius, mCornersRadius, mIconPointerPaint);

    // Draw general bitmap
    canvas.drawBitmap(mBitmap, 0.0f, 0.0f, null);
    // Draw icons bitmap on top
    canvas.drawBitmap(mIconsBitmap, 0.0f, pointerBadgeMargin, null);

    // If is not badged, exit
    if (!mIsBadged)
        return;

    // Model badge margin and offset relative to gravity mode
    final float modelBadgeMargin = mBadgeGravity == BadgeGravity.TOP ? mBadgeMargin : mBounds.height();
    final float modelBadgeOffset = mBadgeGravity == BadgeGravity.TOP ? 0.0f : mBounds.height() - mBadgeMargin;

    for (int i = 0; i < mModels.size(); i++) {
        final Model model = mModels.get(i);

        // Set preview badge title
        if (isInEditMode() || TextUtils.isEmpty(model.getBadgeTitle()))
            model.setBadgeTitle(PREVIEW_BADGE);

        // Set badge title bounds
        mBadgePaint.setTextSize(mBadgeTitleSize * model.mBadgeFraction);
        mBadgePaint.getTextBounds(model.getBadgeTitle(), 0, model.getBadgeTitle().length(), mBadgeBounds);

        // Get horizontal and vertical padding for bg
        final float horizontalPadding = mBadgeTitleSize * BADGE_HORIZONTAL_FRACTION;
        final float verticalPadding = horizontalPadding * BADGE_VERTICAL_FRACTION;

        // Set horizontal badge offset
        final float badgeBoundsHorizontalOffset = (mModelSize * i)
                + (mModelSize * mBadgePosition.mPositionFraction);

        // If is badge title only one char, so create circle else round rect
        if (model.getBadgeTitle().length() == 1) {
            final float badgeMargin = mBadgeMargin * model.mBadgeFraction;
            mBgBadgeBounds.set(badgeBoundsHorizontalOffset - badgeMargin, modelBadgeMargin - badgeMargin,
                    badgeBoundsHorizontalOffset + badgeMargin, modelBadgeMargin + badgeMargin);
        } else
            mBgBadgeBounds.set(badgeBoundsHorizontalOffset - mBadgeBounds.centerX() - horizontalPadding,
                    modelBadgeMargin - (mBadgeMargin * model.mBadgeFraction),
                    badgeBoundsHorizontalOffset + mBadgeBounds.centerX() + horizontalPadding,
                    modelBadgeOffset + (verticalPadding * 2.0f) + mBadgeBounds.height());

        // Set color and alpha for badge bg
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else
            mBadgePaint.setColor(mActiveColor);
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set corners to round rect for badge bg and draw
        final float cornerRadius = mBgBadgeBounds.height() * 0.5f;
        canvas.drawRoundRect(mBgBadgeBounds, cornerRadius, cornerRadius, mBadgePaint);

        // Set color and alpha for badge title
        if (model.mBadgeFraction == MIN_FRACTION)
            mBadgePaint.setColor(Color.TRANSPARENT);
        else
            mBadgePaint.setColor(model.getColor());
        mBadgePaint.setAlpha((int) (MAX_ALPHA * model.mBadgeFraction));

        // Set badge title center position and draw title
        final float badgeHalfHeight = mBadgeBounds.height() * 0.5f;
        float badgeVerticalOffset = (mBgBadgeBounds.height() * 0.5f) + badgeHalfHeight - mBadgeBounds.bottom
                + modelBadgeOffset;
        canvas.drawText(model.getBadgeTitle(), badgeBoundsHorizontalOffset,
                badgeVerticalOffset + mBadgeBounds.height() - (mBadgeBounds.height() * model.mBadgeFraction),
                mBadgePaint);
    }
}