summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilhelm Fitzpatrick <rafial@cyngn.com>2014-09-12 16:10:08 -0700
committerlinus_lee <llee@cyngn.com>2014-11-20 12:03:03 -0800
commit9442e221ed4b8f1abaebe0dae3ee0d979e6d79b3 (patch)
treea0477f5060ebdc8f5ea2492cad699c20152fc782
parent1142f32db0658647186e474e4da32640643647bc (diff)
downloadandroid_packages_apps_Eleven-9442e221ed4b8f1abaebe0dae3ee0d979e6d79b3.tar.gz
android_packages_apps_Eleven-9442e221ed4b8f1abaebe0dae3ee0d979e6d79b3.tar.bz2
android_packages_apps_Eleven-9442e221ed4b8f1abaebe0dae3ee0d979e6d79b3.zip
Eleven: AlbumDetailPage implemented according to red lines
Change-Id: I6b5d5051951eda26018f1be67d19aab27af9ae1a
-rw-r--r--AndroidManifest.xml7
-rw-r--r--res/drawable-hdpi/stopwatch_icon_small_grey.pngbin0 -> 382 bytes
-rw-r--r--res/drawable-mdpi/stopwatch_icon_small_grey.pngbin0 -> 284 bytes
-rw-r--r--res/drawable-xhdpi/stopwatch_icon_small_grey.pngbin0 -> 460 bytes
-rw-r--r--res/drawable-xxhdpi/stopwatch_icon_small_grey.pngbin0 -> 631 bytes
-rw-r--r--res/layout/activity_album_detail.xml100
-rw-r--r--res/layout/album_detail_song.xml48
-rw-r--r--res/layout/artist_detail_album.xml17
-rw-r--r--res/layout/artist_detail_song.xml24
-rw-r--r--res/values/colors.xml3
-rw-r--r--res/values/dimens.xml11
-rw-r--r--res/values/strings.xml3
-rw-r--r--src/com/cyngn/eleven/Config.java3
-rw-r--r--src/com/cyngn/eleven/adapters/AlbumDetailSongAdapter.java58
-rw-r--r--src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java89
-rw-r--r--src/com/cyngn/eleven/adapters/DetailSongAdapter.java102
-rw-r--r--src/com/cyngn/eleven/ui/activities/AlbumDetailActivity.java139
-rw-r--r--src/com/cyngn/eleven/utils/GenreFetcher.java52
-rw-r--r--src/com/cyngn/eleven/utils/MusicUtils.java17
-rw-r--r--src/com/cyngn/eleven/utils/NavUtils.java7
20 files changed, 569 insertions, 111 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index fdd3a9c..cfc3834 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -153,6 +153,13 @@
android:screenOrientation="portrait"
android:theme="@style/Eleven.Theme.ActionBar.Overlay">
</activity>
+ <!-- Album Detail Activity -->
+ <activity
+ android:name=".ui.activities.AlbumDetailActivity"
+ android:excludeFromRecents="true"
+ android:screenOrientation="portrait"
+ android:theme="@style/Eleven.Theme.ActionBar.Overlay">
+ </activity>
<!-- Playlist Detail Activity -->
<activity
android:name=".ui.activities.PlaylistDetailActivity"
diff --git a/res/drawable-hdpi/stopwatch_icon_small_grey.png b/res/drawable-hdpi/stopwatch_icon_small_grey.png
new file mode 100644
index 0000000..ab2aa7e
--- /dev/null
+++ b/res/drawable-hdpi/stopwatch_icon_small_grey.png
Binary files differ
diff --git a/res/drawable-mdpi/stopwatch_icon_small_grey.png b/res/drawable-mdpi/stopwatch_icon_small_grey.png
new file mode 100644
index 0000000..e3cf1f4
--- /dev/null
+++ b/res/drawable-mdpi/stopwatch_icon_small_grey.png
Binary files differ
diff --git a/res/drawable-xhdpi/stopwatch_icon_small_grey.png b/res/drawable-xhdpi/stopwatch_icon_small_grey.png
new file mode 100644
index 0000000..3a0d75f
--- /dev/null
+++ b/res/drawable-xhdpi/stopwatch_icon_small_grey.png
Binary files differ
diff --git a/res/drawable-xxhdpi/stopwatch_icon_small_grey.png b/res/drawable-xxhdpi/stopwatch_icon_small_grey.png
new file mode 100644
index 0000000..9b4db72
--- /dev/null
+++ b/res/drawable-xxhdpi/stopwatch_icon_small_grey.png
Binary files differ
diff --git a/res/layout/activity_album_detail.xml b/res/layout/activity_album_detail.xml
new file mode 100644
index 0000000..d93fc1d
--- /dev/null
+++ b/res/layout/activity_album_detail.xml
@@ -0,0 +1,100 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/background_color" >
+
+ <RelativeLayout
+ android:id="@+id/header"
+ android:layout_width="match_parent"
+ android:layout_height="108dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:background="@color/page_header_background" >
+
+ <ImageView
+ android:id="@+id/overflow"
+ android:layout_width="@dimen/overflow_width"
+ android:layout_height="@dimen/overflow_width"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginBottom="40dp"
+ android:gravity="center"
+ android:src="@drawable/menu_item_button" />
+
+ <ImageView
+ android:id="@+id/album_art"
+ android:layout_width="108dp"
+ android:layout_height="108dp"
+ android:layout_marginRight="@dimen/standard_padding"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/album_art"
+ android:layout_toLeftOf="@id/overflow"
+ android:layout_marginTop="21dp"
+ android:singleLine="true"
+ android:fontFamily="sans-serif"
+ android:textStyle="bold"
+ android:textSize="@dimen/text_size_large"
+ android:textColor="@color/default_text_color" />
+
+ <TextView
+ android:id="@+id/song_count_and_year"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/title"
+ android:layout_toRightOf="@id/album_art"
+ android:singleLine="true"
+ android:fontFamily="sans-serif-light"
+ android:textSize="@dimen/text_size_micro"
+ android:textColor="@color/default_text_color" />
+
+ <TextView
+ android:id="@+id/genre"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/song_count_and_year"
+ android:layout_toRightOf="@id/album_art"
+ android:layout_marginRight="@dimen/standard_padding"
+ android:singleLine="true"
+ android:fontFamily="sans-serif-light"
+ android:textSize="@dimen/text_size_micro"
+ android:textColor="@color/default_text_color"
+ android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/duration_icon"
+ android:layout_width="10dp"
+ android:layout_height="12dp"
+ android:layout_below="@id/song_count_and_year"
+ android:layout_toRightOf="@id/genre"
+ android:layout_marginTop="2dp"
+ android:layout_marginRight="4dp"
+ android:gravity="center"
+ android:src="@drawable/stopwatch_icon_small_grey" />
+
+ <TextView
+ android:id="@+id/duration"
+ android:layout_width="60dp"
+ android:layout_height="30dp"
+ android:layout_below="@id/song_count_and_year"
+ android:layout_toRightOf="@id/duration_icon"
+ android:singleLine="true"
+ android:fontFamily="sans-serif-light"
+ android:textSize="@dimen/text_size_micro"
+ android:textColor="@color/default_text_color" />
+ </RelativeLayout>
+
+ <ListView
+ android:id="@+id/songs"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/header"
+ android:layout_alignParentLeft="true"
+ android:divider="@color/background_color" />
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/album_detail_song.xml b/res/layout/album_detail_song.xml
new file mode 100644
index 0000000..e3b1587
--- /dev/null
+++ b/res/layout/album_detail_song.xml
@@ -0,0 +1,48 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="70dp" >
+
+ <!-- FIXME: hide this until we know what goes in the popup menu -->
+ <ImageView
+ android:visibility="gone"
+ android:id="@+id/overflow"
+ android:layout_width="@dimen/overflow_width"
+ android:layout_height="68dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginBottom="2dp"
+ android:gravity="center"
+ android:src="@drawable/menu_item_button" />
+
+ <TextView
+ android:id="@+id/title"
+ style="@style/ListItemMainText.Single"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@id/overflow"
+ android:paddingTop="6dp"
+ android:layout_marginTop="@dimen/list_preferred_item_padding"
+ android:layout_marginLeft="@dimen/list_preferred_item_padding" />
+
+ <TextView
+ android:id="@+id/duration"
+ style="@style/ListItemSecondaryText.Single"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/title"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@id/overflow"
+ android:layout_marginTop="-2dp"
+ android:layout_marginLeft="@dimen/standard_padding" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="@dimen/list_preferred_item_padding"
+ android:layout_marginRight="@dimen/list_preferred_item_padding"
+ android:background="@color/list_item_divider_color" />
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/artist_detail_album.xml b/res/layout/artist_detail_album.xml
index f7469bc..93131a2 100644
--- a/res/layout/artist_detail_album.xml
+++ b/res/layout/artist_detail_album.xml
@@ -15,7 +15,7 @@
<ImageView
android:visibility="gone"
android:id="@+id/overflow"
- android:layout_width="24dp"
+ android:layout_width="@dimen/overflow_width"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
@@ -26,30 +26,23 @@
<TextView
android:id="@+id/title"
+ style="@style/ListItemMainText.Single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/album_art"
android:layout_toLeftOf="@id/overflow"
android:layout_alignParentLeft="true"
android:layout_marginLeft="8dp"
- android:layout_marginTop="3dp"
- android:singleLine="true"
- android:fontFamily="sans-serif"
- android:textStyle="bold"
- android:textSize="@dimen/text_size_small"
- android:textColor="@color/default_text_color" />
+ android:layout_marginTop="3dp" />
<TextView
android:id="@+id/year"
+ style="@style/ListItemSecondaryText.Single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/overflow"
android:layout_marginLeft="8dp"
- android:layout_marginTop="-4dp"
- android:singleLine="true"
- android:fontFamily="sans-serif-light"
- android:textSize="@dimen/text_size_micro"
- android:textColor="@color/default_text_color" />
+ android:layout_marginTop="-4dp" />
</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/artist_detail_song.xml b/res/layout/artist_detail_song.xml
index 8f20e72..4973ae3 100644
--- a/res/layout/artist_detail_song.xml
+++ b/res/layout/artist_detail_song.xml
@@ -8,13 +8,13 @@
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
- android:layout_margin="10dp" />
+ android:layout_margin="@dimen/list_preferred_item_padding" />
<!-- FIXME: hide this until we know what goes in the popup menu -->
<ImageView
android:visibility="gone"
android:id="@+id/overflow"
- android:layout_width="24dp"
+ android:layout_width="@dimen/overflow_width"
android:layout_height="68dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
@@ -24,37 +24,29 @@
<TextView
android:id="@+id/title"
+ style="@style/ListItemMainText.Single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/overflow"
- android:layout_toRightOf="@id/album_art"
- android:layout_marginTop="16dp"
- android:singleLine="true"
- android:fontFamily="sans-serif"
- android:textStyle="bold"
- android:textSize="@dimen/text_size_small"
- android:textColor="@color/default_text_color" />
+ android:layout_toRightOf="@id/album_art" />
<TextView
android:id="@+id/album"
+ style="@style/ListItemSecondaryText.Single"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_toRightOf="@id/album_art"
android:layout_toLeftOf="@id/overflow"
- android:layout_marginTop="-2dp"
- android:singleLine="true"
- android:fontFamily="sans-serif-light"
- android:textSize="@dimen/text_size_micro"
- android:textColor="@color/default_text_color" />
+ android:layout_marginTop="-2dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
+ android:layout_marginLeft="@dimen/list_preferred_item_padding"
+ android:layout_marginRight="@dimen/list_preferred_item_padding"
android:background="@color/list_item_divider_color" />
</RelativeLayout> \ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6c18a71..2bef984 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -66,6 +66,9 @@
<color name="header_action_bar_text_color">@color/white</color>
<color name="bottom_action_bar_text_color">@color/default_text_color_light</color>
+ <!-- Background color used on some page headers -->
+ <color name="page_header_background">#fff4f4f4</color>
+
<!-- Color for background for shadow on playlist page -->
<color name="header_shadow_color">#ea31353f</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 3a766d1..5ab4b1e 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -24,6 +24,13 @@
<dimen name="text_size_x_large">24.0sp</dimen>
<dimen name="text_size_dayum">36.0sp</dimen>
+ <!-- Frequently used spacing between elements in many layouts -->
+ <dimen name="standard_padding">10.0dip</dimen>
+
+ <!-- overflow menu used on page headers and in list items -->
+ <dimen name="overflow_height">30.0dip</dimen>
+ <dimen name="overflow_width">24.0dip</dimen>
+
<!-- List item section header -->
<dimen name="list_item_header_height">30.0dip</dimen>
@@ -35,8 +42,8 @@
<dimen name="list_item_padding_top">10.0dip</dimen>
<dimen name="list_item_padding_bottom">10.0dip</dimen>
<dimen name="list_item_header_size">16.0sp</dimen>
- <dimen name="list_item_main_text_size">14.0sp</dimen>
- <dimen name="list_item_secondary_text_size">12.0sp</dimen>
+ <dimen name="list_item_main_text_size">@dimens/text_size_small</dimen>
+ <dimen name="list_item_secondary_text_size">@dimens/text_size_micro</dimen>
<dimen name="list_item_queue_text_padding_left">15.0dip</dimen>
<!-- List view fast scroll padding left -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ad3a907..260a285 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -202,6 +202,9 @@
<string name="header_n_albums"><xliff:g id="number">%d</xliff:g> Albums</string>
<string name="header_5_plus_albums">5+ Albums</string>
+ <string name="duration_album_mins_only"><xliff:g id="format">%1$dm</xliff:g></string>
+ <string name="duration_album_hour_mins"><xliff:g id="format">%1$dh %2$dm</xliff:g></string>
+
<string name="duration_mins"><xliff:g id="format">%3$dm %4$ds</xliff:g></string>
<string name="duration_hours"><xliff:g id="format">%2$dh %3$dm %4$ds</xliff:g></string>
<string name="duration_days"><xliff:g id="format">%1$dd %2$dd %3$dm %4$ds</xliff:g></string>
diff --git a/src/com/cyngn/eleven/Config.java b/src/com/cyngn/eleven/Config.java
index 2d18d71..99e90fb 100644
--- a/src/com/cyngn/eleven/Config.java
+++ b/src/com/cyngn/eleven/Config.java
@@ -54,6 +54,9 @@ public final class Config {
*/
public static final String ALBUM_YEAR = "album_year";
+ /** number of songs in a album or track list */
+ public static final String SONG_COUNT = "song_count";
+
/**
* The MIME type passed to a the profile activity
*/
diff --git a/src/com/cyngn/eleven/adapters/AlbumDetailSongAdapter.java b/src/com/cyngn/eleven/adapters/AlbumDetailSongAdapter.java
new file mode 100644
index 0000000..7f5dcee
--- /dev/null
+++ b/src/com/cyngn/eleven/adapters/AlbumDetailSongAdapter.java
@@ -0,0 +1,58 @@
+package com.cyngn.eleven.adapters;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.content.Loader;
+import android.view.View;
+import android.widget.TextView;
+
+import com.cyngn.eleven.Config;
+import com.cyngn.eleven.R;
+import com.cyngn.eleven.cache.ImageFetcher;
+import com.cyngn.eleven.loaders.AlbumSongLoader;
+import com.cyngn.eleven.model.Song;
+import com.cyngn.eleven.ui.activities.AlbumDetailActivity;
+import com.cyngn.eleven.utils.MusicUtils;
+
+import java.util.List;
+
+public class AlbumDetailSongAdapter extends DetailSongAdapter {
+
+ public AlbumDetailSongAdapter(Activity activity) {
+ super(activity);
+ }
+
+ protected int rowLayoutId() { return R.layout.album_detail_song; }
+
+ @Override // LoaderCallbacks
+ public Loader<List<Song>> onCreateLoader(int id, Bundle args) {
+ return new AlbumSongLoader(mActivity, args.getLong(Config.ID));
+ }
+
+ @Override // LoaderCallbacks
+ public void onLoadFinished(Loader<List<Song>> loader, List<Song> songs) {
+ super.onLoadFinished(loader, songs);
+ ((AlbumDetailActivity)mActivity).update(songs);
+ }
+
+ protected Holder newHolder(View root, ImageFetcher fetcher) {
+ return new AlbumHolder(root, fetcher, mActivity);
+ }
+
+ private static class AlbumHolder extends Holder {
+ TextView duration;
+ Context context;
+
+ protected AlbumHolder(View root, ImageFetcher fetcher, Context context) {
+ super(root, fetcher);
+ this.context = context;
+ duration = (TextView)root.findViewById(R.id.duration);
+ }
+
+ protected void update(Song song) {
+ title.setText(song.mSongName);
+ duration.setText(MusicUtils.makeShortTimeString(context, song.mDuration));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java b/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java
index 64a1ece..c24ba7e 100644
--- a/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java
+++ b/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java
@@ -2,12 +2,8 @@ package com.cyngn.eleven.adapters;
import android.app.Activity;
import android.os.Bundle;
-import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
@@ -16,92 +12,43 @@ import com.cyngn.eleven.R;
import com.cyngn.eleven.cache.ImageFetcher;
import com.cyngn.eleven.loaders.ArtistSongLoader;
import com.cyngn.eleven.model.Song;
-import com.cyngn.eleven.utils.ApolloUtils;
-import com.cyngn.eleven.utils.MusicUtils;
-import java.util.Collections;
import java.util.List;
-public class ArtistDetailSongAdapter extends BaseAdapter
-implements LoaderCallbacks<List<Song>> {
- private final Activity mActivity;
- private final ImageFetcher mImageFetcher;
- private final LayoutInflater mInflater;
- private List<Song> mSongs = Collections.emptyList();
+public class ArtistDetailSongAdapter extends DetailSongAdapter {
- public ArtistDetailSongAdapter(final Activity activity) {
- mActivity = activity;
- mImageFetcher = ApolloUtils.getImageFetcher(activity);
- mInflater = LayoutInflater.from(activity);
+ public ArtistDetailSongAdapter(Activity activity) {
+ super(activity);
}
- @Override
- public int getCount() { return mSongs.size(); }
-
- @Override
- public Song getItem(int pos) { return mSongs.get(pos); }
-
- @Override
- public long getItemId(int pos) { return pos; }
-
- @Override
- public View getView(int pos, View convertView, ViewGroup parent) {
- if(convertView == null) {
- convertView = mInflater.inflate(R.layout.artist_detail_song, parent, false);
- convertView.setTag(new Holder(convertView));
- }
-
- Holder h = (Holder)convertView.getTag();
- Song s = getItem(pos);
- h.title.setText(s.mSongName);
- h.album.setText(s.mAlbumName);
-
- if (s.mAlbumId >= 0) {
- mImageFetcher.loadAlbumImage(s.mArtistName, s.mAlbumName, s.mAlbumId, h.art);
- }
-
- addAction(convertView, s);
-
- return convertView;
- }
-
- private void addAction(View view, final Song song) {
- view.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- MusicUtils.playAll(mActivity, new long[] { song.mSongId }, -1, false);
- }
- });
- }
+ protected int rowLayoutId() { return R.layout.artist_detail_song; }
@Override // LoaderCallbacks
public Loader<List<Song>> onCreateLoader(int id, Bundle args) {
return new ArtistSongLoader(mActivity, args.getLong(Config.ID));
}
- @Override // LoaderCallbacks
- public void onLoadFinished(Loader<List<Song>> loader, List<Song> songs) {
- if (songs.isEmpty()) { return; }
- mSongs = songs;
- notifyDataSetChanged();
- }
-
- @Override // LoaderCallbacks
- public void onLoaderReset(Loader<List<Song>> loader) {
- mSongs = Collections.emptyList();
- notifyDataSetChanged();
- mImageFetcher.flush();
+ protected Holder newHolder(View root, ImageFetcher fetcher) {
+ return new ArtistHolder(root, fetcher);
}
- private class Holder {
+ private static class ArtistHolder extends Holder {
ImageView art;
- TextView title;
TextView album;
- Holder(View root) {
+ protected ArtistHolder(View root, ImageFetcher fetcher) {
+ super(root, fetcher);
art = (ImageView)root.findViewById(R.id.album_art);
- title = (TextView)root.findViewById(R.id.title);
album = (TextView)root.findViewById(R.id.album);
}
+
+ protected void update(Song song) {
+ title.setText(song.mSongName);
+ album.setText(song.mAlbumName);
+
+ if (song.mAlbumId >= 0) {
+ fetcher.loadAlbumImage(song.mArtistName, song.mAlbumName, song.mAlbumId, art);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/com/cyngn/eleven/adapters/DetailSongAdapter.java b/src/com/cyngn/eleven/adapters/DetailSongAdapter.java
new file mode 100644
index 0000000..3bd2321
--- /dev/null
+++ b/src/com/cyngn/eleven/adapters/DetailSongAdapter.java
@@ -0,0 +1,102 @@
+package com.cyngn.eleven.adapters;
+
+import android.app.Activity;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+import android.support.v4.content.Loader;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.cyngn.eleven.R;
+import com.cyngn.eleven.cache.ImageFetcher;
+import com.cyngn.eleven.model.Song;
+import com.cyngn.eleven.utils.ApolloUtils;
+import com.cyngn.eleven.utils.MusicUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+public abstract class DetailSongAdapter extends BaseAdapter
+implements LoaderCallbacks<List<Song>> {
+ protected final Activity mActivity;
+ private final ImageFetcher mImageFetcher;
+ private final LayoutInflater mInflater;
+ private List<Song> mSongs = Collections.emptyList();
+
+ public DetailSongAdapter(final Activity activity) {
+ mActivity = activity;
+ mImageFetcher = ApolloUtils.getImageFetcher(activity);
+ mInflater = LayoutInflater.from(activity);
+ }
+
+ @Override
+ public int getCount() { return mSongs.size(); }
+
+ @Override
+ public Song getItem(int pos) { return mSongs.get(pos); }
+
+ @Override
+ public long getItemId(int pos) { return pos; }
+
+ @Override
+ public View getView(int pos, View convertView, ViewGroup parent) {
+ if(convertView == null) {
+ convertView = mInflater.inflate(rowLayoutId(), parent, false);
+ convertView.setTag(newHolder(convertView, mImageFetcher));
+ }
+
+ Holder holder = (Holder)convertView.getTag();
+
+ Song song = getItem(pos);
+ holder.update(song);
+ addAction(convertView, pos);
+
+ return convertView;
+ }
+
+ protected abstract int rowLayoutId();
+
+ private void addAction(View view, final int position) {
+ view.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // play clicked song and enqueue all following songs
+ long[] toPlay = new long[getCount() - position];
+ for(int i = 0; i < toPlay.length; i++) {
+ toPlay[i] = getItem(position + i).mSongId;
+ }
+ MusicUtils.playAll(mActivity, toPlay, -1, false);
+ }
+ });
+ }
+
+ @Override // LoaderCallbacks
+ public void onLoadFinished(Loader<List<Song>> loader, List<Song> songs) {
+ if (songs.isEmpty()) { return; }
+ mSongs = songs;
+ notifyDataSetChanged();
+ }
+
+ @Override // LoaderCallbacks
+ public void onLoaderReset(Loader<List<Song>> loader) {
+ mSongs = Collections.emptyList();
+ notifyDataSetChanged();
+ mImageFetcher.flush();
+ }
+
+ protected abstract Holder newHolder(View root, ImageFetcher fetcher);
+
+ protected static abstract class Holder {
+ protected ImageFetcher fetcher;
+ protected TextView title;
+
+ protected Holder(View root, ImageFetcher fetcher) {
+ this.fetcher = fetcher;
+ title = (TextView)root.findViewById(R.id.title);
+ }
+
+ protected abstract void update(Song song);
+ }
+} \ No newline at end of file
diff --git a/src/com/cyngn/eleven/ui/activities/AlbumDetailActivity.java b/src/com/cyngn/eleven/ui/activities/AlbumDetailActivity.java
new file mode 100644
index 0000000..e2ee2b9
--- /dev/null
+++ b/src/com/cyngn/eleven/ui/activities/AlbumDetailActivity.java
@@ -0,0 +1,139 @@
+package com.cyngn.eleven.ui.activities;
+
+import android.app.ActionBar;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.support.v4.app.LoaderManager;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.cyngn.eleven.Config;
+import com.cyngn.eleven.R;
+import com.cyngn.eleven.adapters.AlbumDetailSongAdapter;
+import com.cyngn.eleven.adapters.DetailSongAdapter;
+import com.cyngn.eleven.cache.ImageFetcher;
+import com.cyngn.eleven.model.Song;
+import com.cyngn.eleven.utils.GenreFetcher;
+
+import java.util.List;
+import java.util.Locale;
+
+public class AlbumDetailActivity extends SlidingPanelActivity {
+
+ private ListView mSongs;
+ private DetailSongAdapter mSongAdapter;
+ private TextView mAlbumDuration;
+ private TextView mGenre;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Bundle arguments = getIntent().getExtras();
+ String artistName = arguments.getString(Config.ARTIST_NAME);
+
+ setupActionBar(artistName);
+
+ View root = findViewById(R.id.activity_base_content);
+
+ setupHeader(root, artistName, arguments);
+ setupSongList(root);
+
+ LoaderManager lm = getSupportLoaderManager();
+ lm.initLoader(1, arguments, mSongAdapter);
+ }
+
+ private void setupHeader(View root, String artist, Bundle arguments) {
+ String album = arguments.getString(Config.NAME);
+ String year = arguments.getString(Config.ALBUM_YEAR);
+ long albumId = arguments.getLong(Config.ID);
+ int songCount = arguments.getInt(Config.SONG_COUNT);
+
+ ImageView albumArt = (ImageView)root.findViewById(R.id.album_art);
+ albumArt.setContentDescription(album);
+ ImageFetcher.getInstance(this).loadAlbumImage(artist, album, albumId, albumArt);
+
+ TextView title = (TextView)root.findViewById(R.id.title);
+ title.setText(album);
+
+ setupCountAndYear(root, year, songCount);
+
+ // will be updated once we have song data
+ mAlbumDuration = (TextView)root.findViewById(R.id.duration);
+ mGenre = (TextView)root.findViewById(R.id.genre);
+ }
+
+ private void setupCountAndYear(View root, String year, int songCount) {
+ TextView songCountAndYear = (TextView)root.findViewById(R.id.song_count_and_year);
+ if(songCount > 0) {
+ String countText = getResources().
+ getQuantityString(R.plurals.Nsongs, songCount, songCount);
+ if(year == null) {
+ songCountAndYear.setText(countText);
+ } else {
+ songCountAndYear.setText(getString(R.string.combine_two_strings, countText, year));
+ }
+ } else if(year != null) {
+ songCountAndYear.setText(year);
+ }
+ }
+
+ private void setupSongList(View root) {
+ mSongs = (ListView)root.findViewById(R.id.songs);
+ mSongAdapter = new AlbumDetailSongAdapter(this);
+ mSongs.setAdapter(mSongAdapter);
+ }
+
+ @Override
+ protected int getLayoutToInflate() { return R.layout.activity_album_detail; }
+
+ protected void setupActionBar(String name) {
+ ActionBar actionBar = getActionBar();
+ actionBar.setTitle(name.toUpperCase(Locale.getDefault()));
+ actionBar.setIcon(R.drawable.ic_action_back);
+ actionBar.setHomeButtonEnabled(true);
+ }
+
+ /** cause action bar icon tap to act like back -- boo-urns! */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ /** called back by song loader */
+ public void update(List<Song> songs) {
+ /** compute total run time for album */
+ int duration = 0;
+ for(Song s : songs) { duration += s.mDuration; }
+ updateDuration(duration);
+
+ /** use the first song on the album to get a genre */
+ if(!songs.isEmpty()) {
+ GenreFetcher.fetch(this, (int)songs.get(0).mSongId, mGenre);
+ }
+ }
+
+ public void updateDuration(int duration) {
+ int mins = Math.round(duration/60);
+ int hours = mins/60;
+ mins %= 60;
+
+ String durationText = (hours == 0)
+ ? getString(R.string.duration_album_mins_only, mins)
+ : getString(R.string.duration_album_hour_mins, hours, mins);
+
+ mAlbumDuration.setText(durationText);
+ }
+} \ No newline at end of file
diff --git a/src/com/cyngn/eleven/utils/GenreFetcher.java b/src/com/cyngn/eleven/utils/GenreFetcher.java
new file mode 100644
index 0000000..befc03d
--- /dev/null
+++ b/src/com/cyngn/eleven/utils/GenreFetcher.java
@@ -0,0 +1,52 @@
+package com.cyngn.eleven.utils;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.view.View;
+import android.widget.TextView;
+
+public class GenreFetcher implements LoaderCallbacks<Cursor> {
+ private static final String[] GENRE_PROJECTION = new String[] { MediaStore.Audio.Genres.NAME };
+
+ private Context mContext;
+ private int mSongId;
+ private TextView mTextView;
+
+ public static void fetch(FragmentActivity activity, int songId, TextView textView) {
+ LoaderManager lm = activity.getSupportLoaderManager();
+ lm.initLoader(0, null, new GenreFetcher(activity, songId, textView));
+ }
+
+ private GenreFetcher(Context context, int songId, TextView textView) {
+ mContext = context;
+ mSongId = songId;
+ mTextView = textView;
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ return new CursorLoader(mContext,
+ MediaStore.Audio.Genres.getContentUriForAudioId("external", mSongId),
+ GENRE_PROJECTION, null, null, null);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ if(mTextView != null && cursor.moveToFirst()) {
+ mTextView.setText(cursor.getString(0));
+ mTextView.setVisibility(View.VISIBLE);
+ } else {
+ mTextView.setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {}
+} \ No newline at end of file
diff --git a/src/com/cyngn/eleven/utils/MusicUtils.java b/src/com/cyngn/eleven/utils/MusicUtils.java
index 6b32d4d..c59dc71 100644
--- a/src/com/cyngn/eleven/utils/MusicUtils.java
+++ b/src/com/cyngn/eleven/utils/MusicUtils.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.BaseColumns;
@@ -36,7 +35,6 @@ import android.provider.MediaStore.MediaColumns;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
-import android.view.SubMenu;
import com.cyngn.eleven.IElevenService;
import com.cyngn.eleven.MusicPlaybackService;
@@ -52,8 +50,6 @@ import com.devspark.appmsg.AppMsg;
import java.io.File;
import java.util.Arrays;
-import java.util.Formatter;
-import java.util.Locale;
import java.util.WeakHashMap;
/**
@@ -1049,12 +1045,17 @@ public final class MusicUtils {
}
}
+ public static final String getSongCountForAlbum(final Context context, final long id) {
+ Integer i = getSongCountForAlbumInt(context, id);
+ return i == null ? null : Integer.toString(i);
+ }
+
/**
* @param context The {@link Context} to use.
* @param id The id of the album.
* @return The song count for an album.
*/
- public static final String getSongCountForAlbum(final Context context, final long id) {
+ public static final Integer getSongCountForAlbumInt(final Context context, final long id) {
if (id == -1) {
return null;
}
@@ -1062,11 +1063,13 @@ public final class MusicUtils {
Cursor cursor = context.getContentResolver().query(uri, new String[] {
AlbumColumns.NUMBER_OF_SONGS
}, null, null, null);
- String songCount = null;
+ Integer songCount = null;
if (cursor != null) {
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
- songCount = cursor.getString(0);
+ if(!cursor.isNull(0)) {
+ songCount = cursor.getInt(0);
+ }
}
cursor.close();
cursor = null;
diff --git a/src/com/cyngn/eleven/utils/NavUtils.java b/src/com/cyngn/eleven/utils/NavUtils.java
index 883824c..5dbc541 100644
--- a/src/com/cyngn/eleven/utils/NavUtils.java
+++ b/src/com/cyngn/eleven/utils/NavUtils.java
@@ -21,10 +21,10 @@ import android.provider.MediaStore;
import com.cyngn.eleven.Config;
import com.cyngn.eleven.R;
+import com.cyngn.eleven.ui.activities.AlbumDetailActivity;
import com.cyngn.eleven.ui.activities.ArtistDetailActivity;
import com.cyngn.eleven.ui.activities.HomeActivity;
import com.cyngn.eleven.ui.activities.PlaylistDetailActivity;
-import com.cyngn.eleven.ui.activities.ProfileActivity;
import com.cyngn.eleven.ui.activities.SearchActivity;
import com.cyngn.eleven.ui.activities.SettingsActivity;
import com.cyngn.eleven.ui.activities.SmartPlaylistDetailActivity;
@@ -71,14 +71,15 @@ public final class NavUtils {
// Create a new bundle to transfer the album info
final Bundle bundle = new Bundle();
bundle.putString(Config.ALBUM_YEAR, MusicUtils.getReleaseDateForAlbum(context, albumId));
+ bundle.putInt(Config.SONG_COUNT, MusicUtils.getSongCountForAlbumInt(context, albumId));
bundle.putString(Config.ARTIST_NAME, artistName);
bundle.putString(Config.MIME_TYPE, MediaStore.Audio.Albums.CONTENT_TYPE);
bundle.putLong(Config.ID, albumId);
bundle.putString(Config.NAME, albumName);
// Create the intent to launch the profile activity
- final Intent intent = new Intent(context, ProfileActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Intent intent = new Intent(context, AlbumDetailActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtras(bundle);
context.startActivity(intent);
}