Refactoring in ContactDrawable to pick a color.
Strategy pattern to pick a color in the letter tile.
Thanks to this, subimplementations can draw the letter tiles
for avatars differently, and still use the all the features
of the ContactDrawable.
Bug: 16378212 Draw letter tile for non-Gmail avatars
Change-Id: I999aa43724ba0e4dd23f2106133aaa34ee3ba008
diff --git a/src/com/android/mail/bitmap/ColorPicker.java b/src/com/android/mail/bitmap/ColorPicker.java
new file mode 100644
index 0000000..f8303d9
--- /dev/null
+++ b/src/com/android/mail/bitmap/ColorPicker.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ * Licensed to The Android Open Source Project.
+ *
+ * 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 com.android.mail.bitmap;
+
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+
+import com.android.mail.R;
+
+public interface ColorPicker {
+ /**
+ * Returns the color to use for the given email address.
+ * This method should return the same output for the same input.
+ * @param email The normalized email address.
+ * @return The color value in the format {@code 0xAARRGGBB}.
+ */
+ public int pickColor(final String email);
+
+ /**
+ * A simple implementation of a {@link ColorPicker}.
+ */
+ public class PaletteColorPicker implements ColorPicker {
+ /**
+ * The palette of colors, inflated from {@code R.array.letter_tile_colors}.
+ */
+ private static TypedArray sColors;
+
+ /**
+ * Cached value of {@code sColors.length()}.
+ */
+ private static int sColorCount;
+
+ /**
+ * Default color returned if the one chosen from {@code R.array.letter_tile_colors} is
+ * a {@link android.content.res.ColorStateList}.
+ */
+ private static int sDefaultColor;
+
+ public PaletteColorPicker(Resources res) {
+ if (sColors == null) {
+ sColors = res.obtainTypedArray(R.array.letter_tile_colors);
+ sColorCount = sColors.length();
+ sDefaultColor = res.getColor(R.color.letter_tile_default_color);
+ }
+ }
+
+ @Override
+ public int pickColor(final String email) {
+ final int color = Math.abs(email.hashCode()) % sColorCount;
+ return sColors.getColor(color, sDefaultColor);
+ }
+ }
+}
diff --git a/src/com/android/mail/bitmap/ContactDrawable.java b/src/com/android/mail/bitmap/ContactDrawable.java
index 7b10690..34983bf 100644
--- a/src/com/android/mail/bitmap/ContactDrawable.java
+++ b/src/com/android/mail/bitmap/ContactDrawable.java
@@ -16,7 +16,6 @@
package com.android.mail.bitmap;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
@@ -48,6 +47,7 @@
*/
public class ContactDrawable extends Drawable implements ContactDrawableInterface {
+ private final Resources mResources;
private BitmapCache mCache;
private ContactResolver mContactResolver;
@@ -56,9 +56,7 @@
private final Paint mPaint;
/** Letter tile */
- private static TypedArray sColors;
- private static int sColorCount;
- private static int sDefaultColor;
+ private static ColorPicker sTileColorPicker;
private static int sTileLetterFontSize;
private static int sTileFontColor;
private static Bitmap DEFAULT_AVATAR;
@@ -76,6 +74,8 @@
private int mDecodeHeight;
public ContactDrawable(final Resources res) {
+ mResources = res;
+
mPaint = new Paint();
mPaint.setFilterBitmap(true);
mPaint.setDither(true);
@@ -95,10 +95,7 @@
mMatrix = new Matrix();
- if (sColors == null) {
- sColors = res.obtainTypedArray(R.array.letter_tile_colors);
- sColorCount = sColors.length();
- sDefaultColor = res.getColor(R.color.letter_tile_default_color);
+ if (sTileLetterFontSize == 0) {
sTileLetterFontSize = res.getDimensionPixelSize(R.dimen.tile_letter_font_size);
sTileFontColor = res.getColor(R.color.letter_tile_font_color);
DEFAULT_AVATAR = BitmapFactory.decodeResource(res, R.drawable.ic_generic_man);
@@ -117,6 +114,26 @@
mContactResolver = contactResolver;
}
+ /**
+ * Sets the {@link ColorPicker} for the background tile used in letter avatars.
+ * @param colorPicker
+ */
+ public static void setTileColorPicker(ColorPicker colorPicker) {
+ sTileColorPicker = colorPicker;
+ }
+
+ /**
+ * Returns the color picker for the background tile used in the letter avatars.
+ * If none was set, initializes a simple {@link ColorPicker.PaletteColorPicker} first.
+ * @return non-null color picker.
+ */
+ public ColorPicker getTileColorPicker() {
+ if (sTileColorPicker == null) {
+ sTileColorPicker = new ColorPicker.PaletteColorPicker(mResources);
+ }
+ return sTileColorPicker;
+ }
+
@Override
public void draw(final Canvas canvas) {
final Rect bounds = getBounds();
@@ -171,7 +188,8 @@
// Draw background color.
final String email = mContactRequest.getEmail();
- sPaint.setColor(pickColor(email));
+ // The email should already have been normalized by the ContactRequest.
+ sPaint.setColor(getTileColorPicker().pickColor(email));
sPaint.setAlpha(mPaint.getAlpha());
drawCircle(canvas, bounds, sPaint);
@@ -203,14 +221,6 @@
canvas.drawCircle(bounds.centerX(), bounds.centerY(), bounds.width() / 2, paint);
}
- private static int pickColor(final String email) {
- // String.hashCode() implementation is not supposed to change across java versions, so
- // this should guarantee the same email address always maps to the same color.
- // The email should already have been normalized by the ContactRequest.
- final int color = Math.abs(email.hashCode()) % sColorCount;
- return sColors.getColor(color, sDefaultColor);
- }
-
private static boolean isEnglishLetterOrDigit(final char c) {
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9');
}
diff --git a/src/com/android/mail/photomanager/LetterTileProvider.java b/src/com/android/mail/photomanager/LetterTileProvider.java
index bf17acb..ca70e72 100644
--- a/src/com/android/mail/photomanager/LetterTileProvider.java
+++ b/src/com/android/mail/photomanager/LetterTileProvider.java
@@ -29,6 +29,7 @@
import android.text.TextUtils;
import com.android.mail.R;
+import com.android.mail.bitmap.ColorPicker;
import com.android.mail.ui.ImageCanvas.Dimensions;
import com.android.mail.utils.BitmapUtil;
import com.android.mail.utils.LogTag;
@@ -54,14 +55,11 @@
private final int mTileLetterFontSizeSmall;
private final int mTileFontColor;
private final TextPaint mPaint = new TextPaint();
- private final TypedArray mColors;
- private final int mColorCount;
- private final int mDefaultColor;
private final Canvas mCanvas = new Canvas();
- private final Dimensions mDims = new Dimensions();
private final char[] mFirstChar = new char[1];
private static final int POSSIBLE_BITMAP_SIZES = 3;
+ private ColorPicker sTileColorPicker;
public LetterTileProvider(Context context) {
final Resources res = context.getResources();
@@ -80,9 +78,9 @@
mDefaultBitmap = BitmapFactory.decodeResource(res, R.drawable.ic_generic_man);
mDefaultBitmapCache = new Bitmap[POSSIBLE_BITMAP_SIZES];
- mColors = res.obtainTypedArray(R.array.letter_tile_colors);
- mColorCount = mColors.length();
- mDefaultColor = res.getColor(R.color.letter_tile_default_color);
+ if (sTileColorPicker == null) {
+ sTileColorPicker = new ColorPicker.PaletteColorPicker(res);
+ }
}
public Bitmap getLetterTile(final Dimensions dimensions, final String displayName,
@@ -100,7 +98,7 @@
final Canvas c = mCanvas;
c.setBitmap(bitmap);
- c.drawColor(pickColor(address));
+ c.drawColor(sTileColorPicker.pickColor(address));
// If its a valid English alphabet letter,
// draw the letter on top of the color
@@ -163,11 +161,4 @@
return mTileLetterFontSizeSmall;
}
}
-
- private int pickColor(String emailAddress) {
- // String.hashCode() implementation is not supposed to change across java versions, so
- // this should guarantee the same email address always maps to the same color.
- int color = Math.abs(emailAddress.hashCode()) % mColorCount;
- return mColors.getColor(color, mDefaultColor);
- }
}