List of usage examples for android.graphics Canvas drawBitmap
public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint)
From source file:com.aujur.ebookreader.activity.ReadingFragment.java
private Bitmap getBookViewSnapshot() { try {/*from w w w .j a va 2s .c o m*/ Bitmap bitmap = Bitmap.createBitmap(viewSwitcher.getWidth(), viewSwitcher.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); bookView.layout(0, 0, viewSwitcher.getWidth(), viewSwitcher.getHeight()); bookView.draw(canvas); if (config.isShowPageNumbers()) { /** * FIXME: creating an intermediate bitmap here because I can't * figure out how to draw the pageNumberView directly on the * canvas and have it show up in the right place. */ Bitmap pageNumberBitmap = Bitmap.createBitmap(pageNumberView.getWidth(), pageNumberView.getHeight(), Config.ARGB_8888); Canvas pageNumberCanvas = new Canvas(pageNumberBitmap); pageNumberView.layout(0, 0, pageNumberView.getWidth(), pageNumberView.getHeight()); pageNumberView.draw(pageNumberCanvas); canvas.drawBitmap(pageNumberBitmap, 0, viewSwitcher.getHeight() - pageNumberView.getHeight(), new Paint()); pageNumberBitmap.recycle(); } return bitmap; } catch (OutOfMemoryError out) { viewSwitcher.setBackgroundColor(config.getBackgroundColor()); } return null; }
From source file:com.android.leanlauncher.CellLayout.java
@Override protected void onDraw(Canvas canvas) { // When we're large, we are either drawn in a "hover" state (ie when dragging an item to // a neighboring page) or with just a normal background (if backgroundAlpha > 0.0f) // When we're small, we are either drawn normally or in the "accepts drops" state (during // a drag). However, we also drag the mini hover background *over* one of those two // backgrounds if (mDrawBackground && mBackgroundAlpha > 0.0f) { Drawable bg;//ww w . ja v a 2 s . c o m if (mUseActiveGlowBackground) { // In the mini case, we draw the active_glow bg *over* the active background bg = mActiveGlowBackground; } else { bg = mNormalBackground; } bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255)); bg.setBounds(mBackgroundRect); bg.draw(canvas); } final Paint paint = mDragOutlinePaint; for (int i = 0; i < mDragOutlines.length; i++) { final float alpha = mDragOutlineAlphas[i]; if (alpha > 0) { final Rect r = mDragOutlines[i]; mTempRect.set(r); Utilities.scaleRectAboutCenter(mTempRect, getChildrenScale()); final Bitmap b = (Bitmap) mDragOutlineAnims[i].getTag(); paint.setAlpha((int) (alpha + .5f)); canvas.drawBitmap(b, null, mTempRect, paint); } } }
From source file:com.android.launcher2.Workspace.java
/** * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location. * Responsibility for the bitmap is transferred to the caller. *//*www . j a v a 2 s . c o m*/ private Bitmap createDragOutline(Bitmap orig, Canvas canvas, int padding, int w, int h, boolean clipAlpha) { final int outlineColor = getResources().getColor(android.R.color.holo_blue_light); final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); canvas.setBitmap(b); Rect src = new Rect(0, 0, orig.getWidth(), orig.getHeight()); float scaleFactor = Math.min((w - padding) / (float) orig.getWidth(), (h - padding) / (float) orig.getHeight()); int scaledWidth = (int) (scaleFactor * orig.getWidth()); int scaledHeight = (int) (scaleFactor * orig.getHeight()); Rect dst = new Rect(0, 0, scaledWidth, scaledHeight); // center the image dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2); canvas.drawBitmap(orig, src, dst, null); mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor, clipAlpha); canvas.setBitmap(null); return b; }
From source file:com.android.launcher2.AsyncTaskCallback.java
private Bitmap getWidgetPreview(ComponentName provider, int previewImage, int iconId, int cellHSpan, int cellVSpan, int maxWidth, int maxHeight) { // Load the preview image if possible String packageName = provider.getPackageName(); if (maxWidth < 0) maxWidth = Integer.MAX_VALUE; if (maxHeight < 0) maxHeight = Integer.MAX_VALUE; Drawable drawable = null;// w w w . j a va 2 s. c o m if (previewImage != 0) { drawable = mPackageManager.getDrawable(packageName, previewImage, null); if (drawable == null) { Log.w(TAG, "Can't load widget preview drawable 0x" + Integer.toHexString(previewImage) + " for provider: " + provider); } } int bitmapWidth; int bitmapHeight; Bitmap defaultPreview = null; boolean widgetPreviewExists = (drawable != null); if (widgetPreviewExists) { bitmapWidth = drawable.getIntrinsicWidth(); bitmapHeight = drawable.getIntrinsicHeight(); } else { // Generate a preview image if we couldn't load one if (cellHSpan < 1) cellHSpan = 1; if (cellVSpan < 1) cellVSpan = 1; BitmapDrawable previewDrawable = (BitmapDrawable) getResources() .getDrawable(R.drawable.widget_preview_tile); final int previewDrawableWidth = previewDrawable.getIntrinsicWidth(); final int previewDrawableHeight = previewDrawable.getIntrinsicHeight(); bitmapWidth = previewDrawableWidth * cellHSpan; // subtract 2 dips bitmapHeight = previewDrawableHeight * cellVSpan; defaultPreview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Config.ARGB_8888); final Canvas c = mCachedAppWidgetPreviewCanvas.get(); c.setBitmap(defaultPreview); previewDrawable.setBounds(0, 0, bitmapWidth, bitmapHeight); previewDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); previewDrawable.draw(c); c.setBitmap(null); // Draw the icon in the top left corner int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage); int smallestSide = Math.min(bitmapWidth, bitmapHeight); float iconScale = Math.min((float) smallestSide / (mAppIconSize + 2 * minOffset), 1f); try { Drawable icon = null; int hoffset = (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2); int yoffset = (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2); if (iconId > 0) icon = mIconCache.getFullResIcon(packageName, iconId); if (icon != null) { renderDrawableToBitmap(icon, defaultPreview, hoffset, yoffset, (int) (mAppIconSize * iconScale), (int) (mAppIconSize * iconScale)); } } catch (Resources.NotFoundException e) { } } // Scale to fit width only - let the widget preview be clipped in the // vertical dimension float scale = 1f; if (bitmapWidth > maxWidth) { scale = maxWidth / (float) bitmapWidth; } if (scale != 1f) { bitmapWidth = (int) (scale * bitmapWidth); bitmapHeight = (int) (scale * bitmapHeight); } Bitmap preview = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Config.ARGB_8888); // Draw the scaled preview into the final bitmap if (widgetPreviewExists) { renderDrawableToBitmap(drawable, preview, 0, 0, bitmapWidth, bitmapHeight); } else { final Canvas c = mCachedAppWidgetPreviewCanvas.get(); final Rect src = mCachedAppWidgetPreviewSrcRect.get(); final Rect dest = mCachedAppWidgetPreviewDestRect.get(); c.setBitmap(preview); src.set(0, 0, defaultPreview.getWidth(), defaultPreview.getHeight()); dest.set(0, 0, preview.getWidth(), preview.getHeight()); Paint p = mCachedAppWidgetPreviewPaint.get(); if (p == null) { p = new Paint(); p.setFilterBitmap(true); mCachedAppWidgetPreviewPaint.set(p); } c.drawBitmap(defaultPreview, src, dest, p); c.setBitmap(null); } return preview; }
From source file:cc.flydev.launcher.Workspace.java
/** * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location. * Responsibility for the bitmap is transferred to the caller. */// ww w.j ava 2 s .c om private Bitmap createDragOutline(Bitmap orig, Canvas canvas, int padding, int w, int h, boolean clipAlpha) { final int outlineColor = getResources().getColor(R.color.outline_color); final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); canvas.setBitmap(b); Rect src = new Rect(0, 0, orig.getWidth(), orig.getHeight()); float scaleFactor = Math.min((w - padding) / (float) orig.getWidth(), (h - padding) / (float) orig.getHeight()); int scaledWidth = (int) (scaleFactor * orig.getWidth()); int scaledHeight = (int) (scaleFactor * orig.getHeight()); Rect dst = new Rect(0, 0, scaledWidth, scaledHeight); // center the image dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2); canvas.drawBitmap(orig, src, dst, null); mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor, clipAlpha); canvas.setBitmap(null); return b; }
From source file:xiaofan.llongimageview.view.SubsamplingScaleImageView.java
/** * Draw method should not be called until the view has dimensions so the first calls are used as triggers to calculate * the scaling and tiling required. Once the view is setup, tiles are displayed as they are loaded. *///from w ww. j av a 2 s . co m @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); createPaints(); // If image or view dimensions are not known yet, abort. if (sWidth == 0 || sHeight == 0 || decoder == null || getWidth() == 0 || getHeight() == 0) { return; } // On first render with no tile map ready, initialise it and kick off async base image loading. if (tileMap == null) { initialiseBaseLayer(getMaxBitmapDimensions(canvas)); return; } // If waiting to translate to new center position, set translate now if (sPendingCenter != null && pendingScale != null) { scale = pendingScale; vTranslate.x = (getWidth() / 2) - (scale * sPendingCenter.x); vTranslate.y = (getHeight() / 2) - (scale * sPendingCenter.y); sPendingCenter = null; pendingScale = null; fitToBounds(true); refreshRequiredTiles(true); } // On first display of base image set up position, and in other cases make sure scale is correct. fitToBounds(false); // Everything is set up and coordinates are valid. Inform subclasses. if (!readySent) { readySent = true; new Thread(new Runnable() { public void run() { onImageReady(); } }).start(); } // If animating scale, calculate current scale and center with easing equations if (anim != null) { long scaleElapsed = System.currentTimeMillis() - anim.time; boolean finished = scaleElapsed > anim.duration; scaleElapsed = Math.min(scaleElapsed, anim.duration); scale = ease(anim.easing, scaleElapsed, anim.scaleStart, anim.scaleEnd - anim.scaleStart, anim.duration); // Apply required animation to the focal point float vFocusNowX = ease(anim.easing, scaleElapsed, anim.vFocusStart.x, anim.vFocusEnd.x - anim.vFocusStart.x, anim.duration); float vFocusNowY = ease(anim.easing, scaleElapsed, anim.vFocusStart.y, anim.vFocusEnd.y - anim.vFocusStart.y, anim.duration); // Find out where the focal point is at this scale and adjust its position to follow the animation path PointF vFocus = sourceToViewCoord(anim.sCenterEnd); vTranslate.x -= vFocus.x - vFocusNowX; vTranslate.y -= vFocus.y - vFocusNowY; // For translate anims, showing the image non-centered is never allowed, for scaling anims it is during the animation. fitToBounds(finished || (anim.scaleStart == anim.scaleEnd)); refreshRequiredTiles(finished); if (finished) { anim = null; } invalidate(); } // Optimum sample size for current scale int sampleSize = Math.min(fullImageSampleSize, calculateInSampleSize()); // First check for missing tiles - if there are any we need the base layer underneath to avoid gaps boolean hasMissingTiles = false; for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) { if (tileMapEntry.getKey() == sampleSize) { for (Tile tile : tileMapEntry.getValue()) { if (tile.visible && (tile.loading || tile.bitmap == null)) { hasMissingTiles = true; } } } } // Render all loaded tiles. LinkedHashMap used for bottom up rendering - lower res tiles underneath. for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) { if (tileMapEntry.getKey() == sampleSize || hasMissingTiles) { for (Tile tile : tileMapEntry.getValue()) { Rect vRect = convertRect(sourceToViewRect(tile.sRect)); if (!tile.loading && tile.bitmap != null) { canvas.drawBitmap(tile.bitmap, null, vRect, bitmapPaint); if (debug) { canvas.drawRect(vRect, debugPaint); } } else if (tile.loading && debug) { canvas.drawText("LOADING", vRect.left + 5, vRect.top + 35, debugPaint); } if (tile.visible && debug) { canvas.drawText( "ISS " + tile.sampleSize + " RECT " + tile.sRect.top + "," + tile.sRect.left + "," + tile.sRect.bottom + "," + tile.sRect.right, vRect.left + 5, vRect.top + 15, debugPaint); } } } } if (debug) { canvas.drawText("Scale: " + String.format("%.2f", scale), 5, 15, debugPaint); canvas.drawText( "Translate: " + String.format("%.2f", vTranslate.x) + ":" + String.format("%.2f", vTranslate.y), 5, 35, debugPaint); PointF center = getCenter(); canvas.drawText( "Source center: " + String.format("%.2f", center.x) + ":" + String.format("%.2f", center.y), 5, 55, debugPaint); if (anim != null) { PointF vCenterStart = sourceToViewCoord(anim.sCenterStart); PointF vCenterEndRequested = sourceToViewCoord(anim.sCenterEndRequested); PointF vCenterEnd = sourceToViewCoord(anim.sCenterEnd); canvas.drawCircle(vCenterStart.x, vCenterStart.y, 10, debugPaint); canvas.drawCircle(vCenterEndRequested.x, vCenterEndRequested.y, 20, debugPaint); canvas.drawCircle(vCenterEnd.x, vCenterEnd.y, 25, debugPaint); canvas.drawCircle(getWidth() / 2, getHeight() / 2, 30, debugPaint); } } }
From source file:com.bizcom.vc.widget.cus.SubsamplingScaleImageView.java
/** * Draw method should not be called until the view has dimensions so the * first calls are used as triggers to calculate the scaling and tiling * required. Once the view is setup, tiles are displayed as they are loaded. *///from ww w . jav a 2s. c om @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); createPaints(); // If image or view dimensions are not known yet, abort. if (sWidth == 0 || sHeight == 0 || decoder == null || getWidth() == 0 || getHeight() == 0) { return; } // On first render with no tile map ready, initialise it and kick off // async base image loading. if (tileMap == null) { initialiseBaseLayer(getMaxBitmapDimensions(canvas)); return; } // If waiting to translate to new center position, set translate now if (sPendingCenter != null && pendingScale != null) { scale = pendingScale; vTranslate.x = (getWidth() / 2) - (scale * sPendingCenter.x); vTranslate.y = (getHeight() / 2) - (scale * sPendingCenter.y); sPendingCenter = null; pendingScale = null; fitToBounds(true); refreshRequiredTiles(true); } // On first display of base image set up position, and in other cases // make sure scale is correct. fitToBounds(false); // Everything is set up and coordinates are valid. Inform subclasses. if (!readySent) { readySent = true; new Thread(new Runnable() { public void run() { onImageReady(); } }).start(); } // If animating scale, calculate current scale and center with easing // equations if (anim != null) { long scaleElapsed = System.currentTimeMillis() - anim.time; boolean finished = scaleElapsed > anim.duration; scaleElapsed = Math.min(scaleElapsed, anim.duration); scale = ease(anim.easing, scaleElapsed, anim.scaleStart, anim.scaleEnd - anim.scaleStart, anim.duration); // Apply required animation to the focal point float vFocusNowX = ease(anim.easing, scaleElapsed, anim.vFocusStart.x, anim.vFocusEnd.x - anim.vFocusStart.x, anim.duration); float vFocusNowY = ease(anim.easing, scaleElapsed, anim.vFocusStart.y, anim.vFocusEnd.y - anim.vFocusStart.y, anim.duration); // Find out where the focal point is at this scale and adjust its // position to follow the animation path PointF vFocus = sourceToViewCoord(anim.sCenterEnd); vTranslate.x -= vFocus.x - vFocusNowX; vTranslate.y -= vFocus.y - vFocusNowY; // For translate anims, showing the image non-centered is never // allowed, for scaling anims it is during the animation. fitToBounds(finished || (anim.scaleStart == anim.scaleEnd)); refreshRequiredTiles(finished); if (finished) { anim = null; } invalidate(); } // Optimum sample size for current scale int sampleSize = Math.min(fullImageSampleSize, calculateInSampleSize()); // First check for missing tiles - if there are any we need the base // layer underneath to avoid gaps boolean hasMissingTiles = false; for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) { if (tileMapEntry.getKey() == sampleSize) { for (Tile tile : tileMapEntry.getValue()) { if (tile.visible && (tile.loading || tile.bitmap == null)) { hasMissingTiles = true; } } } } // Render all loaded tiles. LinkedHashMap used for bottom up rendering - // lower res tiles underneath. for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) { if (tileMapEntry.getKey() == sampleSize || hasMissingTiles) { for (Tile tile : tileMapEntry.getValue()) { Rect vRect = convertRect(sourceToViewRect(tile.sRect)); if (!tile.loading && tile.bitmap != null) { canvas.drawBitmap(tile.bitmap, null, vRect, bitmapPaint); if (debug) { canvas.drawRect(vRect, debugPaint); } } else if (tile.loading && debug) { canvas.drawText("LOADING", vRect.left + 5, vRect.top + 35, debugPaint); } if (tile.visible && debug) { canvas.drawText( "ISS " + tile.sampleSize + " RECT " + tile.sRect.top + "," + tile.sRect.left + "," + tile.sRect.bottom + "," + tile.sRect.right, vRect.left + 5, vRect.top + 15, debugPaint); } } } } if (debug) { canvas.drawText("Scale: " + String.format("%.2f", scale), 5, 15, debugPaint); canvas.drawText( "Translate: " + String.format("%.2f", vTranslate.x) + ":" + String.format("%.2f", vTranslate.y), 5, 35, debugPaint); PointF center = getCenter(); canvas.drawText( "Source center: " + String.format("%.2f", center.x) + ":" + String.format("%.2f", center.y), 5, 55, debugPaint); if (anim != null) { PointF vCenterStart = sourceToViewCoord(anim.sCenterStart); PointF vCenterEndRequested = sourceToViewCoord(anim.sCenterEndRequested); PointF vCenterEnd = sourceToViewCoord(anim.sCenterEnd); canvas.drawCircle(vCenterStart.x, vCenterStart.y, 10, debugPaint); canvas.drawCircle(vCenterEndRequested.x, vCenterEndRequested.y, 20, debugPaint); canvas.drawCircle(vCenterEnd.x, vCenterEnd.y, 25, debugPaint); canvas.drawCircle(getWidth() / 2, getHeight() / 2, 30, debugPaint); } } }
From source file:cn.oddcloud.www.navigationtabbar.ntb.NavigationTabBar.java
@SuppressWarnings("ConstantConditions") @Override/*from 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 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); } }