package com.pchmn.materialchips.util; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.support.v4.content.ContextCompat; import android.text.TextPaint; import android.util.Log; import com.pchmn.materialchips.R; /** * Used to create a {@link Bitmap} that contains a letter used in the English * alphabet or digit, if there is no letter or digit available, a default image * is shown instead */ public class LetterTileProvider { /** The number of available tile colors (see R.array.letter_tile_colors) */ private static final int NUM_OF_TILE_COLORS = 8; /** The {@link TextPaint} used to draw the letter onto the tile */ private final TextPaint mPaint = new TextPaint(); /** The bounds that enclose the letter */ private final Rect mBounds = new Rect(); /** The {@link Canvas} to draw on */ private final Canvas mCanvas = new Canvas(); /** The first char of the name being displayed */ private final char[] mFirstChar = new char[1]; /** The background colors of the tile */ private final TypedArray mColors; /** The font size used to display the letter */ private final int mTileLetterFontSize; /** The default image to display */ private final Bitmap mDefaultBitmap; /** Width */ private final int mWidth; /** Height */ private final int mHeight; /** * Constructor for LetterTileProvider * * @param context The {@link Context} to use */ public LetterTileProvider(Context context) { final Resources res = context.getResources(); mPaint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); mPaint.setColor(Color.WHITE); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setAntiAlias(true); mColors = res.obtainTypedArray(R.array.letter_tile_colors); mTileLetterFontSize = res.getDimensionPixelSize(R.dimen.tile_letter_font_size); //mDefaultBitmap = BitmapFactory.decodeResource(res, android.R.drawable.); mDefaultBitmap = drawableToBitmap(ContextCompat.getDrawable(context, R.drawable.ic_person_white_24dp)); mWidth = res.getDimensionPixelSize(R.dimen.letter_tile_size); mHeight = res.getDimensionPixelSize(R.dimen.letter_tile_size); } /** * @param displayName The name used to create the letter for the tile * @return A {@link Bitmap} that contains a letter used in the English * alphabet or digit, if there is no letter or digit available, a * default image is shown instead */ public Bitmap getLetterTile(String displayName) { // workaround if(displayName == null || displayName.length() == 0) return null; final Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); final char firstChar = displayName.charAt(0); final Canvas c = mCanvas; c.setBitmap(bitmap); c.drawColor(pickColor(displayName)); if (isLetterOrDigit(firstChar)) { mFirstChar[0] = Character.toUpperCase(firstChar); mPaint.setTextSize(mTileLetterFontSize); mPaint.getTextBounds(mFirstChar, 0, 1, mBounds); c.drawText(mFirstChar, 0, 1, mWidth / 2, mHeight / 2 + (mBounds.bottom - mBounds.top) / 2, mPaint); } else { // (32 - 24) / 2 = 4 c.drawBitmap(mDefaultBitmap, ViewUtil.dpToPx(4), ViewUtil.dpToPx(4), null); } return bitmap; } /** * @param displayName The name used to create the letter for the tile * @return A circular {@link Bitmap} that contains a letter used in the English * alphabet or digit, if there is no letter or digit available, a * default image is shown instead */ public Bitmap getCircularLetterTile(String displayName) { // workaround if(displayName == null || displayName.length() == 0) displayName = "."; final Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); final char firstChar = displayName.charAt(0); final Canvas c = mCanvas; c.setBitmap(bitmap); c.drawColor(pickColor(displayName)); if (isLetterOrDigit(firstChar)) { mFirstChar[0] = Character.toUpperCase(firstChar); mPaint.setTextSize(mTileLetterFontSize); mPaint.getTextBounds(mFirstChar, 0, 1, mBounds); c.drawText(mFirstChar, 0, 1, mWidth / 2, mHeight / 2 + (mBounds.bottom - mBounds.top) / 2, mPaint); } else { // (32 - 24) / 2 = 4 c.drawBitmap(mDefaultBitmap, ViewUtil.dpToPx(4), ViewUtil.dpToPx(4), null); } return getCircularBitmap(bitmap); } /** * @param c The char to check * @return True if c is in the English alphabet or is a digit, * false otherwise */ private static boolean isLetterOrDigit(char c) { //return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9'; return Character.isLetterOrDigit(c); } /** * @param key The key used to generate the tile color * @return A new or previously chosen color for key used as the * tile background color */ private int pickColor(String key) { // String.hashCode() is not supposed to change across java versions, so // this should guarantee the same key always maps to the same color final int color = Math.abs(key.hashCode()) % NUM_OF_TILE_COLORS; try { return mColors.getColor(color, Color.BLACK); } finally { // bug with recycler view //mColors.recycle(); } } private Bitmap getCircularBitmap(Bitmap bitmap) { Bitmap output; if (bitmap.getWidth() > bitmap.getHeight()) { output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); } else { output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Bitmap.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()); float r = 0; if (bitmap.getWidth() > bitmap.getHeight()) { r = bitmap.getHeight() / 2; } else { r = bitmap.getWidth() / 2; } paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawCircle(r, r, r, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; } public static Bitmap drawableToBitmap (Drawable drawable) { Bitmap bitmap = null; if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if(bitmapDrawable.getBitmap() != null) { return bitmapDrawable.getBitmap(); } } if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } }