Java tutorial
/* * Copyright 2014 Mike Penz * * * I improved the previous version of the IconicsDrawable which * was written by Joan Zapata for the Android-Iconify project * which you can find here: http://joanzapata.com/android-iconify/ * and added some functionality written by Artur Termenji used * in the https://github.com/theDazzler/droidicon project. * * The droidicon project is under the (MIT LICENSE http://opensource.org/licenses/MIT) * The android-iconify project under the (Apache License) * * This version of the IconicsDrawable uses functions from both * projects. * * In addition i added some more stuff like the toBitmap function. * * * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package lollipop.iconics; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; import android.support.annotation.DimenRes; import android.support.v4.content.ContextCompat; import android.util.Log; import lollipop.iconics.typeface.IIcon; import lollipop.iconics.utils.Utils; import lollipop.iconics.typeface.ITypeface; /** * A custom {@link Drawable} which can display icons from icon fonts. */ public class IconicsDrawable extends Drawable { public static final int ANDROID_ACTIONBAR_ICON_SIZE_DP = 24; public static final int ANDROID_ACTIONBAR_ICON_SIZE_PADDING_DP = 1; private Context mContext; private int mSizeX = -1; private int mSizeY = -1; private Paint mIconPaint; private Paint mContourPaint; private Paint mBackgroundPaint = null; private int mRoundedCornerRx = -1; private int mRoundedCornerRy = -1; private Rect mPaddingBounds; private RectF mPathBounds; private Path mPath; private int mIconPadding; private int mContourWidth; private int mIconOffsetX = 0; private int mIconOffsetY = 0; private int mAlpha = 255; private boolean mDrawContour; private IIcon mIcon; private String mPlainIcon; public IconicsDrawable(Context context) { mContext = context.getApplicationContext(); prepare(); icon(' '); } public IconicsDrawable(Context context, Character icon) { mContext = context.getApplicationContext(); prepare(); icon(icon); } public IconicsDrawable(Context context, String icon) { mContext = context.getApplicationContext(); prepare(); try { ITypeface font = Iconics.findFont(context, icon.substring(0, 3)); icon = icon.replace("-", "_"); icon(font.getIcon(icon)); } catch (Exception ex) { Log.e(Iconics.TAG, "Wrong icon name: " + icon); } } public IconicsDrawable(Context context, final IIcon icon) { mContext = context.getApplicationContext(); prepare(); icon(icon); } protected IconicsDrawable(Context context, final ITypeface typeface, final IIcon icon) { mContext = context.getApplicationContext(); prepare(); icon(typeface, icon); } private void prepare() { mIconPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mContourPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mContourPaint.setStyle(Paint.Style.STROKE); mPath = new Path(); mPathBounds = new RectF(); mPaddingBounds = new Rect(); } /** * Loads and draws given text * * @param icon * @return The current IconExtDrawable for chaining. */ public IconicsDrawable icon(String icon) { try { ITypeface font = Iconics.findFont(mContext, icon.substring(0, 3)); icon = icon.replace("-", "_"); icon(font.getIcon(icon)); } catch (Exception ex) { Log.e(Iconics.TAG, "Wrong icon name: " + icon); } return this; } /** * Loads and draws given. * * @param icon * @return The current IconExtDrawable for chaining. */ public IconicsDrawable icon(Character icon) { return iconText(icon.toString()); } /** * Loads and draws given text * * @param icon * @return The current IconExtDrawable for chaining. */ public IconicsDrawable iconText(String icon) { mPlainIcon = icon; mIcon = null; mIconPaint.setTypeface(Typeface.DEFAULT); invalidateSelf(); return this; } /** * Loads and draws given. * * @param icon * @return The current IconExtDrawable for chaining. */ public IconicsDrawable icon(IIcon icon) { mIcon = icon; mPlainIcon = null; ITypeface typeface = icon.getTypeface(); mIconPaint.setTypeface(typeface.getTypeface(mContext)); invalidateSelf(); return this; } /** * Loads and draws given. * * @param typeface * @param icon * @return The current IconExtDrawable for chaining. */ protected IconicsDrawable icon(ITypeface typeface, IIcon icon) { mIcon = icon; mIconPaint.setTypeface(typeface.getTypeface(mContext)); invalidateSelf(); return this; } /** * Set the color of the drawable. * * @param color The color, usually from android.graphics.Color or 0xFF012345. * @return The current IconExtDrawable for chaining. */ public IconicsDrawable color(@ColorInt int color) { int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); mIconPaint.setColor(Color.rgb(red, green, blue)); setAlpha(Color.alpha(color)); invalidateSelf(); return this; } /* public int adjustAlpha(int color, float factor) { int alpha = Math.round(Color.alpha(color)); int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); return Color.argb(alpha, red, green, blue); } */ /** * Set the color of the drawable. * * @param colorRes The color resource, from your R file. * @return The current IconExtDrawable for chaining. */ public IconicsDrawable colorRes(@ColorRes int colorRes) { return color(ContextCompat.getColor(mContext, colorRes)); } /** * set the icon offset for X from resource * * @param iconOffsetXRes * @return */ public IconicsDrawable iconOffsetXRes(@DimenRes int iconOffsetXRes) { return iconOffsetXPx(mContext.getResources().getDimensionPixelSize(iconOffsetXRes)); } /** * set the icon offset for X as dp * * @param iconOffsetXDp * @return */ public IconicsDrawable iconOffsetXDp(int iconOffsetXDp) { return iconOffsetXPx(Utils.convertDpToPx(mContext, iconOffsetXDp)); } /** * set the icon offset for X * * @param iconOffsetX * @return */ public IconicsDrawable iconOffsetXPx(int iconOffsetX) { this.mIconOffsetX = iconOffsetX; return this; } /** * set the icon offset for Y from resource * * @param iconOffsetYRes * @return */ public IconicsDrawable iconOffsetYRes(@DimenRes int iconOffsetYRes) { return iconOffsetYPx(mContext.getResources().getDimensionPixelSize(iconOffsetYRes)); } /** * set the icon offset for Y as dp * * @param iconOffsetYDp * @return */ public IconicsDrawable iconOffsetYDp(int iconOffsetYDp) { return iconOffsetYPx(Utils.convertDpToPx(mContext, iconOffsetYDp)); } /** * set the icon offset for Y * * @param iconOffsetY * @return */ public IconicsDrawable iconOffsetYPx(int iconOffsetY) { this.mIconOffsetY = iconOffsetY; return this; } /** * Set the padding of the drawable from res * * @param dimenRes * @return The current IconExtDrawable for chaining. */ public IconicsDrawable paddingRes(@DimenRes int dimenRes) { return paddingPx(mContext.getResources().getDimensionPixelSize(dimenRes)); } /** * Set the padding in dp for the drawable * * @param iconPadding * @return The current IconExtDrawable for chaining. */ public IconicsDrawable paddingDp(int iconPadding) { return paddingPx(Utils.convertDpToPx(mContext, iconPadding)); } /** * Set a padding for the. * * @param iconPadding * @return The current IconExtDrawable for chaining. */ public IconicsDrawable paddingPx(int iconPadding) { if (mIconPadding != iconPadding) { mIconPadding = iconPadding; if (mDrawContour) { mIconPadding += mContourWidth; } invalidateSelf(); } return this; } /** * Set the size of this icon to the standard Android ActionBar. * * @return The current IconExtDrawable for chaining. * @deprecated use actionBar() instead */ @Deprecated public IconicsDrawable actionBarSize() { return sizeDp(ANDROID_ACTIONBAR_ICON_SIZE_DP); } /** * Sets the size and the Padding to the correct values to be used for the actionBar / toolBar * * @return */ public IconicsDrawable actionBar() { sizeDp(ANDROID_ACTIONBAR_ICON_SIZE_DP); paddingDp(ANDROID_ACTIONBAR_ICON_SIZE_PADDING_DP); return this; } /** * Set the size of the drawable. * * @param dimenRes The dimension resource. * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizeRes(@DimenRes int dimenRes) { return sizePx(mContext.getResources().getDimensionPixelSize(dimenRes)); } /** * Set the size of the drawable. * * @param size The size in density-independent pixels (dp). * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizeDp(int size) { return sizePx(Utils.convertDpToPx(mContext, size)); } /** * Set the size of the drawable. * * @param size The size in pixels (px). * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizePx(int size) { this.mSizeX = size; this.mSizeY = size; setBounds(0, 0, size, size); invalidateSelf(); return this; } /** * Set the size of the drawable. * * @param dimenResX The dimension resource. * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizeResX(@DimenRes int dimenResX) { return sizePxX(mContext.getResources().getDimensionPixelSize(dimenResX)); } /** * Set the size of the drawable. * * @param sizeX The size in density-independent pixels (dp). * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizeDpX(int sizeX) { return sizePxX(Utils.convertDpToPx(mContext, sizeX)); } /** * Set the size of the drawable. * * @param sizeX The size in pixels (px). * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizePxX(int sizeX) { this.mSizeX = sizeX; setBounds(0, 0, mSizeX, mSizeY); invalidateSelf(); return this; } /** * Set the size of the drawable. * * @param dimenResY The dimension resource. * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizeResY(@DimenRes int dimenResY) { return sizePxY(mContext.getResources().getDimensionPixelSize(dimenResY)); } /** * Set the size of the drawable. * * @param sizeY The size in density-independent pixels (dp). * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizeDpY(int sizeY) { return sizePxY(Utils.convertDpToPx(mContext, sizeY)); } /** * Set the size of the drawable. * * @param sizeY The size in pixels (px). * @return The current IconExtDrawable for chaining. */ public IconicsDrawable sizePxY(int sizeY) { this.mSizeY = sizeY; setBounds(0, 0, mSizeX, mSizeY); invalidateSelf(); return this; } /** * Set contour color for the. * * @param contourColor * @return The current IconExtDrawable for chaining. */ public IconicsDrawable contourColor(@ColorInt int contourColor) { int red = Color.red(contourColor); int green = Color.green(contourColor); int blue = Color.blue(contourColor); mContourPaint.setColor(Color.rgb(red, green, blue)); mContourPaint.setAlpha(Color.alpha(contourColor)); invalidateSelf(); return this; } /** * Set contour color from color res. * * @param contourColorRes * @return The current IconExtDrawable for chaining. */ public IconicsDrawable contourColorRes(@ColorRes int contourColorRes) { return contourColor(ContextCompat.getColor(mContext, contourColorRes)); } /** * set background color * * @param backgroundColor * @return */ public IconicsDrawable backgroundColor(@ColorInt int backgroundColor) { this.mBackgroundPaint.setColor(backgroundColor); this.mRoundedCornerRx = 0; this.mRoundedCornerRy = 0; return this; } /** * set background color from res * * @param backgroundColorRes * @return */ public IconicsDrawable backgroundColorRes(@ColorRes int backgroundColorRes) { return backgroundColor(ContextCompat.getColor(mContext, backgroundColorRes)); } /** * set rounded corner from res * * @param roundedCornerRxRes * @return */ public IconicsDrawable roundedCornersRxRes(@DimenRes int roundedCornerRxRes) { this.mRoundedCornerRx = mContext.getResources().getDimensionPixelSize(roundedCornerRxRes); return this; } /** * set rounded corner from dp * * @param roundedCornerRxDp * @return */ public IconicsDrawable roundedCornersRxDp(int roundedCornerRxDp) { this.mRoundedCornerRx = Utils.convertDpToPx(mContext, roundedCornerRxDp); return this; } /** * set rounded corner from px * * @param roundedCornerRxPx * @return */ public IconicsDrawable roundedCornersRxPx(int roundedCornerRxPx) { this.mRoundedCornerRx = roundedCornerRxPx; return this; } /** * set rounded corner from res * * @param roundedCornerRyRes * @return */ public IconicsDrawable roundedCornersRyRes(@DimenRes int roundedCornerRyRes) { this.mRoundedCornerRy = mContext.getResources().getDimensionPixelSize(roundedCornerRyRes); return this; } /** * set rounded corner from dp * * @param roundedCornerRyDp * @return */ public IconicsDrawable roundedCornersRyDp(int roundedCornerRyDp) { this.mRoundedCornerRy = Utils.convertDpToPx(mContext, roundedCornerRyDp); return this; } /** * set rounded corner from px * * @param roundedCornerRyPx * @return */ public IconicsDrawable roundedCornersRyPx(int roundedCornerRyPx) { this.mRoundedCornerRy = roundedCornerRyPx; return this; } /** * set rounded corner from res * * @param roundedCornerRes * @return */ public IconicsDrawable roundedCornersRes(@DimenRes int roundedCornerRes) { this.mRoundedCornerRx = mContext.getResources().getDimensionPixelSize(roundedCornerRes); this.mRoundedCornerRy = this.mRoundedCornerRx; return this; } /** * set rounded corner from dp * * @param roundedCornerDp * @return */ public IconicsDrawable roundedCornersDp(int roundedCornerDp) { this.mRoundedCornerRx = Utils.convertDpToPx(mContext, roundedCornerDp); this.mRoundedCornerRy = this.mRoundedCornerRx; return this; } /** * set rounded corner from px * * @param roundedCornerPx * @return */ public IconicsDrawable roundedCornersPx(int roundedCornerPx) { this.mRoundedCornerRx = roundedCornerPx; this.mRoundedCornerRy = this.mRoundedCornerRx; return this; } /** * Set contour width from an dimen res for the icon * * @param contourWidthRes * @return The current IconExtDrawable for chaining. */ public IconicsDrawable contourWidthRes(@DimenRes int contourWidthRes) { return contourWidthPx(mContext.getResources().getDimensionPixelSize(contourWidthRes)); } /** * Set contour width from dp for the icon * * @param contourWidthDp * @return The current IconExtDrawable for chaining. */ public IconicsDrawable contourWidthDp(int contourWidthDp) { return contourWidthPx(Utils.convertDpToPx(mContext, contourWidthDp)); } /** * Set contour width for the icon. * * @param contourWidth * @return The current IconExtDrawable for chaining. */ public IconicsDrawable contourWidthPx(int contourWidth) { mContourWidth = contourWidth; mContourPaint.setStrokeWidth(mContourWidth); drawContour(true); invalidateSelf(); return this; } /** * Enable/disable contour drawing. * * @param drawContour * @return The current IconExtDrawable for chaining. */ public IconicsDrawable drawContour(boolean drawContour) { if (mDrawContour != drawContour) { mDrawContour = drawContour; if (mDrawContour) { mIconPadding += mContourWidth; } else { mIconPadding -= mContourWidth; } invalidateSelf(); } return this; } /** * Set the colorFilter * * @param cf * @return The current IconExtDrawable for chaining. */ public IconicsDrawable colorFilter(ColorFilter cf) { setColorFilter(cf); return this; } /** * Sets the opacity * * @param alpha * @return The current IconExtDrawable for chaining. */ public IconicsDrawable alpha(int alpha) { setAlpha(alpha); return this; } /** * Sets the style * * @param style * @return The current IconExtDrawable for chaining. */ public IconicsDrawable style(Paint.Style style) { mIconPaint.setStyle(style); return this; } /** * sets the typeface of the drawable * NOTE THIS WILL OVERWRITE THE ICONFONT! * * @param typeface * @return */ public IconicsDrawable typeface(Typeface typeface) { mIconPaint.setTypeface(typeface); return this; } @Override public void draw(Canvas canvas) { if (mIcon != null || mPlainIcon != null) { final Rect viewBounds = getBounds(); updatePaddingBounds(viewBounds); updateTextSize(viewBounds); offsetIcon(viewBounds); if (mBackgroundPaint != null && mRoundedCornerRy > -1 && mRoundedCornerRx > -1) { canvas.drawRoundRect(new RectF(0, 0, viewBounds.width(), viewBounds.height()), mRoundedCornerRx, mRoundedCornerRy, mBackgroundPaint); } mPath.close(); if (mDrawContour) { canvas.drawPath(mPath, mContourPaint); } mIconPaint.setAlpha(mAlpha); canvas.drawPath(mPath, mIconPaint); } } @Override public boolean isStateful() { return true; } @Override public boolean setState(int[] stateSet) { setAlpha(mAlpha); return true; } @Override public int getIntrinsicWidth() { return mSizeX; } @Override public int getIntrinsicHeight() { return mSizeY; } @Override public int getOpacity() { return PixelFormat.OPAQUE; } @Override public void setAlpha(int alpha) { mIconPaint.setAlpha(alpha); mAlpha = alpha; } @Override public int getAlpha() { return mAlpha; } /** * just a helper method to get the alpha value * * @return */ public int getCompatAlpha() { return mAlpha; } @Override public void setColorFilter(ColorFilter cf) { mIconPaint.setColorFilter(cf); } /** * Creates a BitMap to use in Widgets or anywhere else * * @return bitmap to set */ public Bitmap toBitmap() { if (mSizeX == -1 || mSizeY == -1) { this.actionBar(); } final Bitmap bitmap = Bitmap.createBitmap(this.getIntrinsicWidth(), this.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); this.style(Paint.Style.FILL); final Canvas canvas = new Canvas(bitmap); this.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); this.draw(canvas); return bitmap; } //------------------------------------------ // PRIVATE HELPER METHODS //------------------------------------------ /** * Update the Padding Bounds * * @param viewBounds */ private void updatePaddingBounds(Rect viewBounds) { if (mIconPadding >= 0 && !(mIconPadding * 2 > viewBounds.width()) && !(mIconPadding * 2 > viewBounds.height())) { mPaddingBounds.set(viewBounds.left + mIconPadding, viewBounds.top + mIconPadding, viewBounds.right - mIconPadding, viewBounds.bottom - mIconPadding); } } /** * Update the TextSize * * @param viewBounds */ private void updateTextSize(Rect viewBounds) { float textSize = (float) viewBounds.height() * 2; mIconPaint.setTextSize(textSize); String textValue = mIcon != null ? String.valueOf(mIcon.getCharacter()) : String.valueOf(mPlainIcon); mIconPaint.getTextPath(textValue, 0, textValue.length(), 0, viewBounds.height(), mPath); mPath.computeBounds(mPathBounds, true); float deltaWidth = ((float) mPaddingBounds.width() / mPathBounds.width()); float deltaHeight = ((float) mPaddingBounds.height() / mPathBounds.height()); float delta = (deltaWidth < deltaHeight) ? deltaWidth : deltaHeight; textSize *= delta; mIconPaint.setTextSize(textSize); mIconPaint.getTextPath(textValue, 0, textValue.length(), 0, viewBounds.height(), mPath); mPath.computeBounds(mPathBounds, true); } /** * Set the icon offset * * @param viewBounds */ private void offsetIcon(Rect viewBounds) { float startX = viewBounds.centerX() - (mPathBounds.width() / 2); float offsetX = startX - mPathBounds.left; float startY = viewBounds.centerY() - (mPathBounds.height() / 2); float offsetY = startY - (mPathBounds.top); mPath.offset(offsetX + mIconOffsetX, offsetY + mIconOffsetY); } /** * clones the icon * * @return */ public IconicsDrawable clone() { IconicsDrawable iconicsDrawable = new IconicsDrawable(mContext).paddingPx(mIconPadding) .roundedCornersRxPx(mRoundedCornerRx).roundedCornersRyPx(mRoundedCornerRy).sizePxX(mSizeX) .sizePxY(mSizeY).iconOffsetXPx(mIconOffsetX).iconOffsetYPx(mIconOffsetY) .contourColor(mContourPaint.getColor()).contourWidthPx(mContourWidth) .backgroundColor(mBackgroundPaint.getColor()).color(mIconPaint.getColor()).alpha(mAlpha) .drawContour(mDrawContour).typeface(mIconPaint.getTypeface()); if (mIcon != null) { iconicsDrawable.icon(mIcon); } else if (mPlainIcon != null) { iconicsDrawable.iconText(mPlainIcon); } return iconicsDrawable; } }