Add default cover for no info modes
The improves swiping: before, with no default cover, one just swiped a black screen with no scrolling feedback, which was rather unintuitive.
This commit is contained in:
parent
bb39b8677e
commit
cd847f4a93
BIN
orig/default_cover.svgz
Normal file
BIN
orig/default_cover.svgz
Normal file
Binary file not shown.
BIN
res/drawable-hdpi/default_cover.png
Normal file
BIN
res/drawable-hdpi/default_cover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
res/drawable-mdpi/default_cover.png
Normal file
BIN
res/drawable-mdpi/default_cover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
@ -136,15 +136,18 @@ public final class CoverBitmap {
|
|||||||
*/
|
*/
|
||||||
public static Bitmap createBitmap(Context context, int style, Song song, int width, int height, Bitmap bitmap)
|
public static Bitmap createBitmap(Context context, int style, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
|
if (song == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
switch (style) {
|
switch (style) {
|
||||||
case STYLE_OVERLAPPING_BOX:
|
case STYLE_OVERLAPPING_BOX:
|
||||||
return createOverlappingBitmap(context, song, width, height, bitmap);
|
return createOverlappingBitmap(context, song, width, height, bitmap);
|
||||||
case STYLE_INFO_BELOW:
|
case STYLE_INFO_BELOW:
|
||||||
return createSeparatedBitmap(context, song, width, height, bitmap);
|
return createSeparatedBitmap(context, song, width, height, bitmap);
|
||||||
case STYLE_NO_INFO:
|
case STYLE_NO_INFO:
|
||||||
return createScaledBitmap(context, song, width, height, bitmap);
|
return createScaledBitmap(song.getCover(context), width, height, bitmap);
|
||||||
case STYLE_NO_INFO_ZOOMED:
|
case STYLE_NO_INFO_ZOOMED:
|
||||||
return createZoomedBitmap(context, song, width, height, bitmap);
|
return createZoomedBitmap(song.getCover(context), width, height, bitmap);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid bitmap type given: " + style);
|
throw new IllegalArgumentException("Invalid bitmap type given: " + style);
|
||||||
}
|
}
|
||||||
@ -152,7 +155,7 @@ public final class CoverBitmap {
|
|||||||
|
|
||||||
private static Bitmap createOverlappingBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
private static Bitmap createOverlappingBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (TEXT_SIZE == -1)
|
if (TEXT_SIZE == -1)
|
||||||
@ -246,7 +249,7 @@ public final class CoverBitmap {
|
|||||||
|
|
||||||
private static Bitmap createSeparatedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
private static Bitmap createSeparatedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (TEXT_SIZE == -1)
|
if (TEXT_SIZE == -1)
|
||||||
@ -346,69 +349,76 @@ public final class CoverBitmap {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Bitmap createZoomedBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
/**
|
||||||
|
* Scales a bitmap to completely fill a rectangle of the given size. Aspect
|
||||||
|
* ratio is preserved, thus, parts of the image will be cut off if the
|
||||||
|
* aspect ratio of the rectangle does not match that of the source bitmap.
|
||||||
|
*
|
||||||
|
* @param source The source bitmap.
|
||||||
|
* @param width Width of the result
|
||||||
|
* @param height Height of the result
|
||||||
|
* @param reuse A bitmap to store the result in if possible
|
||||||
|
* @return The zoomed bitmap.
|
||||||
|
*/
|
||||||
|
public static Bitmap createZoomedBitmap(Bitmap source, int width, int height, Bitmap reuse)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (source == null || width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Bitmap cover = song.getCover(context);
|
Bitmap bitmap = null;
|
||||||
if (cover == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (bitmap != null && (bitmap.getHeight() != height || bitmap.getWidth() != width)) {
|
if (reuse != null) {
|
||||||
bitmap.recycle();
|
if (reuse.getHeight() == height && reuse.getWidth() == width)
|
||||||
bitmap = null;
|
bitmap = reuse;
|
||||||
|
else
|
||||||
|
reuse.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmap == null)
|
if (bitmap == null)
|
||||||
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
|
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
|
||||||
int coverWidth = cover.getWidth();
|
int sourceWidth = source.getWidth();
|
||||||
int coverHeight = cover.getHeight();
|
int sourceHeight = source.getHeight();
|
||||||
int size = Math.max(width, height);
|
int size = Math.max(width, height);
|
||||||
float scale = coverWidth < coverHeight ? (float)size / coverWidth : (float)size / coverHeight;
|
float scale = sourceWidth < sourceHeight ? (float)size / sourceWidth : (float)size / sourceHeight;
|
||||||
|
|
||||||
int srcWidth = (int)(Math.min(width, coverWidth * scale) / scale);
|
int srcWidth = (int)(Math.min(width, sourceWidth * scale) / scale);
|
||||||
int srcHeight = (int)(Math.min(height, coverHeight * scale) / scale);
|
int srcHeight = (int)(Math.min(height, sourceHeight * scale) / scale);
|
||||||
int xOffset = (coverWidth - srcWidth) / 2;
|
int xOffset = (sourceWidth - srcWidth) / 2;
|
||||||
int yOffset = (coverHeight - srcHeight) / 2;
|
int yOffset = (sourceHeight - srcHeight) / 2;
|
||||||
Rect src = new Rect(xOffset, yOffset, coverWidth - xOffset, coverHeight - yOffset);
|
Rect src = new Rect(xOffset, yOffset, sourceWidth - xOffset, sourceHeight - yOffset);
|
||||||
Rect dest = new Rect(0, 0, width, height);
|
Rect dest = new Rect(0, 0, width, height);
|
||||||
canvas.drawBitmap(cover, src, dest, null);
|
canvas.drawBitmap(source, src, dest, null);
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scales a cover to fit in a rectangle of the given size. Aspect ratio is
|
* Scales a bitmap to fit in a rectangle of the given size. Aspect ratio is
|
||||||
* preserved. At least one dimension of the result will match the provided
|
* preserved. At least one dimension of the result will match the provided
|
||||||
* dimension exactly.
|
* dimension exactly.
|
||||||
*
|
*
|
||||||
* @param context A context to use.
|
* @param source The source bitmap.
|
||||||
* @param song The song to display information for
|
|
||||||
* @param width Maximum width of image
|
* @param width Maximum width of image
|
||||||
* @param height Maximum height of image
|
* @param height Maximum height of image
|
||||||
* @param bitmap A bitmap that will simply be recycled.
|
* @param reuse A bitmap that will simply be recycled. (This method does not
|
||||||
* @return The scaled Bitmap, or null if a cover could not be found.
|
* support reuse.)
|
||||||
|
* @return The scaled bitmap.
|
||||||
*/
|
*/
|
||||||
private static Bitmap createScaledBitmap(Context context, Song song, int width, int height, Bitmap bitmap)
|
public static Bitmap createScaledBitmap(Bitmap source, int width, int height, Bitmap reuse)
|
||||||
{
|
{
|
||||||
if (song == null || width < 1 || height < 1)
|
if (source == null || width < 1 || height < 1)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (bitmap != null)
|
if (reuse != null)
|
||||||
bitmap.recycle();
|
reuse.recycle();
|
||||||
|
|
||||||
Bitmap cover = song.getCover(context);
|
int sourceWidth = source.getWidth();
|
||||||
if (cover == null)
|
int sourceHeight = source.getHeight();
|
||||||
return null;
|
float scale = Math.min((float)width / sourceWidth, (float)height / sourceHeight);
|
||||||
|
sourceWidth *= scale;
|
||||||
int coverWidth = cover.getWidth();
|
sourceHeight *= scale;
|
||||||
int coverHeight = cover.getHeight();
|
return Bitmap.createScaledBitmap(source, sourceWidth, sourceHeight, false);
|
||||||
float scale = Math.min((float)width / coverWidth, (float)height / coverHeight);
|
|
||||||
coverWidth *= scale;
|
|
||||||
coverHeight *= scale;
|
|
||||||
return Bitmap.createScaledBitmap(cover, coverWidth, coverHeight, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ package org.kreed.vanilla;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@ -75,6 +76,10 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
* Cache of cover bitmaps generated for songs. The song ids are the keys.
|
* Cache of cover bitmaps generated for songs. The song ids are the keys.
|
||||||
*/
|
*/
|
||||||
private final Cache<Bitmap> mBitmapCache = new Cache<Bitmap>(8);
|
private final Cache<Bitmap> mBitmapCache = new Cache<Bitmap>(8);
|
||||||
|
/**
|
||||||
|
* Cover art to use when a song has no cover art in no info display styles.
|
||||||
|
*/
|
||||||
|
private Bitmap mDefaultCover;
|
||||||
|
|
||||||
private final Scroller mScroller;
|
private final Scroller mScroller;
|
||||||
private VelocityTracker mVelocityTracker;
|
private VelocityTracker mVelocityTracker;
|
||||||
@ -126,6 +131,32 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
scrollTo(getWidth(), 0);
|
scrollTo(getWidth(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the cover to show when a song has no cover art. Only used in the
|
||||||
|
* no info modes.
|
||||||
|
*
|
||||||
|
* @return The default cover, now also stored in mDefaultCover.
|
||||||
|
*/
|
||||||
|
private Bitmap generateDefaultCover()
|
||||||
|
{
|
||||||
|
int style = mCoverStyle;
|
||||||
|
Bitmap result = null;
|
||||||
|
|
||||||
|
if (style == CoverBitmap.STYLE_NO_INFO || style == CoverBitmap.STYLE_NO_INFO_ZOOMED) {
|
||||||
|
Bitmap def = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.default_cover);
|
||||||
|
int width = getWidth();
|
||||||
|
int height = getHeight();
|
||||||
|
|
||||||
|
if (style == CoverBitmap.STYLE_NO_INFO)
|
||||||
|
result = CoverBitmap.createScaledBitmap(def, width, height, null);
|
||||||
|
else
|
||||||
|
result = CoverBitmap.createZoomedBitmap(def, width, height, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
mDefaultCover = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recreate all the necessary cached bitmaps.
|
* Recreate all the necessary cached bitmaps.
|
||||||
*/
|
*/
|
||||||
@ -137,6 +168,7 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
((Bitmap)bitmaps[i]).recycle();
|
((Bitmap)bitmaps[i]).recycle();
|
||||||
bitmaps[i] = null;
|
bitmaps[i] = null;
|
||||||
}
|
}
|
||||||
|
mDefaultCover = null;
|
||||||
for (int i = 3; --i != -1; )
|
for (int i = 3; --i != -1; )
|
||||||
setSong(i, mSongs[i]);
|
setSong(i, mSongs[i]);
|
||||||
}
|
}
|
||||||
@ -317,12 +349,21 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
if (song == null || song.id == -1)
|
if (song == null || song.id == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Bitmap bitmap = CoverBitmap.createBitmap(getContext(), mCoverStyle, song, getWidth(), getHeight(), mBitmapCache.discardOldest());
|
Bitmap reuse = mBitmapCache.discardOldest();
|
||||||
if (bitmap != null) {
|
if (reuse == mDefaultCover)
|
||||||
mBitmaps[i] = bitmap;
|
reuse = null;
|
||||||
mBitmapCache.put(song.id, bitmap);
|
|
||||||
postInvalidate();
|
int style = mCoverStyle;
|
||||||
|
Bitmap bitmap = CoverBitmap.createBitmap(getContext(), style, song, getWidth(), getHeight(), reuse);
|
||||||
|
if (bitmap == null && (style == CoverBitmap.STYLE_NO_INFO || style == CoverBitmap.STYLE_NO_INFO_ZOOMED)) {
|
||||||
|
bitmap = mDefaultCover;
|
||||||
|
if (bitmap == null)
|
||||||
|
bitmap = generateDefaultCover();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBitmaps[i] = bitmap;
|
||||||
|
mBitmapCache.put(song.id, bitmap);
|
||||||
|
postInvalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user