OSDN Git Service

Eleven: Change playlist to the new layout, rip out dead code
authorlinus_lee <llee@cyngn.com>
Tue, 9 Sep 2014 23:28:10 +0000 (16:28 -0700)
committerlinus_lee <llee@cyngn.com>
Thu, 20 Nov 2014 20:03:03 +0000 (12:03 -0800)
Still missing the image based on the top played - this turned out to be larger so I'm
moving that to a separate changelist.  Some code similar to the ArtistDetailPage but
not enough to warrant sharing of code

Change-Id: I84454590c8d9580ca42ac8254bc3648368d233a3

18 files changed:
AndroidManifest.xml
res/drawable-xxhdpi/playlist_icon.png [new file with mode: 0644]
res/drawable-xxhdpi/stopwatch_icon_white.png [new file with mode: 0644]
res/layout/faux_playlist_header.xml [new file with mode: 0644]
res/layout/playlist_detail.xml [new file with mode: 0644]
res/layout/playlist_detail_header.xml [new file with mode: 0644]
res/values/colors.xml
res/values/dimens.xml
res/values/strings.xml
src/com/cyngn/eleven/adapters/ProfileSongAdapter.java
src/com/cyngn/eleven/adapters/SongAdapter.java
src/com/cyngn/eleven/ui/activities/PlaylistDetailActivity.java [moved from src/com/cyngn/eleven/ui/fragments/profile/PlaylistSongFragment.java with 56% similarity]
src/com/cyngn/eleven/ui/activities/ProfileActivity.java
src/com/cyngn/eleven/ui/fragments/AudioPlayerFragment.java
src/com/cyngn/eleven/ui/fragments/profile/AlbumSongFragment.java
src/com/cyngn/eleven/ui/fragments/profile/LastAddedFragment.java
src/com/cyngn/eleven/utils/MusicUtils.java
src/com/cyngn/eleven/utils/NavUtils.java

index 4ef165c..db70871 100644 (file)
             android:screenOrientation="portrait"
             android:theme="@style/Eleven.Theme.ActionBar.Overlay">
         </activity>
+        <!-- Playlist Detail Activity -->
+        <activity
+            android:name=".ui.activities.PlaylistDetailActivity"
+            android:excludeFromRecents="true"
+            android:screenOrientation="portrait"
+            android:theme="@style/Eleven.Theme.ActionBar.Overlay">
+        </activity>
         <!-- Shortcut launcher Activity -->
         <activity
             android:name=".ui.activities.ShortcutActivity"
diff --git a/res/drawable-xxhdpi/playlist_icon.png b/res/drawable-xxhdpi/playlist_icon.png
new file mode 100644 (file)
index 0000000..1be226b
Binary files /dev/null and b/res/drawable-xxhdpi/playlist_icon.png differ
diff --git a/res/drawable-xxhdpi/stopwatch_icon_white.png b/res/drawable-xxhdpi/stopwatch_icon_white.png
new file mode 100644 (file)
index 0000000..2f4059a
Binary files /dev/null and b/res/drawable-xxhdpi/stopwatch_icon_white.png differ
diff --git a/res/layout/faux_playlist_header.xml b/res/layout/faux_playlist_header.xml
new file mode 100644 (file)
index 0000000..59ab140
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2012 Andrew Neal
+  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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <include
+        layout="@layout/playlist_detail_header"
+        android:visibility="invisible" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/playlist_detail.xml b/res/layout/playlist_detail.xml
new file mode 100644 (file)
index 0000000..458737e
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 Cyanogen, Inc.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <include
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        layout="@layout/list_base_nopadding" />
+
+    <include
+        android:id="@+id/playlist_header"
+        layout="@layout/playlist_detail_header" />
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/playlist_detail_header.xml b/res/layout/playlist_detail_header.xml
new file mode 100644 (file)
index 0000000..93c2429
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright (C) 2014 Cyanogen, Inc.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/playlist_detail_header_height">
+
+    <com.cyngn.eleven.widgets.LayoutSuppressingImageView
+        android:id="@+id/image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:contentDescription="@null"
+        android:scaleType="centerCrop" />
+
+    <FrameLayout
+        android:layout_width="fill_parent"
+        android:layout_height="@dimen/playlist_detail_header_bottom_height"
+        android:layout_alignParentBottom="true"
+        android:background="@color/header_shadow_color">
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <ImageView
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:scaleType="centerInside"
+                android:src="@drawable/playlist_icon" />
+
+            <TextView
+                android:id="@+id/number_of_songs_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:fontFamily="sans-serif-light"
+                android:paddingRight="16dp"
+                android:textColor="@color/white"
+                android:textSize="@dimen/text_size_micro" />
+
+            <ImageView
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:scaleType="centerInside"
+                android:src="@drawable/stopwatch_icon_white" />
+
+            <TextView
+                android:id="@+id/duration_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:fontFamily="sans-serif-light"
+                android:textColor="@color/white"
+                android:textSize="@dimen/text_size_micro" />
+        </LinearLayout>
+    </FrameLayout>
+</RelativeLayout>
index 62579cb..1cc9430 100644 (file)
@@ -66,6 +66,8 @@
     <color name="header_action_bar_text_color">@color/white</color>
     <color name="bottom_action_bar_text_color">@color/default_text_color_light</color>
 
+    <!-- Color for background for shadow on playlist page -->
+    <color name="header_shadow_color">#ea31353f</color>
 
     <!-- Color for the pop up menu -->
     <color name="menu_divider_color">#4ca19d9e</color>
index 6437a23..7fd95f0 100644 (file)
@@ -94,6 +94,9 @@
     <dimen name="profile_carousel_label_height">45.0dip</dimen>
     <dimen name="profile_indicator_height">5.0dip</dimen>
     <dimen name="profile_label_padding">16.0dip</dimen>
+    <!-- playlist detail header -->
+    <dimen name="playlist_detail_header_height">240.0dip</dimen>
+    <dimen name="playlist_detail_header_bottom_height">40.0dip</dimen>
 
     <!-- Audio player Buttons (play/pause/shuffle/repeat/next/previous)-->
     <dimen name="audio_player_controls_end_button_width">30.0dip</dimen>
index ec7e719..84ac14c 100644 (file)
     <string name="header_5_plus_albums">5+ Albums</string>
 
     <string name="combine_two_strings">%1$s | %2$s</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>
 </resources>
index 7d80133..52f4bf1 100644 (file)
@@ -12,7 +12,6 @@
 package com.cyngn.eleven.adapters;
 
 import android.app.Activity;
-import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -27,7 +26,7 @@ import com.cyngn.eleven.ui.fragments.profile.AlbumSongFragment;
 import com.cyngn.eleven.ui.fragments.profile.ArtistSongFragment;
 import com.cyngn.eleven.ui.fragments.profile.GenreSongFragment;
 import com.cyngn.eleven.ui.fragments.profile.LastAddedFragment;
-import com.cyngn.eleven.ui.fragments.profile.PlaylistSongFragment;
+import com.cyngn.eleven.ui.activities.PlaylistDetailActivity;
 import com.cyngn.eleven.utils.ApolloUtils;
 import com.cyngn.eleven.utils.Lists;
 import com.cyngn.eleven.utils.MusicUtils;
@@ -37,7 +36,7 @@ import java.util.List;
 /**
  * This {@link ArrayAdapter} is used to display the songs for a particular
  * artist, album, playlist, or genre for {@link ArtistSongFragment},
- * {@link AlbumSongFragment},{@link PlaylistSongFragment},
+ * {@link AlbumSongFragment},{@link PlaylistDetailActivity},
  * {@link GenreSongFragment},{@link LastAddedFragment}.
  * 
  * @author Andrew Neal (andrewdneal@gmail.com)
@@ -116,12 +115,12 @@ public class ProfileSongAdapter extends ArrayAdapter<Song> {
      * @param layoutId The resource Id of the view to inflate.
      * @param setting defines the content of the second line
      */
-    public ProfileSongAdapter(final Activity activity, final int layoutId, final int setting) {
+    public ProfileSongAdapter(final Activity activity, final int layoutId, final int headerId, final int setting) {
         super(activity, 0);
         // Used to create the custom layout
         mInflater = LayoutInflater.from(activity);
         // Cache the header
-        mHeader = mInflater.inflate(R.layout.faux_carousel, null);
+        mHeader = mInflater.inflate(headerId, null);
         // Get the layout Id
         mLayoutId = layoutId;
         // Know what to put in line two
@@ -137,7 +136,7 @@ public class ProfileSongAdapter extends ArrayAdapter<Song> {
      * @param layoutId The resource Id of the view to inflate.
      */
     public ProfileSongAdapter(final Activity activity, final int layoutId) {
-        this(activity, layoutId, DISPLAY_DEFAULT_SETTING);
+        this(activity, layoutId, R.layout.faux_carousel, DISPLAY_DEFAULT_SETTING);
     }
 
     /**
@@ -177,7 +176,7 @@ public class ProfileSongAdapter extends ArrayAdapter<Song> {
                 holder.mLineOneRight.get().setVisibility(View.GONE);
 
                 holder.mLineTwo.get().setText(
-                        MusicUtils.makeTimeString(getContext(), song.mDuration));
+                        MusicUtils.makeShortTimeString(getContext(), song.mDuration));
                 break;
             case DISPLAY_PLAYLIST_SETTING:
                 if (song.mDuration == -1) {
@@ -185,7 +184,7 @@ public class ProfileSongAdapter extends ArrayAdapter<Song> {
                 } else {
                     holder.mLineOneRight.get().setVisibility(View.VISIBLE);
                     holder.mLineOneRight.get().setText(
-                            MusicUtils.makeTimeString(getContext(), song.mDuration));
+                            MusicUtils.makeShortTimeString(getContext(), song.mDuration));
                 }
 
                 final StringBuilder sb = new StringBuilder(song.mArtistName);
@@ -204,7 +203,7 @@ public class ProfileSongAdapter extends ArrayAdapter<Song> {
                 holder.mLineOneRight.get().setVisibility(View.VISIBLE);
 
                 holder.mLineOneRight.get().setText(
-                        MusicUtils.makeTimeString(getContext(), song.mDuration));
+                        MusicUtils.makeShortTimeString(getContext(), song.mDuration));
                 holder.mLineTwo.get().setText(song.mAlbumName);
                 break;
         }
index ac38cf0..6e3c8d2 100644 (file)
@@ -162,7 +162,7 @@ public class SongAdapter extends ArrayAdapter<Song> implements SectionAdapter.Ba
             // Song names (line one)
             mData[i].mLineOne = song.mSongName;
             // Song duration (line one, right)
-            mData[i].mLineOneRight = MusicUtils.makeTimeString(getContext(), song.mDuration);
+            mData[i].mLineOneRight = MusicUtils.makeShortTimeString(getContext(), song.mDuration);
             // Album names (line two)
             mData[i].mLineTwo = song.mAlbumName;
         }
@@ -1,40 +1,33 @@
-/*
- * Copyright (C) 2012 Andrew Neal 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.ui.fragments.profile;
-
-import android.app.Activity;
+package com.cyngn.eleven.ui.activities;
+
+import android.app.ActionBar;
 import android.database.Cursor;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.provider.MediaStore;
-import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
 import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MenuItem;
 import android.view.SubMenu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
 import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import com.cyngn.eleven.Config;
 import com.cyngn.eleven.R;
 import com.cyngn.eleven.adapters.ProfileSongAdapter;
+import com.cyngn.eleven.cache.ImageFetcher;
 import com.cyngn.eleven.dragdrop.DragSortListView;
 import com.cyngn.eleven.dragdrop.DragSortListView.DragScrollProfile;
 import com.cyngn.eleven.dragdrop.DragSortListView.DropListener;
@@ -47,18 +40,13 @@ import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.recycler.RecycleHolder;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.utils.NavUtils;
-import com.cyngn.eleven.widgets.ProfileTabCarousel;
-import com.cyngn.eleven.widgets.VerticalScrollListener;
 
 import java.util.List;
+import java.util.Locale;
 
-/**
- * This class is used to display all of the songs from a particular playlist.
- * 
- * @author Andrew Neal (andrewdneal@gmail.com)
- */
-public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<List<Song>>,
-        OnItemClickListener, DropListener, RemoveListener, DragScrollProfile {
+public class PlaylistDetailActivity extends SlidingPanelActivity implements
+        OnScrollListener, LoaderCallbacks<List<Song>>, OnItemClickListener, DropListener,
+        RemoveListener, DragScrollProfile {
 
     /**
      * Used to keep context menu items from bleeding into other fragments
@@ -70,15 +58,17 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
      */
     private static final int LOADER = 0;
 
-    /**
-     * The adapter for the list
-     */
-    private ProfileSongAdapter mAdapter;
+    private static final int ACTION_BAR_DEFAULT_OPACITY = 65;
+    private Drawable mActionBarBackground;
 
-    /**
-     * The list view
-     */
     private DragSortListView mListView;
+    private ProfileSongAdapter mAdapter;
+
+    private View mHeaderContainer;
+    private ImageView mPlaylistImageView;
+
+    private TextView mNumberOfSongs;
+    private TextView mDurationOfPlaylist;
 
     /**
      * Represents a song
@@ -101,56 +91,54 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
     private String mSongName, mAlbumName, mArtistName;
 
     /**
-     * Profile header
-     */
-    private ProfileTabCarousel mProfileTabCarousel;
-
-    /**
      * The Id of the playlist the songs belong to
      */
     private long mPlaylistId;
 
-    /**
-     * Empty constructor as per the {@link Fragment} documentation
-     */
-    public PlaylistSongFragment() {
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onAttach(final Activity activity) {
-        super.onAttach(activity);
-        mProfileTabCarousel = (ProfileTabCarousel)activity
-                .findViewById(R.id.acivity_profile_base_tab_carousel);
+    protected int getLayoutToInflate() {
+        return R.layout.playlist_detail;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onCreate(final Bundle savedInstanceState) {
+    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        // Create the adpater
+
+        Bundle arguments = getIntent().getExtras();
+        String playlistName = arguments.getString(Config.NAME);
+        mPlaylistId = arguments.getLong(Config.ID);
+
+        setupActionBar(playlistName);
+
+        ViewGroup root = (ViewGroup) findViewById(R.id.activity_base_content);
+        root.setPadding(0, 0, 0, 0); // clear default padding
+
+        setupHero();
+        setupSongList(root);
+
+        LoaderManager lm = getSupportLoaderManager();
+        lm.initLoader(0, arguments, this);
+    }
+
+    private void setupHero() {
+        mPlaylistImageView = (ImageView)findViewById(R.id.image);
+        mHeaderContainer = findViewById(R.id.playlist_header);
+        mNumberOfSongs = (TextView)findViewById(R.id.number_of_songs_text);
+        mDurationOfPlaylist = (TextView)findViewById(R.id.duration_text);
+
+        // TODO: Get the top artist image - do this in the next patch
+        // ImageFetcher.getInstance(this).loadCurrentArtwork(mPlaylistImageView);
+    }
+
+    private void setupSongList(ViewGroup root) {
+        mListView = (DragSortListView) root.findViewById(R.id.list_base);
+        mListView.setOnScrollListener(this);
         mAdapter = new ProfileSongAdapter(
-                getActivity(),
+                this,
                 R.layout.edit_track_list_item,
+                R.layout.faux_playlist_header,
                 ProfileSongAdapter.DISPLAY_PLAYLIST_SETTING
         );
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
-            final Bundle savedInstanceState) {
-        // The View for the fragment's UI
-        final ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.list_base_nopadding, null);
-        // Initialize the list
-        mListView = (DragSortListView)rootView.findViewById(R.id.list_base);
-        // Set the data behind the list
         mListView.setAdapter(mAdapter);
         // Release any references to the recycled Views
         mListView.setRecyclerListener(new RecycleHolder());
@@ -164,52 +152,21 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
         mListView.setRemoveListener(this);
         // Quick scroll while dragging
         mListView.setDragScrollProfile(this);
-        // To help make scrolling smooth
-        mListView.setOnScrollListener(new VerticalScrollListener(null, mProfileTabCarousel, 0) {
-            @Override
-            public void onScrollStateChanged(AbsListView view, int scrollState) {
-                super.onScrollStateChanged(view, scrollState);
-
-                // Pause disk cache access to ensure smoother scrolling
-                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
-                        || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
-                    mAdapter.setPauseDiskCache(true);
-                } else {
-                    mAdapter.setPauseDiskCache(false);
-                    mAdapter.notifyDataSetChanged();
-                }
-            }
-        });
         // Remove the scrollbars and padding for the fast scroll
         mListView.setVerticalScrollBarEnabled(false);
         mListView.setFastScrollEnabled(false);
         mListView.setPadding(0, 0, 0, 0);
-        return rootView;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onActivityCreated(final Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        // Enable the options menu
-        setHasOptionsMenu(true);
-        // Start the loader
-        final Bundle arguments = getArguments();
-        if (arguments != null) {
-            mPlaylistId = arguments.getLong(Config.ID);
-            getLoaderManager().initLoader(LOADER, arguments, this);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onSaveInstanceState(final Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putAll(getArguments() != null ? getArguments() : new Bundle());
+    private void setupActionBar(String playlistName) {
+        ActionBar actionBar = getActionBar();
+        actionBar.setTitle(playlistName.toUpperCase(Locale.getDefault()));
+        actionBar.setIcon(R.drawable.ic_action_back);
+        actionBar.setHomeButtonEnabled(true);
+        // change action bar background to a drawable we can control
+        mActionBarBackground = new ColorDrawable(getResources().getColor(R.color.header_action_bar_color));
+        mActionBarBackground.setAlpha(ACTION_BAR_DEFAULT_OPACITY);
+        actionBar.setBackgroundDrawable(mActionBarBackground);
     }
 
     /**
@@ -217,10 +174,10 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
      */
     @Override
     public void onCreateContextMenu(final ContextMenu menu, final View v,
-            final ContextMenuInfo menuInfo) {
+                                    final ContextMenu.ContextMenuInfo menuInfo) {
         super.onCreateContextMenu(menu, v, menuInfo);
         // Get the position of the selected item
-        final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
+        final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
         mSelectedPosition = info.position - 1;
         // Creat a new song
         mSong = mAdapter.getItem(mSelectedPosition);
@@ -244,7 +201,7 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
         // Add the song to a playlist
         final SubMenu subMenu = menu.addSubMenu(GROUP_ID, FragmentMenuItems.ADD_TO_PLAYLIST,
                 Menu.NONE, R.string.add_to_playlist);
-        MusicUtils.makePlaylistMenu(getActivity(), GROUP_ID, subMenu);
+        MusicUtils.makePlaylistMenu(this, GROUP_ID, subMenu);
 
         // View more content by the song artist
         menu.add(GROUP_ID, FragmentMenuItems.MORE_BY_ARTIST, Menu.NONE,
@@ -268,50 +225,50 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
         if (item.getGroupId() == GROUP_ID) {
             switch (item.getItemId()) {
                 case FragmentMenuItems.PLAY_SELECTION:
-                    MusicUtils.playAll(getActivity(), new long[] {
-                        mSelectedId
+                    MusicUtils.playAll(this, new long[]{
+                            mSelectedId
                     }, 0, false);
                     return true;
                 case FragmentMenuItems.PLAY_NEXT:
-                    MusicUtils.playNext(new long[] {
-                        mSelectedId
+                    MusicUtils.playNext(new long[]{
+                            mSelectedId
                     });
                     return true;
                 case FragmentMenuItems.ADD_TO_QUEUE:
-                    MusicUtils.addToQueue(getActivity(), new long[] {
-                        mSelectedId
+                    MusicUtils.addToQueue(this, new long[]{
+                            mSelectedId
                     });
                     return true;
                 case FragmentMenuItems.NEW_PLAYLIST:
-                    CreateNewPlaylist.getInstance(new long[] {
-                        mSelectedId
-                    }).show(getFragmentManager(), "CreatePlaylist");
+                    CreateNewPlaylist.getInstance(new long[]{
+                            mSelectedId
+                    }).show(getSupportFragmentManager(), "CreatePlaylist");
                     return true;
                 case FragmentMenuItems.PLAYLIST_SELECTED:
                     final long playlistId = item.getIntent().getLongExtra("playlist", 0);
-                    MusicUtils.addToPlaylist(getActivity(), new long[] {
-                        mSelectedId
+                    MusicUtils.addToPlaylist(this, new long[]{
+                            mSelectedId
                     }, playlistId);
                     return true;
                 case FragmentMenuItems.MORE_BY_ARTIST:
-                    NavUtils.openArtistProfile(getActivity(), mArtistName);
+                    NavUtils.openArtistProfile(this, mArtistName);
                     return true;
                 case FragmentMenuItems.USE_AS_RINGTONE:
-                    MusicUtils.setRingtone(getActivity(), mSelectedId);
+                    MusicUtils.setRingtone(this, mSelectedId);
                     return true;
                 case FragmentMenuItems.DELETE:
-                    DeleteDialog.newInstance(mSong.mSongName, new long[] {
-                        mSelectedId
-                    }, null).show(getFragmentManager(), "DeleteDialog");
+                    DeleteDialog.newInstance(mSong.mSongName, new long[]{
+                            mSelectedId
+                    }, null).show(getSupportFragmentManager(), "DeleteDialog");
                     SystemClock.sleep(10);
                     mAdapter.notifyDataSetChanged();
-                    getLoaderManager().restartLoader(LOADER, null, this);
+                    getSupportLoaderManager().restartLoader(LOADER, null, this);
                     return true;
                 case FragmentMenuItems.REMOVE_FROM_PLAYLIST:
                     mAdapter.remove(mSong);
                     mAdapter.notifyDataSetChanged();
-                    MusicUtils.removeFromPlaylist(getActivity(), mSong.mSongId, mPlaylistId);
-                    getLoaderManager().restartLoader(LOADER, null, this);
+                    MusicUtils.removeFromPlaylist(this, mSong.mSongId, mPlaylistId);
+                    getSupportLoaderManager().restartLoader(LOADER, null, this);
                     return true;
                 default:
                     break;
@@ -324,60 +281,6 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
      * {@inheritDoc}
      */
     @Override
-    public void onItemClick(final AdapterView<?> parent, final View view, final int position,
-            final long id) {
-        if (position == 0) {
-            return;
-        }
-        Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(getActivity(),
-                getArguments().getLong(Config.ID));
-        final long[] list = MusicUtils.getSongListForCursor(cursor);
-        MusicUtils.playAll(getActivity(), list, position - 1, false);
-        cursor.close();
-        cursor = null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Loader<List<Song>> onCreateLoader(final int id, final Bundle args) {
-        return new PlaylistSongLoader(getActivity(), mPlaylistId);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onLoadFinished(final Loader<List<Song>> loader, final List<Song> data) {
-        // Check for any errors
-        if (data.isEmpty()) {
-            return;
-        }
-
-        // Start fresh
-        mAdapter.unload();
-        // Return the correct count
-        mAdapter.setCount(data);
-        // Add the data to the adpater
-        for (final Song song : data) {
-            mAdapter.add(song);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onLoaderReset(final Loader<List<Song>> loader) {
-        // Clear the data in the adapter
-        mAdapter.unload();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public float getSpeed(final float w, final long t) {
         if (w > 0.8f) {
             return mAdapter.getCount() / 0.001f;
@@ -395,7 +298,7 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
         mAdapter.remove(mSong);
         mAdapter.notifyDataSetChanged();
         final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", mPlaylistId);
-        getActivity().getContentResolver().delete(uri,
+        getContentResolver().delete(uri,
                 MediaStore.Audio.Playlists.Members.AUDIO_ID + "=" + mSong.mSongId,
                 null);
     }
@@ -415,7 +318,115 @@ public class PlaylistSongFragment extends Fragment implements LoaderCallbacks<Li
         mAdapter.remove(mSong);
         mAdapter.insert(mSong, realTo);
         mAdapter.notifyDataSetChanged();
-        MediaStore.Audio.Playlists.Members.moveItem(getActivity().getContentResolver(),
+        MediaStore.Audio.Playlists.Members.moveItem(getContentResolver(),
                 mPlaylistId, realFrom, realTo);
     }
-}
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onItemClick(final AdapterView<?> parent, final View view, final int position,
+                            final long id) {
+        if (position == 0) {
+            return;
+        }
+        Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(this,
+                mPlaylistId);
+        final long[] list = MusicUtils.getSongListForCursor(cursor);
+        MusicUtils.playAll(this, list, position - 1, false);
+        cursor.close();
+        cursor = null;
+    }
+
+    /**
+     * 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);
+        }
+    }
+
+    @Override
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+        // Pause disk cache access to ensure smoother scrolling
+        if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
+                || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
+            mAdapter.setPauseDiskCache(true);
+        } else {
+            mAdapter.setPauseDiskCache(false);
+            mAdapter.notifyDataSetChanged();
+        }
+    }
+
+    @Override // OnScrollListener
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+        View firstChild = view.getChildAt(0);
+        if (firstChild == null) {
+            return;
+        }
+
+        float firstChildY = firstChild.getY();
+
+        // if the first fake header is off the screen,
+        // set opaque and header container to be off screen
+        if (firstVisibleItem != 0) {
+            mHeaderContainer.setY(-mHeaderContainer.getHeight());
+            mActionBarBackground.setAlpha(255);
+        } else {
+            // otherwise set the offset and calculate the alpha
+            mHeaderContainer.setY(firstChildY);
+            int alpha = ACTION_BAR_DEFAULT_OPACITY +
+                    (int)((255 - ACTION_BAR_DEFAULT_OPACITY) * -firstChildY /
+                            (float)mHeaderContainer.getHeight());
+
+            alpha = Math.min(255, alpha);
+            mActionBarBackground.setAlpha(alpha);
+        }
+    }
+
+    @Override
+    public Loader<List<Song>> onCreateLoader(int i, Bundle bundle) {
+        return new PlaylistSongLoader(this, mPlaylistId);
+    }
+
+    @Override
+    public void onLoadFinished(final Loader<List<Song>> loader, final List<Song> data) {
+        // Check for any errors
+        if (data.isEmpty()) {
+            return;
+        }
+
+        // Start fresh
+        mAdapter.unload();
+        // Return the correct count
+        mAdapter.setCount(data);
+        // set the number of songs
+        String numberOfSongs = MusicUtils.makeLabel(this, R.plurals.Nsongs, data.size());
+        mNumberOfSongs.setText(numberOfSongs);
+
+        long duration = 0;
+
+        // Add the data to the adapter
+        for (final Song song : data) {
+            mAdapter.add(song);
+            duration += song.mDuration;
+        }
+
+        // set the duration
+        String durationString = MusicUtils.makeLongTimeString(this, duration);
+        mDurationOfPlaylist.setText(durationString);
+    }
+
+    @Override
+    public void onLoaderReset(final Loader<List<Song>> loader) {
+        // Clear the data in the adapter
+        mAdapter.unload();
+    }
+}
\ No newline at end of file
index 8d570dd..6b7951d 100644 (file)
@@ -39,7 +39,6 @@ import com.cyngn.eleven.ui.fragments.profile.ArtistAlbumFragment;
 import com.cyngn.eleven.ui.fragments.profile.ArtistSongFragment;
 import com.cyngn.eleven.ui.fragments.profile.GenreSongFragment;
 import com.cyngn.eleven.ui.fragments.profile.LastAddedFragment;
-import com.cyngn.eleven.ui.fragments.profile.PlaylistSongFragment;
 import com.cyngn.eleven.utils.ApolloUtils;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.utils.NavUtils;
@@ -191,17 +190,6 @@ public class ProfileActivity extends SlidingPanelActivity implements OnPageChang
             // Action bar title = Last added
             getActionBar().setTitle(mProfileName);
         } else
-        // Set up the user playlist profile
-        if (isPlaylist()) {
-            // Add the carousel images
-            mTabCarousel.setPlaylistOrGenreProfileHeader(this, mProfileName);
-
-            // Playlist profile fragments
-            mPagerAdapter.add(PlaylistSongFragment.class, mArguments);
-
-            // Action bar title = playlist name
-            getActionBar().setTitle(mProfileName);
-        } else
         // Set up the genre profile
         if (isGenre()) {
             // Add the carousel images
@@ -248,7 +236,7 @@ public class ProfileActivity extends SlidingPanelActivity implements OnPageChang
         // Set the shuffle all title to "play all" if a playlist.
         final MenuItem shuffle = menu.findItem(R.id.menu_shuffle);
         String title = null;
-        if (isLastAdded() || isPlaylist()) {
+        if (isLastAdded()) {
             title = getString(R.string.menu_play_all);
         } else {
             title = getString(R.string.menu_shuffle);
@@ -301,9 +289,7 @@ public class ProfileActivity extends SlidingPanelActivity implements OnPageChang
                 } else if (isGenre()) {
                     list = MusicUtils.getSongListForGenre(this, id);
                 }
-                if (isPlaylist()) {
-                    MusicUtils.playPlaylist(this, id);
-                } else if (isLastAdded()) {
+                if (isLastAdded()) {
                     MusicUtils.playLastAdded(this);
                 } else {
                     if (list != null && list.length > 0) {
@@ -620,14 +606,6 @@ public class ProfileActivity extends SlidingPanelActivity implements OnPageChang
     }
 
     /**
-     * @return True if the MIME type is vnd.android.cursor.dir/playlist, false
-     *         otherwise.
-     */
-    private final boolean isPlaylist() {
-        return mType.equals(MediaStore.Audio.Playlists.CONTENT_TYPE);
-    }
-
-    /**
      * @return True if the MIME type is "LastAdded", false otherwise.
      */
     private final boolean isLastAdded() {
index a47d96b..dbf85d4 100644 (file)
@@ -356,7 +356,7 @@ public class AudioPlayerFragment extends Fragment implements ServiceConnection {
         mTrackName.setText(MusicUtils.getTrackName());
 
         // Set the total time
-        String totalTime = MusicUtils.makeTimeString(getActivity(), MusicUtils.duration() / 1000);
+        String totalTime = MusicUtils.makeShortTimeString(getActivity(), MusicUtils.duration() / 1000);
         if (!mTotalTime.getText().equals(totalTime)) {
             mTotalTime.setText(totalTime);
         }
@@ -579,7 +579,7 @@ public class AudioPlayerFragment extends Fragment implements ServiceConnection {
     }
 
     private void refreshCurrentTimeText(final long pos) {
-        mCurrentTime.setText(MusicUtils.makeTimeString(getActivity(), pos / 1000));
+        mCurrentTime.setText(MusicUtils.makeShortTimeString(getActivity(), pos / 1000));
     }
 
     /* Used to update the current time string */
index b99fe8b..46aa066 100644 (file)
@@ -124,6 +124,7 @@ public class AlbumSongFragment extends Fragment implements LoaderCallbacks<List<
         mAdapter = new ProfileSongAdapter(
                 getActivity(),
                 R.layout.list_item_simple,
+                R.layout.faux_carousel,
                 ProfileSongAdapter.DISPLAY_ALBUM_SETTING
         );
     }
index ffbf4b6..96a4a18 100644 (file)
@@ -132,6 +132,7 @@ public class LastAddedFragment extends Fragment implements LoaderCallbacks<List<
         mAdapter = new ProfileSongAdapter(
                 getActivity(),
                 R.layout.list_item_normal,
+                R.layout.faux_carousel,
                 ProfileSongAdapter.DISPLAY_PLAYLIST_SETTING
         );
     }
index d4067ba..edd741e 100644 (file)
@@ -190,13 +190,13 @@ public final class MusicUtils {
      * @param secs The track in seconds.
      * @return Duration of a track that's properly formatted.
      */
-    public static final String makeTimeString(final Context context, long secs) {
+    public static final String makeShortTimeString(final Context context, long secs) {
         long hours, mins;
 
         hours = secs / 3600;
-        secs -= hours * 3600;
+        secs %= 3600;
         mins = secs / 60;
-        secs -= mins * 60;
+        secs %= 60;
 
         final String durationFormat = context.getResources().getString(
                 hours == 0 ? R.string.durationformatshort : R.string.durationformatlong);
@@ -204,6 +204,34 @@ public final class MusicUtils {
     }
 
     /**
+     * * Used to create a formatted time string in the format of #d #h #m #s
+     *
+     * @param context The {@link Context} to use.
+     * @param secs The duration seconds.
+     * @return Duration properly formatted in #d #h #m #s format
+     */
+    public static final String makeLongTimeString(final Context context, long secs) {
+        long days, hours, mins;
+
+        days = secs / (3600 * 24);
+        secs %= (3600 * 24);
+        hours = secs / 3600;
+        secs %= 3600;
+        mins = secs / 60;
+        secs %= 60;
+
+        int stringId = R.string.duration_mins;
+        if (days != 0) {
+            stringId = R.string.duration_days;
+        } else if (hours != 0) {
+            stringId = R.string.duration_hours;
+        }
+
+        final String durationFormat = context.getResources().getString(stringId);
+        return String.format(durationFormat, days, hours, mins, secs);
+    }
+
+    /**
      * Changes to the next track
      */
     public static void next() {
@@ -1288,6 +1316,7 @@ public final class MusicUtils {
             try {
                 return mService.duration();
             } catch (final RemoteException ignored) {
+            } catch (final IllegalStateException ignored) {
             }
         }
         return 0;
index f18f861..4fdfacb 100644 (file)
@@ -23,6 +23,7 @@ import com.cyngn.eleven.Config;
 import com.cyngn.eleven.R;
 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;
@@ -101,7 +102,7 @@ public final class NavUtils {
         bundle.putString(Config.NAME, playlistName);
 
         // Create the intent to launch the profile activity
-        final Intent intent = new Intent(context, ProfileActivity.class);
+        final Intent intent = new Intent(context, PlaylistDetailActivity.class);
         intent.putExtras(bundle);
         context.startActivity(intent);
     }