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:
parent
124780de98
commit
9e8bc71904
@ -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>
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user