summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable-hdpi/default_artist.pngbin4783 -> 0 bytes
-rw-r--r--res/drawable-hdpi/default_artwork_sm.pngbin18293 -> 0 bytes
-rw-r--r--res/drawable-hdpi/default_playlist.pngbin3823 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_album.pngbin0 -> 970 bytes
-rw-r--r--res/drawable-hdpi/ic_album_lg.pngbin0 -> 3416 bytes
-rw-r--r--res/drawable-hdpi/ic_artist.pngbin0 -> 1377 bytes
-rw-r--r--res/drawable-hdpi/ic_artist_lg.pngbin0 -> 4536 bytes
-rw-r--r--res/drawable-hdpi/ic_playlist.pngbin0 -> 1027 bytes
-rw-r--r--res/drawable-hdpi/ic_playlist_lg.pngbin0 -> 3345 bytes
-rw-r--r--res/drawable-mdpi/default_artist.pngbin3191 -> 0 bytes
-rw-r--r--res/drawable-mdpi/default_artwork_sm.pngbin17200 -> 0 bytes
-rw-r--r--res/drawable-mdpi/default_playlist.pngbin2380 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_album.pngbin0 -> 721 bytes
-rw-r--r--res/drawable-mdpi/ic_album_lg.pngbin0 -> 2016 bytes
-rw-r--r--res/drawable-mdpi/ic_artist.pngbin0 -> 962 bytes
-rw-r--r--res/drawable-mdpi/ic_artist_lg.pngbin0 -> 2855 bytes
-rw-r--r--res/drawable-mdpi/ic_playlist.pngbin0 -> 730 bytes
-rw-r--r--res/drawable-mdpi/ic_playlist_lg.pngbin0 -> 2059 bytes
-rw-r--r--res/drawable-xhdpi/default_artist.pngbin6742 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/default_artwork_sm.pngbin19232 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/default_playlist.pngbin5404 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_album.pngbin0 -> 1300 bytes
-rw-r--r--res/drawable-xhdpi/ic_album_lg.pngbin0 -> 4967 bytes
-rw-r--r--res/drawable-xhdpi/ic_artist.pngbin0 -> 1863 bytes
-rw-r--r--res/drawable-xhdpi/ic_artist_lg.pngbin0 -> 6494 bytes
-rw-r--r--res/drawable-xhdpi/ic_playlist.pngbin0 -> 1322 bytes
-rw-r--r--res/drawable-xhdpi/ic_playlist_lg.pngbin0 -> 4891 bytes
-rw-r--r--res/drawable-xxhdpi/default_artist.pngbin11197 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/default_artwork_sm.pngbin4503 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/default_playlist.pngbin8917 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_album.pngbin0 -> 2017 bytes
-rw-r--r--res/drawable-xxhdpi/ic_album_lg.pngbin0 -> 11010 bytes
-rw-r--r--res/drawable-xxhdpi/ic_artist.pngbin0 -> 2819 bytes
-rw-r--r--res/drawable-xxhdpi/ic_artist_lg.pngbin0 -> 12047 bytes
-rw-r--r--res/drawable-xxhdpi/ic_playlist.pngbin0 -> 2056 bytes
-rw-r--r--res/drawable-xxhdpi/ic_playlist_lg.pngbin0 -> 9381 bytes
-rw-r--r--res/layout-v16/notification_template_expanded_base.xml1
-rw-r--r--res/layout/app_widget_large.xml1
-rw-r--r--res/layout/app_widget_large_alternate.xml1
-rw-r--r--res/layout/app_widget_small.xml1
-rw-r--r--res/layout/list_item_common.xml2
-rw-r--r--res/layout/notification_template_base.xml1
-rw-r--r--res/values/colors.xml14
-rw-r--r--res/values/dimens.xml2
-rw-r--r--res/values/donottranslate.xml2
-rw-r--r--res/values/strings.xml1
-rw-r--r--src/com/cyngn/eleven/cache/ImageFetcher.java44
-rw-r--r--src/com/cyngn/eleven/cache/ImageWorker.java132
-rw-r--r--src/com/cyngn/eleven/cache/PlaylistWorkerTask.java77
-rw-r--r--src/com/cyngn/eleven/menu/PhotoSelectionDialog.java9
-rw-r--r--src/com/cyngn/eleven/ui/fragments/FadingBarFragment.java2
-rw-r--r--src/com/cyngn/eleven/widgets/LetterTileDrawable.java328
52 files changed, 453 insertions, 165 deletions
diff --git a/res/drawable-hdpi/default_artist.png b/res/drawable-hdpi/default_artist.png
deleted file mode 100644
index cc2fc45..0000000
--- a/res/drawable-hdpi/default_artist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/default_artwork_sm.png b/res/drawable-hdpi/default_artwork_sm.png
deleted file mode 100644
index e5e1f0e..0000000
--- a/res/drawable-hdpi/default_artwork_sm.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/default_playlist.png b/res/drawable-hdpi/default_playlist.png
deleted file mode 100644
index d906e25..0000000
--- a/res/drawable-hdpi/default_playlist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_album.png b/res/drawable-hdpi/ic_album.png
new file mode 100644
index 0000000..3d2c389
--- /dev/null
+++ b/res/drawable-hdpi/ic_album.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_album_lg.png b/res/drawable-hdpi/ic_album_lg.png
new file mode 100644
index 0000000..989d0b6
--- /dev/null
+++ b/res/drawable-hdpi/ic_album_lg.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_artist.png b/res/drawable-hdpi/ic_artist.png
new file mode 100644
index 0000000..b839a8b
--- /dev/null
+++ b/res/drawable-hdpi/ic_artist.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_artist_lg.png b/res/drawable-hdpi/ic_artist_lg.png
new file mode 100644
index 0000000..ef38a96
--- /dev/null
+++ b/res/drawable-hdpi/ic_artist_lg.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_playlist.png b/res/drawable-hdpi/ic_playlist.png
new file mode 100644
index 0000000..74876fa
--- /dev/null
+++ b/res/drawable-hdpi/ic_playlist.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_playlist_lg.png b/res/drawable-hdpi/ic_playlist_lg.png
new file mode 100644
index 0000000..bb9a734
--- /dev/null
+++ b/res/drawable-hdpi/ic_playlist_lg.png
Binary files differ
diff --git a/res/drawable-mdpi/default_artist.png b/res/drawable-mdpi/default_artist.png
deleted file mode 100644
index 24c2c43..0000000
--- a/res/drawable-mdpi/default_artist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/default_artwork_sm.png b/res/drawable-mdpi/default_artwork_sm.png
deleted file mode 100644
index fbe603a..0000000
--- a/res/drawable-mdpi/default_artwork_sm.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/default_playlist.png b/res/drawable-mdpi/default_playlist.png
deleted file mode 100644
index 3bacabc..0000000
--- a/res/drawable-mdpi/default_playlist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_album.png b/res/drawable-mdpi/ic_album.png
new file mode 100644
index 0000000..7ebc0e0
--- /dev/null
+++ b/res/drawable-mdpi/ic_album.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_album_lg.png b/res/drawable-mdpi/ic_album_lg.png
new file mode 100644
index 0000000..a5c40a3
--- /dev/null
+++ b/res/drawable-mdpi/ic_album_lg.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_artist.png b/res/drawable-mdpi/ic_artist.png
new file mode 100644
index 0000000..d1bf6cb
--- /dev/null
+++ b/res/drawable-mdpi/ic_artist.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_artist_lg.png b/res/drawable-mdpi/ic_artist_lg.png
new file mode 100644
index 0000000..3b8f6cf
--- /dev/null
+++ b/res/drawable-mdpi/ic_artist_lg.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_playlist.png b/res/drawable-mdpi/ic_playlist.png
new file mode 100644
index 0000000..16c2c83
--- /dev/null
+++ b/res/drawable-mdpi/ic_playlist.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_playlist_lg.png b/res/drawable-mdpi/ic_playlist_lg.png
new file mode 100644
index 0000000..aea793b
--- /dev/null
+++ b/res/drawable-mdpi/ic_playlist_lg.png
Binary files differ
diff --git a/res/drawable-xhdpi/default_artist.png b/res/drawable-xhdpi/default_artist.png
deleted file mode 100644
index f93deac..0000000
--- a/res/drawable-xhdpi/default_artist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/default_artwork_sm.png b/res/drawable-xhdpi/default_artwork_sm.png
deleted file mode 100644
index 6df4dba..0000000
--- a/res/drawable-xhdpi/default_artwork_sm.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/default_playlist.png b/res/drawable-xhdpi/default_playlist.png
deleted file mode 100644
index 627bdc0..0000000
--- a/res/drawable-xhdpi/default_playlist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_album.png b/res/drawable-xhdpi/ic_album.png
new file mode 100644
index 0000000..7e259f7
--- /dev/null
+++ b/res/drawable-xhdpi/ic_album.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_album_lg.png b/res/drawable-xhdpi/ic_album_lg.png
new file mode 100644
index 0000000..68cb298
--- /dev/null
+++ b/res/drawable-xhdpi/ic_album_lg.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_artist.png b/res/drawable-xhdpi/ic_artist.png
new file mode 100644
index 0000000..43a3e43
--- /dev/null
+++ b/res/drawable-xhdpi/ic_artist.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_artist_lg.png b/res/drawable-xhdpi/ic_artist_lg.png
new file mode 100644
index 0000000..849957e
--- /dev/null
+++ b/res/drawable-xhdpi/ic_artist_lg.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_playlist.png b/res/drawable-xhdpi/ic_playlist.png
new file mode 100644
index 0000000..22defcc
--- /dev/null
+++ b/res/drawable-xhdpi/ic_playlist.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_playlist_lg.png b/res/drawable-xhdpi/ic_playlist_lg.png
new file mode 100644
index 0000000..d1ccedd
--- /dev/null
+++ b/res/drawable-xhdpi/ic_playlist_lg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/default_artist.png b/res/drawable-xxhdpi/default_artist.png
deleted file mode 100644
index c117eb3..0000000
--- a/res/drawable-xxhdpi/default_artist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/default_artwork_sm.png b/res/drawable-xxhdpi/default_artwork_sm.png
deleted file mode 100644
index 19b0e50..0000000
--- a/res/drawable-xxhdpi/default_artwork_sm.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/default_playlist.png b/res/drawable-xxhdpi/default_playlist.png
deleted file mode 100644
index df873ed..0000000
--- a/res/drawable-xxhdpi/default_playlist.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_album.png b/res/drawable-xxhdpi/ic_album.png
new file mode 100644
index 0000000..a87c660
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_album.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_album_lg.png b/res/drawable-xxhdpi/ic_album_lg.png
new file mode 100644
index 0000000..022b098
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_album_lg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_artist.png b/res/drawable-xxhdpi/ic_artist.png
new file mode 100644
index 0000000..6dc97ef
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_artist.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_artist_lg.png b/res/drawable-xxhdpi/ic_artist_lg.png
new file mode 100644
index 0000000..b3eb2fd
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_artist_lg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_playlist.png b/res/drawable-xxhdpi/ic_playlist.png
new file mode 100644
index 0000000..76280f9
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_playlist.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_playlist_lg.png b/res/drawable-xxhdpi/ic_playlist_lg.png
new file mode 100644
index 0000000..c082480
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_playlist_lg.png
Binary files differ
diff --git a/res/layout-v16/notification_template_expanded_base.xml b/res/layout-v16/notification_template_expanded_base.xml
index ba1f807..2b452ae 100644
--- a/res/layout-v16/notification_template_expanded_base.xml
+++ b/res/layout-v16/notification_template_expanded_base.xml
@@ -28,7 +28,6 @@
android:layout_height="@dimen/notification_expanded_height"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
- android:background="@drawable/default_artwork"
android:scaleType="fitXY" />
<LinearLayout
diff --git a/res/layout/app_widget_large.xml b/res/layout/app_widget_large.xml
index 1bf1f2d..65e528a 100644
--- a/res/layout/app_widget_large.xml
+++ b/res/layout/app_widget_large.xml
@@ -29,7 +29,6 @@
android:layout_height="@dimen/notification_expanded_height"
android:layout_rowSpan="3"
android:layout_marginBottom="@dimen/app_widget_bottom_margin"
- android:background="@drawable/default_artwork_sm"
android:scaleType="fitXY" />
<LinearLayout
diff --git a/res/layout/app_widget_large_alternate.xml b/res/layout/app_widget_large_alternate.xml
index df93316..6accbcf 100644
--- a/res/layout/app_widget_large_alternate.xml
+++ b/res/layout/app_widget_large_alternate.xml
@@ -27,7 +27,6 @@
android:id="@+id/app_widget_large_alternate_image"
android:layout_width="@dimen/app_widget_large_alternate_artwork_size"
android:layout_height="@dimen/app_widget_large_alternate_artwork_size"
- android:background="@drawable/default_artwork_sm"
android:scaleType="fitXY" />
<LinearLayout
diff --git a/res/layout/app_widget_small.xml b/res/layout/app_widget_small.xml
index 0539fd9..955f837 100644
--- a/res/layout/app_widget_small.xml
+++ b/res/layout/app_widget_small.xml
@@ -29,7 +29,6 @@
android:id="@+id/app_widget_small_image"
android:layout_width="@dimen/app_widget_small_artwork_size"
android:layout_height="@dimen/app_widget_small_artwork_size"
- android:background="@drawable/default_artwork_sm"
android:contentDescription="@null"
android:scaleType="centerInside" />
diff --git a/res/layout/list_item_common.xml b/res/layout/list_item_common.xml
index b4ef0c7..0bf966f 100644
--- a/res/layout/list_item_common.xml
+++ b/res/layout/list_item_common.xml
@@ -1,5 +1,5 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <com.cyngn.eleven.widgets.SquareImageView
+ <ImageView
android:id="@+id/image"
android:layout_width="@dimen/list_item_image_width"
android:layout_height="@dimen/list_item_image_height"
diff --git a/res/layout/notification_template_base.xml b/res/layout/notification_template_base.xml
index 5af6514..2fc66ff 100644
--- a/res/layout/notification_template_base.xml
+++ b/res/layout/notification_template_base.xml
@@ -27,7 +27,6 @@
android:id="@+id/notification_base_image"
android:layout_width="@dimen/notification_big_icon_width"
android:layout_height="@dimen/notification_big_icon_height"
- android:background="@drawable/default_artwork"
android:gravity="center" />
<LinearLayout
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 92b6fb0..8a373ee 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -115,4 +115,18 @@
<!-- Background Lyrics Color -->
<color name="lyrics_background_color">#b2000000</color>
+
+ <!-- Letter tile colors -->
+ <color name="letter_tile_default_color">#cccccc</color>
+ <color name="letter_tile_font_color">#ffffff</color>
+ <array name="letter_tile_colors">
+ <item>#9237A2</item>
+ <item>#4B498C</item>
+ <item>#4E5BA7</item>
+ <item>#41A4F4</item>
+ <item>#10887C</item>
+ <item>#689144</item>
+ <item>#B9BF45</item>
+ <item>#757578</item>
+ </array>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index cd80a8c..268113e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -207,4 +207,6 @@
<!-- General consensus is to leave dividers at 1px instead of having different
partial scaled up values for different resolutions -->
<dimen name="divider_height">1px</dimen>
+
+ <item name="letter_to_tile_ratio" type="dimen">53%</item>
</resources>
diff --git a/res/values/donottranslate.xml b/res/values/donottranslate.xml
index e5841ed..a763ec4 100644
--- a/res/values/donottranslate.xml
+++ b/res/values/donottranslate.xml
@@ -22,4 +22,6 @@
<!-- Do not translate. This provides a separator for two strings -->
<string name="combine_two_strings" translatable="false">%1$s | %2$s</string>
+ <!-- Font family used when drawing letters for letter tile avatars. -->
+ <string name="letter_tile_letter_font_family" translatable="false">sans-serif-light</string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b7b550c..6f2dd84 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -201,5 +201,4 @@
<string name="search_title_playlists">All \"%s\" playlists</string>
<string name="duration_format"><xliff:g id="hours">%1$s</xliff:g> <xliff:g id="minutes">%2$s</xliff:g></string>
-
</resources>
diff --git a/src/com/cyngn/eleven/cache/ImageFetcher.java b/src/com/cyngn/eleven/cache/ImageFetcher.java
index e918d7b..c0a51c8 100644
--- a/src/com/cyngn/eleven/cache/ImageFetcher.java
+++ b/src/com/cyngn/eleven/cache/ImageFetcher.java
@@ -22,6 +22,7 @@ import com.cyngn.eleven.MusicPlaybackService;
import com.cyngn.eleven.cache.PlaylistWorkerTask.PlaylistWorkerType;
import com.cyngn.eleven.utils.MusicUtils;
import com.cyngn.eleven.widgets.BlurScrimImage;
+import com.cyngn.eleven.widgets.LetterTileDrawable;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -174,40 +175,6 @@ public class ImageFetcher extends ImageWorker {
}
/**
- * @param key The key used to find the image to return
- */
- public Bitmap getCachedBitmap(final String key) {
- if (mImageCache != null) {
- return mImageCache.getCachedBitmap(key);
- }
- return getDefaultArtwork();
- }
-
- /**
- * @param keyAlbum The key (album name) used to find the album art to return
- * @param keyArtist The key (artist name) used to find the album art to return
- */
- public Bitmap getCachedArtwork(final String keyAlbum, final String keyArtist) {
- return getCachedArtwork(keyAlbum, keyArtist,
- MusicUtils.getIdForAlbum(mContext, keyAlbum, keyArtist));
- }
-
- /**
- * @param keyAlbum The key (album name) used to find the album art to return
- * @param keyArtist The key (artist name) used to find the album art to return
- * @param keyId The key (album id) used to find the album art to return
- */
- public Bitmap getCachedArtwork(final String keyAlbum, final String keyArtist,
- final long keyId) {
- if (mImageCache != null) {
- return mImageCache.getCachedArtwork(mContext,
- generateAlbumCacheKey(keyAlbum, keyArtist),
- keyId);
- }
- return getDefaultArtwork();
- }
-
- /**
* Finds cached or downloads album art. Used in {@link MusicPlaybackService}
* to set the current album art in the notification and lock screen
*
@@ -222,10 +189,11 @@ public class ImageFetcher extends ImageWorker {
boolean smallArtwork) {
// Check the disk cache
Bitmap artwork = null;
+ String key = albumName;
if (artwork == null && albumName != null && mImageCache != null) {
- artwork = mImageCache.getBitmapFromDiskCache(
- generateAlbumCacheKey(albumName, artistName));
+ key = generateAlbumCacheKey(albumName, artistName);
+ artwork = mImageCache.getBitmapFromDiskCache(key);
}
if (artwork == null && albumId >= 0 && mImageCache != null) {
// Check for local artwork
@@ -234,7 +202,9 @@ public class ImageFetcher extends ImageWorker {
if (artwork != null) {
return artwork;
}
- return getDefaultArtwork(smallArtwork);
+
+ return LetterTileDrawable.createDefaultBitmap(mContext, key, ImageType.ALBUM, false,
+ smallArtwork);
}
/**
diff --git a/src/com/cyngn/eleven/cache/ImageWorker.java b/src/com/cyngn/eleven/cache/ImageWorker.java
index 414e481..e3cea92 100644
--- a/src/com/cyngn/eleven/cache/ImageWorker.java
+++ b/src/com/cyngn/eleven/cache/ImageWorker.java
@@ -20,7 +20,7 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.support.v8.renderscript.RenderScript;
-import android.text.TextUtils;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@@ -30,6 +30,7 @@ import com.cyngn.eleven.utils.ApolloUtils;
import com.cyngn.eleven.utils.ImageUtils;
import com.cyngn.eleven.widgets.BlurScrimImage;
import com.cyngn.eleven.cache.PlaylistWorkerTask.PlaylistWorkerType;
+import com.cyngn.eleven.widgets.LetterTileDrawable;
import java.lang.ref.WeakReference;
import java.util.Collections;
@@ -77,26 +78,6 @@ public abstract class ImageWorker {
private final ColorDrawable mTransparentDrawable;
/**
- * Default album art
- */
- private final Bitmap mDefault;
-
- /**
- * A small version of the default album art
- */
- private final Bitmap mDefaultSmall;
-
- /**
- * Default Artist art
- */
- private final Bitmap mDefaultArtist;
-
- /**
- * Default Playlist art
- */
- private final Bitmap mDefaultPlaylist;
-
- /**
* The Context to use
*/
protected Context mContext;
@@ -119,17 +100,6 @@ public abstract class ImageWorker {
}
mResources = mContext.getResources();
- // Create the default artwork
- mDefault = ((BitmapDrawable) mResources.getDrawable(R.drawable.default_artwork)).getBitmap();
- // Create the small version of the default artwork
- mDefaultSmall = ((BitmapDrawable) mResources.getDrawable(R.drawable.default_artwork_sm))
- .getBitmap();
- // Create the artist artwork
- mDefaultArtist = ((BitmapDrawable) mResources.getDrawable(R.drawable.default_artist))
- .getBitmap();
- // Create the playlist artwork
- mDefaultPlaylist = ((BitmapDrawable) mResources.getDrawable(R.drawable.default_playlist))
- .getBitmap();
// Create the transparent layer for the transition drawable
mTransparentDrawable = new ColorDrawable(Color.TRANSPARENT);
}
@@ -177,47 +147,14 @@ public abstract class ImageWorker {
}
/**
- * @return The default artwork
- */
- public Bitmap getDefaultArtwork() {
- return getDefaultArtwork(false);
- }
-
- /**
- * @param small returns the smaller version of the default artwork if true
- * @return The default artwork
+ * @return A new drawable of the default artwork
*/
- public Bitmap getDefaultArtwork(boolean small) {
- return small ? mDefaultSmall : mDefault;
- }
-
- /**
- * @return A new bitmap drawable of the default artwork
- */
- public BitmapDrawable getNewDefaultBitmapDrawable(ImageType imageType) {
- Bitmap targetBitmap = null;
-
- switch (imageType) {
- case ARTIST:
- targetBitmap = mDefaultArtist;
- break;
-
- case PLAYLIST:
- targetBitmap = mDefaultPlaylist;
- break;
-
- case ALBUM:
- default:
- targetBitmap = mDefault;
- break;
- }
-
- BitmapDrawable bitmapDrawable = new BitmapDrawable(mResources, targetBitmap);
- // No filter and no dither makes things much quicker
- bitmapDrawable.setFilterBitmap(false);
- bitmapDrawable.setDither(false);
-
- return bitmapDrawable;
+ public Drawable getNewDrawable(ImageType imageType, String name,
+ String identifier) {
+ LetterTileDrawable letterTileDrawable = new LetterTileDrawable(mContext);
+ letterTileDrawable.setTileDetails(name, identifier, imageType);
+ letterTileDrawable.setIsCircular(false);
+ return letterTileDrawable;
}
public static Bitmap getBitmapInBackground(final Context context, final ImageCache imageCache,
@@ -447,6 +384,25 @@ public abstract class ImageWorker {
}
/**
+ * Loads the default image into the image view given the image type
+ * @param imageView The {@link ImageView}
+ * @param imageType The type of image
+ */
+ public void loadDefaultImage(final ImageView imageView, final ImageType imageType,
+ final String name, final String identifier) {
+ if (imageView != null) {
+ // if an existing letter drawable exists, re-use it
+ Drawable existingDrawable = imageView.getDrawable();
+ if (existingDrawable != null && existingDrawable instanceof LetterTileDrawable) {
+ ((LetterTileDrawable)existingDrawable).setTileDetails(name, identifier, imageType);
+ } else {
+ imageView.setImageDrawable(getNewDrawable(imageType, name,
+ identifier));
+ }
+ }
+ }
+
+ /**
* Called to fetch the artist or album art.
*
* @param key The unique identifier for the image.
@@ -493,17 +449,28 @@ public abstract class ImageWorker {
imageView.setImageBitmap(lruBitmap);
}
} else {
- // if a background drawable hasn't been set, create one so that even if
- // the disk cache is paused we see something
- if (imageView.getBackground() == null) {
- imageView.setBackgroundDrawable(getNewDefaultBitmapDrawable(imageType));
+ // load the default image
+ if (imageType == ImageType.ARTIST) {
+ loadDefaultImage(imageView, imageType, artistName, key);
+ } else if (imageType == ImageType.ALBUM) {
+ // don't show letters for albums so pass in null as the display string
+ // because an album could have multiple artists, use the album id as the key here
+ loadDefaultImage(imageView, imageType, null, String.valueOf(albumId));
+ } else {
+ // don't show letters for playlists so pass in null as the display string
+ loadDefaultImage(imageView, imageType, null, key);
}
if (executePotentialWork(key, imageView)
&& imageView != null && !mImageCache.isDiskCachePaused()) {
+ Drawable fromDrawable = imageView.getDrawable();
+ if (fromDrawable == null) {
+ fromDrawable = mTransparentDrawable;
+ }
+
// Otherwise run the worker task
final SimpleBitmapWorkerTask bitmapWorkerTask = new SimpleBitmapWorkerTask(key,
- imageView, imageType, mTransparentDrawable, mContext, scaleImgToView);
+ imageView, imageType, fromDrawable, mContext, scaleImgToView);
final AsyncTaskContainer asyncTaskContainer = new AsyncTaskContainer(bitmapWorkerTask);
imageView.setTag(asyncTaskContainer);
@@ -546,15 +513,8 @@ public abstract class ImageWorker {
// Bitmap found in memory cache
imageView.setImageBitmap(lruBitmap);
} else {
- // if a background drawable hasn't been set, create one so that even if
- // the disk cache is paused we see something
- if (imageView.getBackground() == null) {
- if (type == PlaylistWorkerType.Artist) {
- imageView.setBackground(getNewDefaultBitmapDrawable(ImageType.ARTIST));
- } else if (type == PlaylistWorkerType.CoverArt) {
- imageView.setBackground(getNewDefaultBitmapDrawable(ImageType.PLAYLIST));
- }
- }
+ // load the default image
+ loadDefaultImage(imageView, ImageType.PLAYLIST, null, String.valueOf(playlistId));
}
// even though we may have found the image in the cache, we want to check if the playlist
diff --git a/src/com/cyngn/eleven/cache/PlaylistWorkerTask.java b/src/com/cyngn/eleven/cache/PlaylistWorkerTask.java
index ff9e0d9..011b6f6 100644
--- a/src/com/cyngn/eleven/cache/PlaylistWorkerTask.java
+++ b/src/com/cyngn/eleven/cache/PlaylistWorkerTask.java
@@ -4,18 +4,15 @@
package com.cyngn.eleven.cache;
import android.content.Context;
-import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.provider.MediaStore;
import android.widget.ImageView;
-import com.cyngn.eleven.R;
import com.cyngn.eleven.cache.ImageWorker.ImageType;
import com.cyngn.eleven.loaders.PlaylistSongLoader;
import com.cyngn.eleven.loaders.SortedCursor;
@@ -48,6 +45,9 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
// if the playlist has changed
protected final boolean mFoundInCache;
+ // because a cached image can be loaded, we use this flag to signal to remove that default image
+ protected boolean mFallbackToDefaultImage;
+
/**
* Constructor of <code>PlaylistWorkerTask</code>
* @param key the key of the image to store to
@@ -66,6 +66,7 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
mWorkerType = type;
mPlaylistStore = PlaylistArtworkStore.getInstance(mContext);
mFoundInCache = foundInCache;
+ mFallbackToDefaultImage = false;
}
/**
@@ -99,9 +100,15 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
bitmap = mImageCache.getCachedBitmap(mKey);
}
- // if we found a bitmap and we don't need an update, return it
- if (bitmap != null && !needsUpdate) {
- return createImageTransitionDrawable(bitmap);
+ // if we don't need an update, return something
+ if (!needsUpdate) {
+ if (bitmap != null) {
+ // if we found a bitmap, return it
+ return createImageTransitionDrawable(bitmap);
+ } else {
+ // otherwise return null since we don't need an update
+ return null;
+ }
}
// otherwise re-run the logic to get the bitmap
@@ -123,19 +130,15 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
mPlaylistStore.updateArtistArt(mPlaylistId);
// remove the cached image
mImageCache.removeFromCache(PlaylistArtworkStore.getArtistCacheKey(mPlaylistId));
- // go back to the default image
- BitmapDrawable drawable =
- (BitmapDrawable) mResources.getDrawable(R.drawable.default_artist);
- bitmap = drawable.getBitmap();
+ // revert back to default image
+ mFallbackToDefaultImage = true;
} else if (mWorkerType == PlaylistWorkerType.CoverArt) {
// update the timestamp
mPlaylistStore.updateCoverArt(mPlaylistId);
// remove the cached image
mImageCache.removeFromCache(PlaylistArtworkStore.getCoverCacheKey(mPlaylistId));
- // go back to the default image
- BitmapDrawable drawable =
- (BitmapDrawable) mResources.getDrawable(R.drawable.default_playlist);
- bitmap = drawable.getBitmap();
+ // revert back to default image
+ mFallbackToDefaultImage = true;
}
} else if (mWorkerType == PlaylistWorkerType.Artist) {
bitmap = loadTopArtist(sortedCursor);
@@ -230,16 +233,23 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
null, artistName, -1, ImageType.ARTIST);
} while (sortedCursor.moveToNext() && bitmap == null);
- sortedCursor.close();
+ if (bitmap == null) {
+ // if we can't find any artist images, try loading the top songs image
+ bitmap = mImageCache.getCachedBitmap(
+ PlaylistArtworkStore.getCoverCacheKey(mPlaylistId));
+ }
if (bitmap != null) {
// add the image to the cache
mImageCache.addBitmapToCache(mKey, bitmap, true);
-
- // store this artist name into the db
- mPlaylistStore.updateArtistArt(mPlaylistId);
+ } else {
+ mImageCache.removeFromCache(mKey);
+ mFallbackToDefaultImage = true;
}
+ // store the fact that we ran this code into the db to prevent multiple re-runs
+ mPlaylistStore.updateArtistArt(mPlaylistId);
+
return bitmap;
}
@@ -292,8 +302,6 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
}
} while (sortedCursor.moveToNext() && loadedBitmaps.size() < MAX_NUM_BITMAPS_TO_LOAD);
- sortedCursor.close();
-
// if we found at least 1 bitmap
if (loadedBitmaps.size() > 0) {
// get the first bitmap
@@ -324,22 +332,24 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
combinedCanvas.drawBitmap(loadedBitmaps.get(3), null,
new Rect(width / 2, height / 2, width, height), null);
+ combinedCanvas.release();
combinedCanvas = null;
bitmap = combinedBitmap;
}
+ }
- if (bitmap != null) {
- // add the image to the cache
- mImageCache.addBitmapToCache(mKey, bitmap, true);
+ // store the fact that we ran this code into the db to prevent multiple re-runs
+ mPlaylistStore.updateCoverArt(mPlaylistId);
- // store this artist name into the db
- mPlaylistStore.updateCoverArt(mPlaylistId);
- }
-
- return bitmap;
+ if (bitmap != null) {
+ // add the image to the cache
+ mImageCache.addBitmapToCache(mKey, bitmap, true);
+ } else {
+ mImageCache.removeFromCache(mKey);
+ mFallbackToDefaultImage = true;
}
- return null;
+ return bitmap;
}
/**
@@ -348,8 +358,13 @@ public class PlaylistWorkerTask extends BitmapWorkerTask<Void, Void, TransitionD
@Override
protected void onPostExecute(TransitionDrawable transitionDrawable) {
final ImageView imageView = getAttachedImageView();
- if (transitionDrawable != null && imageView != null) {
- imageView.setImageDrawable(transitionDrawable);
+ if (imageView != null) {
+ if (transitionDrawable != null) {
+ imageView.setImageDrawable(transitionDrawable);
+ } else if (mFallbackToDefaultImage) {
+ ImageFetcher.getInstance(mContext).loadDefaultImage(imageView,
+ ImageType.PLAYLIST, null, String.valueOf(mPlaylistId));
+ }
}
}
}
diff --git a/src/com/cyngn/eleven/menu/PhotoSelectionDialog.java b/src/com/cyngn/eleven/menu/PhotoSelectionDialog.java
index 7adc921..7d27da8 100644
--- a/src/com/cyngn/eleven/menu/PhotoSelectionDialog.java
+++ b/src/com/cyngn/eleven/menu/PhotoSelectionDialog.java
@@ -118,10 +118,11 @@ public class PhotoSelectionDialog extends DialogFragment {
private void setArtistChoices() {
// Select a photo from the gallery
mChoices.add(NEW_PHOTO, getString(R.string.new_photo));
+ /* Disable fetching image until we find a last.fm replacement
if (ApolloUtils.isOnline(getActivity())) {
// Option to fetch the old artist image
mChoices.add(OLD_PHOTO, getString(R.string.context_menu_fetch_artist_image));
- }
+ }*/
}
/**
@@ -130,11 +131,12 @@ public class PhotoSelectionDialog extends DialogFragment {
private void setAlbumChoices() {
// Select a photo from the gallery
mChoices.add(NEW_PHOTO, getString(R.string.new_photo));
+ /* Disable fetching image until we find a last.fm replacement
// Option to fetch the old album image
if (ApolloUtils.isOnline(getActivity())) {
// Option to fetch the old artist image
mChoices.add(OLD_PHOTO, getString(R.string.context_menu_fetch_album_art));
- }
+ }*/
}
/**
@@ -143,8 +145,9 @@ public class PhotoSelectionDialog extends DialogFragment {
private void setOtherChoices() {
// Select a photo from the gallery
mChoices.add(NEW_PHOTO, getString(R.string.new_photo));
+ // Disable fetching image until we find a last.fm replacement
// Option to use the default image
- mChoices.add(OLD_PHOTO, getString(R.string.use_default));
+ // mChoices.add(OLD_PHOTO, getString(R.string.use_default));
}
/**
diff --git a/src/com/cyngn/eleven/ui/fragments/FadingBarFragment.java b/src/com/cyngn/eleven/ui/fragments/FadingBarFragment.java
index 7fe3a59..5c3404e 100644
--- a/src/com/cyngn/eleven/ui/fragments/FadingBarFragment.java
+++ b/src/com/cyngn/eleven/ui/fragments/FadingBarFragment.java
@@ -7,7 +7,7 @@ import android.widget.AbsListView.OnScrollListener;
import com.cyngn.eleven.ui.activities.HomeActivity;
public abstract class FadingBarFragment extends DetailFragment implements OnScrollListener {
- protected static final int ACTION_BAR_DEFAULT_OPACITY = 65;
+ protected static final int ACTION_BAR_DEFAULT_OPACITY = 100;
@Override
public void setupActionBar() {
diff --git a/src/com/cyngn/eleven/widgets/LetterTileDrawable.java b/src/com/cyngn/eleven/widgets/LetterTileDrawable.java
new file mode 100644
index 0000000..139d5e7
--- /dev/null
+++ b/src/com/cyngn/eleven/widgets/LetterTileDrawable.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2013 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.cyngn.eleven.widgets;
+
+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.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+
+import junit.framework.Assert;
+
+import com.cyngn.eleven.R;
+import com.cyngn.eleven.cache.ImageWorker.ImageType;
+import com.cyngn.eleven.utils.MusicUtils;
+
+/**
+ * A drawable that encapsulates all the functionality needed to display a letter tile to
+ * represent a artist/album/playlist image.
+ */
+public class LetterTileDrawable extends Drawable {
+
+ private final String TAG = LetterTileDrawable.class.getSimpleName();
+
+ private final Paint mPaint;
+
+ /** Letter tile */
+ private static TypedArray sColors;
+ private static int sDefaultColor;
+ private static int sTileFontColor;
+ private static float sLetterToTileRatio;
+ private static Bitmap DEFAULT_ARTIST;
+ private static Bitmap DEFAULT_ARTIST_LARGE;
+ private static Bitmap DEFAULT_ALBUM;
+ private static Bitmap DEFAULT_ALBUM_LARGE;
+ private static Bitmap DEFAULT_PLAYLIST;
+ private static Bitmap DEFAULT_PLAYLIST_LARGE;
+
+ /** Reusable components to avoid new allocations */
+ private static final Paint sPaint = new Paint();
+ private static final Rect sRect = new Rect();
+ private static final char[] sChars = new char[2];
+
+ private String mDisplayName;
+ private String mIdentifier;
+ private float mScale = 1.0f;
+ private float mOffset = 0.0f;
+ private Resources res;
+ private boolean mIsCircle = false;
+
+ private ImageType mImageType;
+
+ private static synchronized void initializeStaticVariables(final Resources res) {
+ if (sColors == null) {
+ sColors = res.obtainTypedArray(R.array.letter_tile_colors);
+ sDefaultColor = res.getColor(R.color.letter_tile_default_color);
+ sTileFontColor = res.getColor(R.color.letter_tile_font_color);
+ sLetterToTileRatio = res.getFraction(R.dimen.letter_to_tile_ratio, 1, 1);
+ DEFAULT_ARTIST = BitmapFactory.decodeResource(res, R.drawable.ic_artist);
+ DEFAULT_ARTIST_LARGE = BitmapFactory.decodeResource(res, R.drawable.ic_artist_lg);
+ DEFAULT_ALBUM = BitmapFactory.decodeResource(res, R.drawable.ic_album);
+ DEFAULT_ALBUM_LARGE = BitmapFactory.decodeResource(res, R.drawable.ic_album_lg);
+ DEFAULT_PLAYLIST = BitmapFactory.decodeResource(res, R.drawable.ic_playlist);
+ DEFAULT_PLAYLIST_LARGE = BitmapFactory.decodeResource(res, R.drawable.ic_playlist_lg);
+
+ sPaint.setTypeface(Typeface.create(
+ res.getString(R.string.letter_tile_letter_font_family), Typeface.NORMAL));
+ sPaint.setTextAlign(Align.CENTER);
+ sPaint.setAntiAlias(true);
+ }
+ }
+
+ public LetterTileDrawable(final Context context) {
+ mPaint = new Paint();
+ mPaint.setFilterBitmap(true);
+ mPaint.setDither(true);
+ res = context.getResources();
+
+ initializeStaticVariables(res);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ //setBounds(0, 0, 120, 120);
+ final Rect bounds = getBounds();
+ if (!isVisible() || bounds.isEmpty()) {
+ return;
+ }
+ // Draw letter tile.
+ drawLetterTile(canvas);
+ }
+
+ @Override
+ public void setBounds(Rect bounds) {
+ super.setBounds(bounds);
+ }
+
+ private void drawLetterTile(final Canvas canvas) {
+ // Draw background color.
+ sPaint.setColor(pickColor(mIdentifier));
+
+ sPaint.setAlpha(mPaint.getAlpha());
+ final Rect bounds = getBounds();
+ final int minDimension = Math.min(bounds.width(), bounds.height());
+
+ if (mIsCircle) {
+ canvas.drawCircle(bounds.centerX(), bounds.centerY(), minDimension / 2, sPaint);
+ } else {
+ canvas.drawRect(bounds, sPaint);
+ }
+
+ // Draw letter/digit only if the first character is an english letter
+ if (mDisplayName != null
+ && isEnglishLetter(mDisplayName.charAt(0))) {
+ int numChars = 1;
+
+ // Draw letter or digit.
+ sChars[0] = Character.toUpperCase(mDisplayName.charAt(0));
+
+ if (mDisplayName.length() > 1 && isEnglishLetter(mDisplayName.charAt(1))) {
+ sChars[1] = Character.toLowerCase(mDisplayName.charAt(1));
+ numChars = 2;
+ }
+
+ // Scale text by canvas bounds and user selected scaling factor
+ sPaint.setTextSize(mScale * sLetterToTileRatio * minDimension);
+ //sPaint.setTextSize(sTileLetterFontSize);
+ sPaint.getTextBounds(sChars, 0, numChars, sRect);
+ sPaint.setColor(sTileFontColor);
+
+ // Draw the letter in the canvas, vertically shifted up or down by the user-defined
+ // offset
+ canvas.drawText(sChars, 0, numChars, bounds.centerX(),
+ bounds.centerY() + mOffset * bounds.height() + sRect.height() / 2,
+ sPaint);
+ } else {
+ // Draw the default image if there is no letter/digit to be drawn
+ final Bitmap bitmap = getDefaultBitmapForImageType(mImageType, bounds);
+
+ // The bitmap should be drawn in the middle of the canvas without changing its width to
+ // height ratio.
+ final Rect destRect = copyBounds();
+
+ drawBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), canvas, destRect, mScale,
+ mOffset, mPaint);
+ }
+ }
+
+ public int getColor() {
+ return pickColor(mIdentifier);
+ }
+
+ /**
+ * Returns a deterministic color based on the provided contact identifier string.
+ */
+ private static int pickColor(final String identifier) {
+ if (TextUtils.isEmpty(identifier)) {
+ return sDefaultColor;
+ }
+ // 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(identifier.hashCode()) % sColors.length();
+ return sColors.getColor(color, sDefaultColor);
+ }
+
+ /**
+ * Gets the default image to show for the image type. If the bounds are large,
+ * it will use the large default bitmap
+ */
+ private static Bitmap getDefaultBitmapForImageType(ImageType type, Rect bounds) {
+ Bitmap ret = getDefaultBitmap(type, true);
+ if (Math.max(bounds.width(), bounds.height()) > Math.max(ret.getWidth(), ret.getHeight())) {
+ ret = getDefaultBitmap(type, false);
+ }
+
+ return ret;
+ }
+
+ private static Bitmap getDefaultBitmap(ImageType type, boolean small) {
+ switch (type) {
+ case ARTIST:
+ return small ? DEFAULT_ARTIST : DEFAULT_ARTIST_LARGE;
+ case ALBUM:
+ return small ? DEFAULT_ALBUM : DEFAULT_ALBUM_LARGE;
+ case PLAYLIST:
+ return small ? DEFAULT_PLAYLIST : DEFAULT_PLAYLIST_LARGE;
+ default:
+ throw new IllegalArgumentException("Unrecognized image type");
+ }
+ }
+
+ private static boolean isEnglishLetter(final char c) {
+ return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9');
+ }
+
+ @Override
+ public void setAlpha(final int alpha) {
+ mPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(final ColorFilter cf) {
+ mPaint.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ return android.graphics.PixelFormat.OPAQUE;
+ }
+
+ /**
+ * Scale the drawn letter tile to a ratio of its default size
+ *
+ * @param scale The ratio the letter tile should be scaled to as a percentage of its default
+ * size, from a scale of 0 to 2.0f. The default is 1.0f.
+ */
+ public void setScale(float scale) {
+ mScale = scale;
+ }
+
+ /**
+ * Assigns the vertical offset of the position of the letter tile to the ContactDrawable
+ *
+ * @param offset The provided offset must be within the range of -0.5f to 0.5f.
+ * If set to -0.5f, the letter will be shifted upwards by 0.5 times the height of the canvas
+ * it is being drawn on, which means it will be drawn with the center of the letter starting
+ * at the top edge of the canvas.
+ * If set to 0.5f, the letter will be shifted downwards by 0.5 times the height of the canvas
+ * it is being drawn on, which means it will be drawn with the center of the letter starting
+ * at the bottom edge of the canvas.
+ * The default is 0.0f.
+ */
+ public void setOffset(float offset) {
+ Assert.assertTrue(offset >= -0.5f && offset <= 0.5f);
+ mOffset = offset;
+ }
+
+ public void setTileDetails(final String displayName, final String identifier,
+ final ImageType type) {
+ mDisplayName = MusicUtils.getTrimmedName(displayName);
+ mIdentifier = MusicUtils.getTrimmedName(identifier);
+ mImageType = type;
+ invalidateSelf();
+ }
+
+ public void setIsCircular(boolean isCircle) {
+ mIsCircle = isCircle;
+ }
+
+ /**
+ * Draw the bitmap onto the canvas at the current bounds taking into account the current scale.
+ */
+ private static void drawBitmap(final Bitmap bitmap, final int width, final int height,
+ final Canvas canvas, final Rect destRect, final float scale,
+ final float offset, final Paint paint) {
+ // Crop the destination bounds into a square, scaled and offset as appropriate
+ final int halfLength = (int) (scale * Math.min(destRect.width(), destRect.height()) / 2);
+
+ destRect.set(destRect.centerX() - halfLength,
+ (int) (destRect.centerY() - halfLength + offset * destRect.height()),
+ destRect.centerX() + halfLength,
+ (int) (destRect.centerY() + halfLength + offset * destRect.height()));
+
+ // Source rectangle remains the entire bounds of the source bitmap.
+ sRect.set(0, 0, width, height);
+
+ canvas.drawBitmap(bitmap, sRect, destRect, paint);
+ }
+
+ /**
+ * Draws the default letter tile drawable for the image type to a bitmap
+ */
+ public static Bitmap createDefaultBitmap(Context context, String identifier, ImageType type,
+ boolean isCircle, boolean smallArtwork) {
+ initializeStaticVariables(context.getResources());
+
+ identifier = MusicUtils.getTrimmedName(identifier);
+
+ // get the default bitmap to determine what to draw to
+ Bitmap defaultBitmap = getDefaultBitmap(type, smallArtwork);
+ final Rect bounds = new Rect(0, 0, defaultBitmap.getWidth(), defaultBitmap.getHeight());
+
+ // create a bitmap and canvas for drawing
+ Bitmap createdBitmap = Bitmap.createBitmap(defaultBitmap.getWidth(),
+ defaultBitmap.getHeight(), defaultBitmap.getConfig());
+ Canvas canvas = new Canvas(createdBitmap);
+
+ Paint paint = new Paint();
+ paint.setColor(pickColor(identifier));
+
+ final int minDimension = Math.min(bounds.width(), bounds.height());
+
+ if (isCircle) {
+ canvas.drawCircle(bounds.centerX(), bounds.centerY(), minDimension / 2, paint);
+ } else {
+ canvas.drawRect(bounds, paint);
+ }
+
+ // draw to the bitmap
+ drawBitmap(defaultBitmap, defaultBitmap.getWidth(), defaultBitmap.getHeight(), canvas,
+ bounds, 1, 0, paint);
+
+ return createdBitmap;
+ }
+}