open-keychain/extern/MaterialChipsInput/src/main/java/com/pchmn/materialchips/util/LetterTileProvider.java
2018-07-04 13:59:21 +02:00

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;
}
}