222 lines
8 KiB
Java
222 lines
8 KiB
Java
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 <code>LetterTileProvider</code>
|
|
*
|
|
* @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 <code>c</code> 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 <code>key</code> 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;
|
|
}
|
|
|
|
}
|