Allow the song info to be shown below the cover instead of on top of it

The complexity of the cover view drawing routines is getting a bit ridiculous..
This commit is contained in:
Christopher Eby 2010-04-04 00:34:55 -05:00
parent 124780de98
commit 9e8bc71904
3 changed files with 152 additions and 12 deletions

View File

@ -7,6 +7,7 @@
<string name="settings">Preferences</string> <string name="settings">Preferences</string>
<string name="library">Choose Songs</string> <string name="library">Choose Songs</string>
<string name="quit">Stop and Exit</string> <string name="quit">Stop and Exit</string>
<string name="display_mode">Display Mode</string>
<!-- Widgets --> <!-- Widgets -->
<string name="starting">Starting up...</string> <string name="starting">Starting up...</string>

View File

@ -29,7 +29,7 @@ import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region; import android.graphics.drawable.Drawable;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.RemoteException; import android.os.RemoteException;
@ -42,7 +42,7 @@ import android.view.View;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import android.widget.Scroller; import android.widget.Scroller;
public class CoverView extends View { public final class CoverView extends View {
private static final int STORE_SIZE = 3; private static final int STORE_SIZE = 3;
private final int SNAP_VELOCITY; private final int SNAP_VELOCITY;
@ -53,6 +53,8 @@ public class CoverView extends View {
private float mStartY; private float mStartY;
private IPlaybackService mService; private IPlaybackService mService;
private boolean mSeparateInfo;
Song[] mSongs = new Song[3]; Song[] mSongs = new Song[3];
private Bitmap[] mBitmaps = new Bitmap[3]; private Bitmap[] mBitmaps = new Bitmap[3];
@ -66,6 +68,16 @@ public class CoverView extends View {
SNAP_VELOCITY = ViewConfiguration.get(context).getScaledMinimumFlingVelocity(); SNAP_VELOCITY = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
} }
public boolean hasSeparateInfo()
{
return mSeparateInfo;
}
public void setSeparateInfo(boolean separate)
{
mSeparateInfo = separate;
}
public void setPlaybackService(IPlaybackService service) public void setPlaybackService(IPlaybackService service)
{ {
try { try {
@ -78,9 +90,11 @@ public class CoverView extends View {
private static void drawText(Canvas canvas, String text, float left, float top, float width, float maxWidth, Paint paint) private static void drawText(Canvas canvas, String text, float left, float top, float width, float maxWidth, Paint paint)
{ {
canvas.save();
float offset = Math.max(0, maxWidth - width) / 2; float offset = Math.max(0, maxWidth - width) / 2;
canvas.clipRect(left, top, left + maxWidth, top + paint.getTextSize() * 2, Region.Op.REPLACE); canvas.clipRect(left, top, left + maxWidth, top + paint.getTextSize() * 2);
canvas.drawText(text, left + offset, top - paint.ascent(), paint); canvas.drawText(text, left + offset, top - paint.ascent(), paint);
canvas.restore();
} }
private static RectF centerRect(float maxWidth, float maxHeight, float width, float height) private static RectF centerRect(float maxWidth, float maxHeight, float width, float height)
@ -149,7 +163,7 @@ public class CoverView extends View {
return bitmap; return bitmap;
} }
public Bitmap createBitmap(Song song, int width, int height) private Bitmap createOverlappingBitmap(Song song, int width, int height)
{ {
if (song == null || width < 1 || height < 1) if (song == null || width < 1 || height < 1)
return null; return null;
@ -231,10 +245,108 @@ public class CoverView extends View {
return bitmap; return bitmap;
} }
private Bitmap createSeparatedBitmap(Song song, int width, int height)
{
if (song == null || width < 1 || height < 1)
return null;
boolean horizontal = width > height;
Paint paint = new Paint();
paint.setAntiAlias(true);
String title = song.title == null ? "" : song.title;
String album = song.album == null ? "" : song.album;
String artist = song.artist == null ? "" : song.artist;
Bitmap cover = song.coverPath == null ? null : BitmapFactory.decodeFile(song.coverPath);
float coverWidth;
float coverHeight;
if (cover == null) {
coverWidth = 0;
coverHeight = 0;
} else {
coverWidth = cover.getWidth();
coverHeight = cover.getHeight();
float drawableAspectRatio = coverHeight / coverWidth;
float viewAspectRatio = (float) height / width;
float scale = drawableAspectRatio > viewAspectRatio ? height / coverWidth
: width / coverHeight;
coverWidth *= scale;
coverHeight *= scale;
}
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, metrics);
float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, metrics);
paint.setTextSize(textSize);
float titleWidth = paint.measureText(title);
float albumWidth = paint.measureText(album);
float artistWidth = paint.measureText(artist);
float maxBoxWidth = horizontal ? width - coverWidth : width;
float maxBoxHeight = horizontal ? height : height - coverHeight;
float boxWidth = Math.min(maxBoxWidth, textSize + Math.max(titleWidth, Math.max(artistWidth, albumWidth)) + padding * 3);
float boxHeight = Math.min(maxBoxHeight, textSize * 3 + padding * 4);
int bitmapWidth = (int)(horizontal ? coverWidth + boxWidth : Math.max(coverWidth, boxWidth));
int bitmapHeight = (int)(horizontal ? Math.max(coverHeight, boxHeight) : coverHeight + boxHeight);
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
if (cover != null) {
RectF rect = new RectF(0, 0, coverWidth, coverHeight);
canvas.drawBitmap(cover, null, rect, paint);
cover.recycle();
cover = null;
}
Drawable drawable;
float top = padding;
float left = padding;
if (horizontal) {
top = (height - boxHeight) / 2;
left += coverWidth;
} else {
top += coverHeight;
}
float maxWidth = boxWidth - padding * 3 - textSize;
paint.setARGB(255, 255, 255, 255);
drawable = getResources().getDrawable(R.drawable.tab_songs_selected);
drawable.setBounds((int)left, (int)top, (int)(left + textSize), (int)(top + textSize));
drawable.draw(canvas);
drawText(canvas, title, left + padding + textSize, top, maxWidth, maxWidth, paint);
top += textSize + padding;
drawable = getResources().getDrawable(R.drawable.tab_albums_selected);
drawable.setBounds((int)left, (int)top, (int)(left + textSize), (int)(top + textSize));
drawable.draw(canvas);
drawText(canvas, album, left + padding + textSize, top, maxWidth, maxWidth, paint);
top += textSize + padding;
drawable = getResources().getDrawable(R.drawable.tab_artists_selected);
drawable.setBounds((int)left, (int)top, (int)(left + textSize), (int)(top + textSize));
drawable.draw(canvas);
drawText(canvas, artist, left + padding + textSize, top, maxWidth, maxWidth, paint);
return bitmap;
}
private void createBitmap(int i) private void createBitmap(int i)
{ {
Bitmap oldBitmap = mBitmaps[i]; Bitmap oldBitmap = mBitmaps[i];
mBitmaps[i] = createBitmap(mSongs[i], getWidth(), getHeight()); if (mSeparateInfo)
mBitmaps[i] = createSeparatedBitmap(mSongs[i], getWidth(), getHeight());
else
mBitmaps[i] = createOverlappingBitmap(mSongs[i], getWidth(), getHeight());
if (oldBitmap != null) if (oldBitmap != null)
oldBitmap.recycle(); oldBitmap.recycle();
} }
@ -296,14 +408,26 @@ public class CoverView extends View {
invalidate(); invalidate();
} }
private void regenerateBitmaps()
{
for (int i = STORE_SIZE; --i != -1; )
createBitmap(i);
}
public void toggleDisplayMode()
{
mSeparateInfo = !mSeparateInfo;
regenerateBitmaps();
postInvalidate();
}
@Override @Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
{ {
if (width == 0 || height == 0) if (width == 0 || height == 0)
return; return;
for (int i = STORE_SIZE; --i != -1; ) regenerateBitmaps();
createBitmap(i);
reset(); reset();
} }

View File

@ -62,6 +62,7 @@ public class FullPlaybackActivity extends PlaybackActivity implements View.OnCli
private static final int SONG_SELECTOR = 8; private static final int SONG_SELECTOR = 8;
private static final int MENU_QUIT = 0; private static final int MENU_QUIT = 0;
private static final int MENU_DISPLAY = 1;
private static final int MENU_PREFS = 2; private static final int MENU_PREFS = 2;
private static final int MENU_LIBRARY = 3; private static final int MENU_LIBRARY = 3;
@ -70,16 +71,15 @@ public class FullPlaybackActivity extends PlaybackActivity implements View.OnCli
{ {
super.onCreate(icicle); super.onCreate(icicle);
if (icicle == null) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
if (settings.getBoolean("selector_on_startup", false)) if (icicle == null && settings.getBoolean("selector_on_startup", false))
showDialog(SONG_SELECTOR); showDialog(SONG_SELECTOR);
}
setContentView(R.layout.full_playback); setContentView(R.layout.full_playback);
mCoverView = (CoverView)findViewById(R.id.cover_view); mCoverView = (CoverView)findViewById(R.id.cover_view);
mCoverView.setOnClickListener(this); mCoverView.setOnClickListener(this);
mCoverView.setSeparateInfo(settings.getBoolean("separate_info", false));
mControlsTop = findViewById(R.id.controls_top); mControlsTop = findViewById(R.id.controls_top);
mControlsBottom = findViewById(R.id.controls_bottom); mControlsBottom = findViewById(R.id.controls_bottom);
@ -101,6 +101,17 @@ public class FullPlaybackActivity extends PlaybackActivity implements View.OnCli
mSeekBar.setOnFocusChangeListener(this); mSeekBar.setOnFocusChangeListener(this);
} }
@Override
public void onDestroy()
{
super.onDestroy();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("separate_info", mCoverView.hasSeparateInfo());
editor.commit();
}
@Override @Override
protected void setState(int state) protected void setState(int state)
{ {
@ -178,6 +189,7 @@ public class FullPlaybackActivity extends PlaybackActivity implements View.OnCli
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) public boolean onCreateOptionsMenu(Menu menu)
{ {
menu.add(0, MENU_DISPLAY, 0, R.string.display_mode).setIcon(android.R.drawable.ic_menu_gallery);
menu.add(0, MENU_LIBRARY, 0, R.string.library).setIcon(android.R.drawable.ic_menu_add); menu.add(0, MENU_LIBRARY, 0, R.string.library).setIcon(android.R.drawable.ic_menu_add);
menu.add(0, MENU_PREFS, 0, R.string.settings).setIcon(android.R.drawable.ic_menu_preferences); menu.add(0, MENU_PREFS, 0, R.string.settings).setIcon(android.R.drawable.ic_menu_preferences);
menu.add(0, MENU_QUIT, 0, R.string.quit).setIcon(android.R.drawable.ic_menu_close_clear_cancel); menu.add(0, MENU_QUIT, 0, R.string.quit).setIcon(android.R.drawable.ic_menu_close_clear_cancel);
@ -204,6 +216,9 @@ public class FullPlaybackActivity extends PlaybackActivity implements View.OnCli
case MENU_LIBRARY: case MENU_LIBRARY:
showDialog(SONG_SELECTOR); showDialog(SONG_SELECTOR);
break; break;
case MENU_DISPLAY:
mCoverView.toggleDisplayMode();
break;
} }
return true; return true;