OSDN Git Service

Eleven: Move most activities to fragments to improve perf
authorlinus_lee <llee@cyngn.com>
Tue, 30 Sep 2014 23:51:08 +0000 (16:51 -0700)
committerlinus_lee <llee@cyngn.com>
Thu, 20 Nov 2014 20:03:04 +0000 (12:03 -0800)
Change-Id: I20cdf01a4b1a3554dfbd1c9bc2c14d4f77560ec8

31 files changed:
AndroidManifest.xml
res/anim/fade_out.xml [new file with mode: 0644]
res/layout/activity_base.xml
src/com/cyngn/eleven/adapters/AlbumDetailSongAdapter.java
src/com/cyngn/eleven/adapters/PagerAdapter.java
src/com/cyngn/eleven/adapters/ProfileSongAdapter.java
src/com/cyngn/eleven/cache/ImageFetcher.java
src/com/cyngn/eleven/ui/activities/BaseActivity.java
src/com/cyngn/eleven/ui/activities/DetailActivity.java [deleted file]
src/com/cyngn/eleven/ui/activities/HomeActivity.java
src/com/cyngn/eleven/ui/activities/SlidingPanelActivity.java
src/com/cyngn/eleven/ui/activities/SmartPlaylistDetailActivity.java [deleted file]
src/com/cyngn/eleven/ui/fragments/AlbumDetailFragment.java [moved from src/com/cyngn/eleven/ui/activities/AlbumDetailActivity.java with 61% similarity]
src/com/cyngn/eleven/ui/fragments/AlbumFragment.java
src/com/cyngn/eleven/ui/fragments/ArtistDetailFragment.java [moved from src/com/cyngn/eleven/ui/activities/ArtistDetailActivity.java with 75% similarity]
src/com/cyngn/eleven/ui/fragments/ArtistFragment.java
src/com/cyngn/eleven/ui/fragments/BaseFragment.java [new file with mode: 0644]
src/com/cyngn/eleven/ui/fragments/DetailFragment.java [new file with mode: 0644]
src/com/cyngn/eleven/ui/fragments/ISetupActionBar.java [new file with mode: 0644]
src/com/cyngn/eleven/ui/fragments/PlaylistDetailFragment.java [moved from src/com/cyngn/eleven/ui/activities/PlaylistDetailActivity.java with 78% similarity]
src/com/cyngn/eleven/ui/fragments/PlaylistFragment.java
src/com/cyngn/eleven/ui/fragments/RecentFragment.java
src/com/cyngn/eleven/ui/fragments/SongFragment.java
src/com/cyngn/eleven/ui/fragments/phone/MusicBrowserFragment.java [new file with mode: 0644]
src/com/cyngn/eleven/ui/fragments/phone/MusicBrowserPhoneFragment.java
src/com/cyngn/eleven/ui/fragments/profile/BasicSongFragment.java
src/com/cyngn/eleven/ui/fragments/profile/LastAddedFragment.java
src/com/cyngn/eleven/ui/fragments/profile/TopTracksFragment.java
src/com/cyngn/eleven/utils/NavUtils.java
src/com/cyngn/eleven/utils/PreferenceUtils.java
src/com/cyngn/eleven/widgets/BlurScrimImage.java

index 9c888c4..bfb1fef 100644 (file)
@@ -63,7 +63,7 @@
         <activity
             android:name=".ui.activities.HomeActivity"
             android:windowSoftInputMode="adjustPan"
-            android:launchMode="singleTask"
+            android:launchMode="singleTop"
             android:exported="true"
             android:screenOrientation="portrait"
             android:theme="@style/Eleven.Theme.ActionBar.Overlay">
             </intent-filter>
         </activity>
 
-        <!-- Artist Detail Activity -->
-        <activity
-            android:name=".ui.activities.ArtistDetailActivity"
-            android:excludeFromRecents="true"
-            android:screenOrientation="portrait"
-            android:theme="@style/Eleven.Theme.ActionBar.Overlay">
-        </activity>
-        <!-- Smart Playlist Detail Activity -->
-        <activity
-            android:name=".ui.activities.SmartPlaylistDetailActivity"
-            android:excludeFromRecents="true"
-            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"
-            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/anim/fade_out.xml b/res/anim/fade_out.xml
new file mode 100644 (file)
index 0000000..5b0a5da
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/fade_out.xml
+**
+** Copyright 2007, The Android Open Source Project
+**
+** 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false" android:zAdjustment="top">
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+        android:interpolator="@android:interpolator/decelerate_cubic"
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:duration="300"/>
+    <scale android:fromXScale="1.0" android:toXScale=".8"
+        android:fromYScale="1.0" android:toYScale=".8"
+        android:pivotX="50%p" android:pivotY="50%p"
+        android:interpolator="@android:interpolator/decelerate_cubic"
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:duration="300"/>
+</set>
\ No newline at end of file
index f2609b1..9513a66 100644 (file)
             android:id="@+id/activity_base_content"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:paddingTop="?android:attr/actionBarSize">
-            <ViewStub
-                    android:id="@+id/content_stub"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"/>
-        </FrameLayout>
+            android:paddingTop="?android:attr/actionBarSize" />
 
         <com.cyngn.eleven.slidinguppanel.SlidingUpPanelLayout
             xmlns:sothree="http://schemas.android.com/apk/res-auto"
index 7f5dcee..32f9f3a 100644 (file)
@@ -12,15 +12,17 @@ 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.ui.fragments.AlbumDetailFragment;
 import com.cyngn.eleven.utils.MusicUtils;
 
 import java.util.List;
 
 public class AlbumDetailSongAdapter extends DetailSongAdapter {
+    private AlbumDetailFragment mFragment;
 
-    public AlbumDetailSongAdapter(Activity activity) {
+    public AlbumDetailSongAdapter(Activity activity, AlbumDetailFragment fragment) {
         super(activity);
+        mFragment = fragment;
     }
 
     protected int rowLayoutId() { return R.layout.album_detail_song; }
@@ -33,7 +35,7 @@ public class AlbumDetailSongAdapter extends DetailSongAdapter {
     @Override // LoaderCallbacks
     public void onLoadFinished(Loader<List<Song>> loader, List<Song> songs) {
         super.onLoadFinished(loader, songs);
-        ((AlbumDetailActivity)mActivity).update(songs);
+        mFragment.update(songs);
     }
 
     protected Holder newHolder(View root, ImageFetcher fetcher) {
index 3a0746b..c9f540c 100644 (file)
 package com.cyngn.eleven.adapters;
 
 import android.app.Activity;
+import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentPagerAdapter;
 import android.util.SparseArray;
 import android.view.ViewGroup;
@@ -40,19 +42,18 @@ public class PagerAdapter extends FragmentPagerAdapter {
 
     private final List<Holder> mHolderList = Lists.newArrayList();
 
-    private final FragmentActivity mFragmentActivity;
+    private final Context mContext;
 
     private int mCurrentPage;
 
     /**
      * Constructor of <code>PagerAdatper<code>
      * 
-     * @param fragmentActivity The {@link Activity} of the
-     *            {@link Fragment}.
+     * @param fragmentManager The supporting fragment manager
      */
-    public PagerAdapter(final FragmentActivity fragmentActivity) {
-        super(fragmentActivity.getSupportFragmentManager());
-        mFragmentActivity = fragmentActivity;
+    public PagerAdapter(final Context context, final FragmentManager fragmentManager) {
+        super(fragmentManager);
+        mContext = context;
     }
 
     /**
@@ -108,7 +109,7 @@ public class PagerAdapter extends FragmentPagerAdapter {
     @Override
     public Fragment getItem(final int position) {
         final Holder mCurrentHolder = mHolderList.get(position);
-        final Fragment mFragment = Fragment.instantiate(mFragmentActivity,
+        final Fragment mFragment = Fragment.instantiate(mContext,
                 mCurrentHolder.mClassName, mCurrentHolder.mParams);
         return mFragment;
     }
@@ -138,7 +139,7 @@ public class PagerAdapter extends FragmentPagerAdapter {
      */
     @Override
     public CharSequence getPageTitle(final int position) {
-        return mFragmentActivity.getResources().getStringArray(R.array.page_titles)[position]
+        return mContext.getResources().getStringArray(R.array.page_titles)[position]
                 .toUpperCase(Locale.getDefault());
     }
 
index 52d0141..946b435 100644 (file)
@@ -17,13 +17,11 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 
-import com.cyngn.eleven.R;
 import com.cyngn.eleven.cache.ImageFetcher;
 import com.cyngn.eleven.model.Artist;
 import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.ui.MusicHolder;
 import com.cyngn.eleven.ui.fragments.profile.LastAddedFragment;
-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;
@@ -34,7 +32,7 @@ import java.util.List;
 /**
  * This {@link ArrayAdapter} is used to display the songs for a particular
  * artist, album, playlist, or genre for
- * {@link PlaylistDetailActivity},{@link LastAddedFragment}.
+ * {@link com.cyngn.eleven.ui.fragments.PlaylistDetailFragment},{@link LastAddedFragment}.
  * 
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
index 3832c6e..9afc100 100644 (file)
@@ -81,7 +81,7 @@ public class ImageFetcher extends ImageWorker {
      * Used to fetch the current artwork.
      */
     public void loadCurrentArtwork(final ImageView imageView) {
-        loadImage(generateAlbumCacheKey(MusicUtils.getAlbumName(), MusicUtils.getArtistName()),
+        loadImage(getCurrentCacheKey(),
                 MusicUtils.getArtistName(), MusicUtils.getAlbumName(), MusicUtils.getCurrentAlbumId(),
                 imageView, ImageType.ALBUM);
     }
@@ -90,11 +90,15 @@ public class ImageFetcher extends ImageWorker {
      * Used to fetch the current artwork blurred.
      */
     public void loadCurrentBlurredArtwork(final BlurScrimImage image) {
-        loadBlurImage(generateAlbumCacheKey(MusicUtils.getAlbumName(), MusicUtils.getArtistName()),
+        loadBlurImage(getCurrentCacheKey(),
                 MusicUtils.getArtistName(), MusicUtils.getAlbumName(), MusicUtils.getCurrentAlbumId(),
                 image, ImageType.ALBUM);
     }
 
+    public static String getCurrentCacheKey() {
+        return generateAlbumCacheKey(MusicUtils.getAlbumName(), MusicUtils.getArtistName());
+    }
+
     /**
      * Used to fetch artist images.
      */
index 3b144b5..82f3862 100644 (file)
@@ -13,18 +13,20 @@ package com.cyngn.eleven.ui.activities;
 
 import static com.cyngn.eleven.utils.MusicUtils.mService;
 
-import android.app.SearchManager;
-import android.app.SearchableInfo;
+import android.app.ActionBar;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.support.v4.app.FragmentActivity;
+import android.util.TypedValue;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -61,6 +63,8 @@ public abstract class BaseActivity extends FragmentActivity implements ServiceCo
      */
     private final ArrayList<MusicStateListener> mMusicStateListener = Lists.newArrayList();
 
+    private int mActionBarHeight;
+
     /**
      * The service token
      */
@@ -91,10 +95,7 @@ public abstract class BaseActivity extends FragmentActivity implements ServiceCo
      */
     private PlaybackStatus mPlaybackStatus;
 
-    /**
-     * Keeps track of the back button being used
-     */
-    private boolean mIsBackPressed = false;
+    private Drawable mActionBarBackground;
 
     /**
      * {@inheritDoc}
@@ -117,13 +118,20 @@ public abstract class BaseActivity extends FragmentActivity implements ServiceCo
 
         getActionBar().setTitle(getString(R.string.app_name).toUpperCase());
 
+        // Calculate ActionBar height
+        TypedValue value = new TypedValue();
+        if (getTheme().resolveAttribute(android.R.attr.actionBarSize, value, true))
+        {
+            mActionBarHeight = TypedValue.complexToDimensionPixelSize(value.data,
+                    getResources().getDisplayMetrics());
+        }
+
         // Set the layout
         setContentView(setContentView());
 
         // set the background on the root view
         getWindow().getDecorView().getRootView().setBackgroundColor(
                 getResources().getColor(R.color.background_color));
-
         // Initialze the bottom action bar
         initBottomActionBar();
     }
@@ -174,7 +182,11 @@ public abstract class BaseActivity extends FragmentActivity implements ServiceCo
 
             case R.id.menu_search:
                 NavUtils.openSearch(BaseActivity.this, "");
-                break;
+                return true;
+
+            case android.R.id.home:
+                getSupportFragmentManager().popBackStack();
+                return true;
 
             default:
                 break;
@@ -251,13 +263,28 @@ public abstract class BaseActivity extends FragmentActivity implements ServiceCo
         mMusicStateListener.clear();
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onBackPressed() {
-        super.onBackPressed();
-        mIsBackPressed = true;
+    public void setupActionBar(int resId) {
+        setupActionBar(getString(resId));
+    }
+
+    public void setupActionBar(String title) {
+        ActionBar actionBar = getActionBar();
+        actionBar.setTitle(title.toUpperCase());
+
+        if (mActionBarBackground == null) {
+            final int actionBarColor = getResources().getColor(R.color.header_action_bar_color);
+            mActionBarBackground = new ColorDrawable(actionBarColor);
+            actionBar.setBackgroundDrawable(mActionBarBackground);
+        }
+    }
+
+    public void setActionBarAlpha(int alpha) {
+        mActionBarBackground.setAlpha(alpha);
+    }
+
+    public void setFragmentPadding(boolean enablePadding) {
+        final int height = enablePadding ? mActionBarHeight : 0;
+        findViewById(R.id.activity_base_content).setPadding(0, height, 0, 0);
     }
 
     /**
@@ -404,6 +431,15 @@ public abstract class BaseActivity extends FragmentActivity implements ServiceCo
     }
 
     /**
+     * @param status The {@link MusicStateListener} to use
+     */
+    public void removeMusicStateListenerListener(final MusicStateListener status) {
+        if (status != null) {
+            mMusicStateListener.remove(status);
+        }
+    }
+
+    /**
      * @return The resource ID to be inflated.
      */
     public abstract int setContentView();
diff --git a/src/com/cyngn/eleven/ui/activities/DetailActivity.java b/src/com/cyngn/eleven/ui/activities/DetailActivity.java
deleted file mode 100644 (file)
index 9b95125..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.cyngn.eleven.ui.activities;
-
-import android.app.ActionBar;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
-
-import com.cyngn.eleven.R;
-
-import java.util.Locale;
-
-public abstract class DetailActivity extends SlidingPanelActivity implements
-OnScrollListener {
-    protected static final int ACTION_BAR_DEFAULT_OPACITY = 65;
-    protected Drawable mActionBarBackground;
-
-    protected void setupActionBar(String name) {
-        ActionBar actionBar = getActionBar();
-        actionBar.setTitle(name.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);
-    }
-
-    /** 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);
-        }
-    }
-
-    protected abstract int getHeaderHeight();
-
-    protected abstract void setHeaderPosition(float y);
-
-    @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();
-
-        int alpha = 255;
-        if (firstVisibleItem == 0) {
-            // move header to current top of list
-            setHeaderPosition(firstChildY);
-            // calculate alpha for the action bar
-            alpha = ACTION_BAR_DEFAULT_OPACITY +
-                    (int)((255 - ACTION_BAR_DEFAULT_OPACITY) * -firstChildY /
-                            (float)getHeaderHeight());
-            if(alpha > 255) { alpha = 255; }
-        } else {
-            // header off screen
-            setHeaderPosition(-getHeaderHeight());
-        }
-
-        mActionBarBackground.setAlpha(alpha);
-    }
-
-    @Override // OnScrollListener
-    public void onScrollStateChanged(AbsListView view, int scrollState) {}
-}
\ No newline at end of file
index 5d1447b..1f650ad 100644 (file)
@@ -17,29 +17,83 @@ package com.cyngn.eleven.ui.activities;
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+
+import com.cyngn.eleven.Config;
 import com.cyngn.eleven.R;
-import com.cyngn.eleven.ui.fragments.AudioPlayerFragment;
+import com.cyngn.eleven.ui.fragments.AlbumDetailFragment;
+import com.cyngn.eleven.ui.fragments.ArtistDetailFragment;
+import com.cyngn.eleven.ui.fragments.ISetupActionBar;
+import com.cyngn.eleven.ui.fragments.PlaylistDetailFragment;
+import com.cyngn.eleven.ui.fragments.RecentFragment;
 import com.cyngn.eleven.ui.fragments.phone.MusicBrowserPhoneFragment;
+import com.cyngn.eleven.ui.fragments.profile.LastAddedFragment;
+import com.cyngn.eleven.ui.fragments.profile.TopTracksFragment;
 
 public class HomeActivity extends SlidingPanelActivity {
+    private static final String ACTION_PREFIX = HomeActivity.class.getName();
+    public static final String ACTION_VIEW_BROWSE = ACTION_PREFIX + ".view.Browse";
+    public static final String ACTION_VIEW_MUSIC_PLAYER = ACTION_PREFIX + ".view.MusicPlayer";
+    public static final String ACTION_VIEW_QUEUE = ACTION_PREFIX + ".view.Queue";
+    public static final String ACTION_VIEW_ARTIST_DETAILS = ACTION_PREFIX + ".view.ArtistDetails";
+    public static final String ACTION_VIEW_ALBUM_DETAILS = ACTION_PREFIX + ".view.AlbumDetails";
+    public static final String ACTION_VIEW_PLAYLIST_DETAILS = ACTION_PREFIX + ".view.PlaylistDetails";
+    public static final String ACTION_VIEW_SMART_PLAYLIST = ACTION_PREFIX + ".view.SmartPlaylist";
 
-    public static final String ACTION_VIEW_BROWSE = "com.cyngn.eleven.ui.activities.HomeActivity.view.Browse";
-    public static final String ACTION_VIEW_MUSIC_PLAYER = "com.cyngn.eleven.ui.activities.HomeActivity.view.MusicPlayer";
-    public static final String ACTION_VIEW_QUEUE = "com.cyngn.eleven.ui.activities.HomeActivity.view.Queue";
+    private boolean mLoadedBaseFragment = false;
+    private Handler mHandler = new Handler();
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        if (savedInstanceState == null) {
-            getSupportFragmentManager().beginTransaction()
-                    .replace(R.id.activity_base_content, new MusicBrowserPhoneFragment()).commit();
-        }
-
         // if we've been launched by an intent, parse it
         Intent launchIntent = getIntent();
         if (launchIntent != null) {
             parseIntent(launchIntent);
         }
+
+        // if the intent didn't cause us to load a fragment, load the music browse one
+        if (!mLoadedBaseFragment) {
+            getSupportFragmentManager().beginTransaction()
+                    .replace(R.id.activity_base_content, new MusicBrowserPhoneFragment()).commit();
+
+            mLoadedBaseFragment = true;
+        }
+
+        getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
+            @Override
+            public void onBackStackChanged() {
+                Fragment topFragment = getTopFragment();
+                if (topFragment != null) {
+                    ISetupActionBar setupActionBar = (ISetupActionBar) topFragment;
+                    setupActionBar.setupActionBar();
+
+                    if (topFragment instanceof MusicBrowserPhoneFragment) {
+                        getActionBar().setIcon(R.drawable.ic_launcher);
+                        getActionBar().setHomeButtonEnabled(false);
+                    } else {
+                        getActionBar().setIcon(R.drawable.ic_action_back);
+                        getActionBar().setHomeButtonEnabled(true);
+                    }
+                }
+            }
+        });
+    }
+
+    public Fragment getTopFragment() {
+        return getSupportFragmentManager().findFragmentById(R.id.activity_base_content);
+    }
+
+    public void postRemoveFragment(final Fragment frag) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                getSupportFragmentManager().beginTransaction().remove(frag).commit();
+            }
+        });
     }
 
     @Override
@@ -50,21 +104,55 @@ public class HomeActivity extends SlidingPanelActivity {
     }
 
     private void parseIntent(Intent intent) {
-        Panel targetPanel = null;
-
         if (intent.getAction() != null) {
+            final String action = intent.getAction();
+            Fragment targetFragment = null;
+            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
 
-        } else {
-            AudioPlayerFragment player = getAudioPlayerFragment();
-            if (player != null && player.startPlayback()) {
-                targetPanel = Panel.MusicPlayer;
+            if (action.equals(ACTION_VIEW_SMART_PLAYLIST)) {
+                int playlistType = intent.getExtras().getInt(Config.SMART_PLAYLIST_TYPE);
+                switch (Config.SmartPlaylistType.values()[playlistType]) {
+                    case LastAdded:
+                        targetFragment = new LastAddedFragment();
+                        break;
+                    case RecentlyPlayed:
+                        targetFragment = new RecentFragment();
+                        break;
+                    case TopTracks:
+                        targetFragment = new TopTracksFragment();
+                        break;
+                }
+            } else if (action.equals(ACTION_VIEW_PLAYLIST_DETAILS)) {
+                targetFragment = new PlaylistDetailFragment();
+            } else if (action.equals(ACTION_VIEW_ALBUM_DETAILS)) {
+                targetFragment = new AlbumDetailFragment();
+            } else if (action.equals(ACTION_VIEW_ARTIST_DETAILS)) {
+                targetFragment = new ArtistDetailFragment();
             }
-        }
 
-        if (targetPanel != null) {
-            showPanel(targetPanel);
+            if (targetFragment != null) {
+                targetFragment.setArguments(intent.getExtras());
+                transaction.setCustomAnimations(0, 0, 0, R.anim.fade_out);
+                // If we ever come back to this because of memory concerns because
+                // none of the fragments are being removed from memory, we can fix this
+                // by using "replace" instead of "add".  The caveat is that the performance of
+                // returning to previous fragments is a bit more sluggish because the fragment
+                // view needs to be recreated. If we do remove that, we can remove the back stack
+                // change listener code above
+                transaction.add(R.id.activity_base_content, targetFragment);
+                if (mLoadedBaseFragment) {
+                    transaction.addToBackStack(null);
+                    showPanel(Panel.Browse);
+                } else {
+                    // else mark the fragment as loaded so we don't load the music browse fragment.
+                    // this happens when they launch search which is its own activity and then
+                    // browse through that back to home activity
+                    mLoadedBaseFragment = true;
+                    getActionBar().setIcon(R.drawable.ic_action_back);
+                    getActionBar().setHomeButtonEnabled(true);
+                }
+                transaction.commit();
+            }
         }
     }
-
-
 }
index fe7681e..6840fad 100644 (file)
@@ -97,18 +97,6 @@ public class SlidingPanelActivity extends BaseActivity {
 
         // get the blur scrim image
         mBlurScrimImage = (BlurScrimImage)findViewById(R.id.blurScrimImage);
-
-        if (getLayoutToInflate() != 0) {
-            ViewStub contentStub = (ViewStub) findViewById(R.id.content_stub);
-            if (contentStub != null) {
-                contentStub.setLayoutResource(getLayoutToInflate());
-                contentStub.inflate();
-            }
-        }
-    }
-
-    protected int getLayoutToInflate() {
-        return 0;
     }
 
     private void setupFirstPanel() {
diff --git a/src/com/cyngn/eleven/ui/activities/SmartPlaylistDetailActivity.java b/src/com/cyngn/eleven/ui/activities/SmartPlaylistDetailActivity.java
deleted file mode 100644 (file)
index b908e9d..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014 Cyanogen, Inc.
- */
-
-package com.cyngn.eleven.ui.activities;
-
-import android.app.ActionBar;
-import android.os.Bundle;
-import android.view.MenuItem;
-
-import com.cyngn.eleven.Config;
-import com.cyngn.eleven.R;
-import com.cyngn.eleven.ui.fragments.RecentFragment;
-import com.cyngn.eleven.ui.fragments.profile.LastAddedFragment;
-import com.cyngn.eleven.ui.fragments.profile.TopTracksFragment;
-
-import java.util.Locale;
-
-public class SmartPlaylistDetailActivity extends SlidingPanelActivity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        if (savedInstanceState == null) {
-            int playlistType = getIntent().getExtras().getInt(Config.SMART_PLAYLIST_TYPE);
-            switch (Config.SmartPlaylistType.values()[playlistType]) {
-                case LastAdded:
-                    getSupportFragmentManager().beginTransaction()
-                            .replace(R.id.activity_base_content, new LastAddedFragment()).commit();
-
-                    setupActionBar(R.string.playlist_last_added);
-                    break;
-                case RecentlyPlayed:
-                    getSupportFragmentManager().beginTransaction()
-                            .replace(R.id.activity_base_content, new RecentFragment()).commit();
-
-                    setupActionBar(R.string.playlist_recently_played);
-                    break;
-                case TopTracks:
-                    getSupportFragmentManager().beginTransaction()
-                            .replace(R.id.activity_base_content, new TopTracksFragment()).commit();
-
-                    setupActionBar(R.string.playlist_top_tracks);
-                    break;
-            }
-        }
-    }
-
-    private void setupActionBar(int resId) {
-        ActionBar actionBar = getActionBar();
-        actionBar.setTitle(getString(resId).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);
-        }
-    }
-}
\ No newline at end of file
@@ -1,14 +1,7 @@
-package com.cyngn.eleven.ui.activities;
+package com.cyngn.eleven.ui.fragments;
 
-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.FragmentManager;
 import android.support.v4.app.LoaderManager;
-import android.view.MenuItem;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.ListView;
@@ -19,21 +12,18 @@ 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.menu.DeleteDialog;
 import com.cyngn.eleven.model.Album;
 import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.utils.AlbumPopupMenuHelper;
 import com.cyngn.eleven.utils.GenreFetcher;
-import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.utils.PopupMenuHelper;
 import com.cyngn.eleven.utils.SongPopupMenuHelper;
 import com.cyngn.eleven.widgets.IPopupMenuCallback;
 import com.cyngn.eleven.widgets.PopupMenuButton;
 
 import java.util.List;
-import java.util.Locale;
 
-public class AlbumDetailActivity extends SlidingPanelActivity {
+public class AlbumDetailFragment extends BaseFragment {
     private static final int LOADER_ID = 1;
 
     private ListView mSongs;
@@ -48,45 +38,51 @@ public class AlbumDetailActivity extends SlidingPanelActivity {
     private String mAlbumName;
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+    protected int getLayoutToInflate() {
+        return R.layout.activity_album_detail;
+    }
 
-        Bundle arguments = getIntent().getExtras();
-        String artistName = arguments.getString(Config.ARTIST_NAME);
+    @Override
+    protected String getTitle() {
+        return getArguments().getString(Config.ARTIST_NAME);
+    }
 
-        setupActionBar(artistName);
+    @Override
+    protected void onViewCreated() {
+        super.onViewCreated();
 
-        View root = findViewById(R.id.activity_base_content);
+        Bundle arguments = getArguments();
+        String artistName = arguments.getString(Config.ARTIST_NAME);
 
         setupPopupMenuHelper();
-        setupHeader(root, artistName, arguments);
-        setupSongList(root);
+        setupHeader(artistName, arguments);
+        setupSongList();
 
-        LoaderManager lm = getSupportLoaderManager();
+        LoaderManager lm = getLoaderManager();
         lm.initLoader(LOADER_ID, arguments, mSongAdapter);
     }
 
-    private void setupHeader(View root, String artist, Bundle arguments) {
+    private void setupHeader(String artist, Bundle arguments) {
         mAlbumId = arguments.getLong(Config.ID);
         mArtistName = artist;
         mAlbumName = arguments.getString(Config.NAME);
         String year = arguments.getString(Config.ALBUM_YEAR);
         int songCount = arguments.getInt(Config.SONG_COUNT);
 
-        ImageView albumArt = (ImageView)root.findViewById(R.id.album_art);
+        ImageView albumArt = (ImageView)mRootView.findViewById(R.id.album_art);
         albumArt.setContentDescription(mAlbumName);
-        ImageFetcher.getInstance(this).loadAlbumImage(artist, mAlbumName, mAlbumId, albumArt);
+        ImageFetcher.getInstance(getActivity()).loadAlbumImage(artist, mAlbumName, mAlbumId, albumArt);
 
-        TextView title = (TextView)root.findViewById(R.id.title);
+        TextView title = (TextView)mRootView.findViewById(R.id.title);
         title.setText(mAlbumName);
 
-        setupCountAndYear(root, year, songCount);
+        setupCountAndYear(mRootView, year, songCount);
 
         // will be updated once we have song data
-        mAlbumDuration = (TextView)root.findViewById(R.id.duration);
-        mGenre = (TextView)root.findViewById(R.id.genre);
+        mAlbumDuration = (TextView)mRootView.findViewById(R.id.duration);
+        mGenre = (TextView)mRootView.findViewById(R.id.genre);
 
-        mPopupMenuButton = (PopupMenuButton)root.findViewById(R.id.overflow);
+        mPopupMenuButton = (PopupMenuButton)mRootView.findViewById(R.id.overflow);
         mPopupMenuButton.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
             @Override
             public void onPopupMenuClicked(View v, int position) {
@@ -111,23 +107,23 @@ public class AlbumDetailActivity extends SlidingPanelActivity {
     }
 
     private void setupPopupMenuHelper() {
-        mPopupMenuHelper = new SongPopupMenuHelper(this, getSupportFragmentManager()) {
+        mPopupMenuHelper = new SongPopupMenuHelper(getActivity(), getChildFragmentManager()) {
             @Override
             public Song getSong(int position) {
                 return mSongAdapter.getItem(position);
             }
         };
 
-        mHeaderPopupMenuHelper = new AlbumPopupMenuHelper(this, getSupportFragmentManager()) {
+        mHeaderPopupMenuHelper = new AlbumPopupMenuHelper(getActivity(), getChildFragmentManager()) {
             public Album getAlbum(int position) {
                 return new Album(mAlbumId, mAlbumName, mArtistName, -1, null);
             }
         };
     }
 
-    private void setupSongList(View root) {
-        mSongs = (ListView)root.findViewById(R.id.songs);
-        mSongAdapter = new AlbumDetailSongAdapter(this);
+    private void setupSongList() {
+        mSongs = (ListView)mRootView.findViewById(R.id.songs);
+        mSongAdapter = new AlbumDetailSongAdapter(getActivity(), this);
         mSongAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
             @Override
             public void onPopupMenuClicked(View v, int position) {
@@ -138,28 +134,6 @@ public class AlbumDetailActivity extends SlidingPanelActivity {
         mSongs.setOnItemClickListener(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 */
@@ -169,10 +143,10 @@ public class AlbumDetailActivity extends SlidingPanelActivity {
 
         /** use the first song on the album to get a genre */
         if(!songs.isEmpty()) {
-            GenreFetcher.fetch(this, (int)songs.get(0).mSongId, mGenre);
+            GenreFetcher.fetch(getActivity(), (int)songs.get(0).mSongId, mGenre);
         } else {
-            // no songs, quit this page
-            finish();
+            // no songs, remove from stack
+            getContainingActivity().postRemoveFragment(this);
         }
     }
 
@@ -190,8 +164,6 @@ public class AlbumDetailActivity extends SlidingPanelActivity {
 
     @Override
     public void restartLoader() {
-        super.restartLoader();
-
-        getSupportLoaderManager().restartLoader(LOADER_ID, getIntent().getExtras(), mSongAdapter);
+        getLoaderManager().restartLoader(LOADER_ID, getArguments(), mSongAdapter);
     }
 }
\ No newline at end of file
index b653873..ea0e12e 100644 (file)
 
 package com.cyngn.eleven.ui.fragments;
 
-import android.app.Activity;
 import android.os.Bundle;
 import android.os.SystemClock;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
 import android.view.LayoutInflater;
@@ -30,15 +27,15 @@ import android.widget.GridView;
 import com.cyngn.eleven.MusicStateListener;
 import com.cyngn.eleven.R;
 import com.cyngn.eleven.adapters.AlbumAdapter;
-import com.cyngn.eleven.cache.ImageFetcher;
+import com.cyngn.eleven.adapters.PagerAdapter;
 import com.cyngn.eleven.loaders.AlbumLoader;
-import com.cyngn.eleven.menu.DeleteDialog;
 import com.cyngn.eleven.model.Album;
 import com.cyngn.eleven.recycler.RecycleHolder;
 import com.cyngn.eleven.sectionadapter.SectionAdapter;
 import com.cyngn.eleven.sectionadapter.SectionCreator;
 import com.cyngn.eleven.sectionadapter.SectionListContainer;
 import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.ui.fragments.phone.MusicBrowserFragment;
 import com.cyngn.eleven.utils.AlbumPopupMenuHelper;
 import com.cyngn.eleven.utils.ApolloUtils;
 import com.cyngn.eleven.utils.MusicUtils;
@@ -53,8 +50,9 @@ import com.viewpagerindicator.TitlePageIndicator;
  * 
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionListContainer<Album>>,
-        OnScrollListener, OnItemClickListener, MusicStateListener {
+public class AlbumFragment extends MusicBrowserFragment implements
+        LoaderCallbacks<SectionListContainer<Album>>, OnScrollListener,
+        OnItemClickListener, MusicStateListener {
 
     /**
      * Grid view column count. ONE - list, TWO - normal grid, FOUR - landscape
@@ -62,11 +60,6 @@ public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionLi
     private static final int ONE = 1, TWO = 2, FOUR = 4;
 
     /**
-     * LoaderCallbacks identifier
-     */
-    private static final int LOADER = 0;
-
-    /**
      * Fragment UI
      */
     private ViewGroup mRootView;
@@ -86,14 +79,9 @@ public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionLi
      */
     private PopupMenuHelper mPopupMenuHelper;
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onAttach(final Activity activity) {
-        super.onAttach(activity);
-        // Register the music status listener
-        ((BaseActivity)activity).setMusicStateListenerListener(this);
+    public int getLoaderId() {
+        return PagerAdapter.MusicFragments.ALBUM.ordinal();
     }
 
     /**
@@ -129,6 +117,10 @@ public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionLi
             final Bundle savedInstanceState) {
         mRootView = (ViewGroup)inflater.inflate(R.layout.grid_base, null);
         initGridView();
+
+        // Register the music status listener
+        ((BaseActivity)getActivity()).setMusicStateListenerListener(this);
+
         return mRootView;
     }
 
@@ -141,9 +133,17 @@ public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionLi
         // Enable the options menu
         setHasOptionsMenu(true);
         // Start the loader
-        getLoaderManager().initLoader(LOADER, null, this);
+        initLoader(null, this);
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+
+        ((BaseActivity)getActivity()).removeMusicStateListenerListener(this);
+    }
+
+
     /**
      * {@inheritDoc}
      */
@@ -253,7 +253,7 @@ public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionLi
     public void refresh() {
         // Wait a moment for the preference to change.
         SystemClock.sleep(10);
-        getLoaderManager().restartLoader(LOADER, null, this);
+        restartLoader(null, this);
     }
 
     /**
@@ -271,7 +271,7 @@ public class AlbumFragment extends Fragment implements LoaderCallbacks<SectionLi
     @Override
     public void restartLoader() {
         // Update the list when the user deletes any items
-        getLoaderManager().restartLoader(LOADER, null, this);
+        restartLoader(null, this);
     }
 
     /**
@@ -1,4 +1,4 @@
-package com.cyngn.eleven.ui.activities;
+package com.cyngn.eleven.ui.fragments;
 
 import android.os.Bundle;
 import android.support.v4.app.LoaderManager;
@@ -16,6 +16,7 @@ import com.cyngn.eleven.adapters.ArtistDetailAlbumAdapter;
 import com.cyngn.eleven.adapters.ArtistDetailSongAdapter;
 import com.cyngn.eleven.adapters.IEmptyAdapterCallback;
 import com.cyngn.eleven.cache.ImageFetcher;
+import com.cyngn.eleven.lastfm.Artist;
 import com.cyngn.eleven.menu.FragmentMenuItems;
 import com.cyngn.eleven.model.Album;
 import com.cyngn.eleven.model.Song;
@@ -25,7 +26,7 @@ import com.cyngn.eleven.widgets.IPopupMenuCallback;
 
 import java.util.TreeSet;
 
-public class ArtistDetailActivity extends DetailActivity {
+public class ArtistDetailFragment extends DetailFragment {
     private final int ALBUM_LOADER_ID = 0;
     private final int SONG_LOADER_ID = 1;
     private ImageView mHero;
@@ -44,23 +45,25 @@ public class ArtistDetailActivity extends DetailActivity {
     protected int getLayoutToInflate() { return R.layout.activity_artist_detail; }
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+    protected String getTitle() {
+        return getArguments().getString(Config.ARTIST_NAME);
+    }
 
-        Bundle arguments = getIntent().getExtras();
-        String artistName = arguments.getString(Config.ARTIST_NAME);
+    @Override
+    protected void onViewCreated() {
+        super.onViewCreated();
 
-        setupActionBar(artistName);
+        getContainingActivity().setFragmentPadding(false);
 
-        ViewGroup root = (ViewGroup)findViewById(R.id.activity_base_content);
-        root.setPadding(0, 0, 0, 0); // clear default padding
+        Bundle arguments = getArguments();
+        String artistName = arguments.getString(Config.ARTIST_NAME);
 
         setupPopupMenuHelpers();
-        setupSongList(root);
+        setupSongList();
         setupAlbumList();
         setupHero(artistName);
 
-        LoaderManager lm = getSupportLoaderManager();
+        LoaderManager lm = getLoaderManager();
         lm.initLoader(ALBUM_LOADER_ID, arguments, mAlbumAdapter);
         lm.initLoader(SONG_LOADER_ID, arguments, mSongAdapter);
     }
@@ -68,14 +71,14 @@ public class ArtistDetailActivity extends DetailActivity {
     private void setupHero(String artistName) {
         mHero = (ImageView)mHeader.findViewById(R.id.hero);
         mHero.setContentDescription(artistName);
-        ImageFetcher.getInstance(this).loadArtistImage(artistName, mHero);
+        ImageFetcher.getInstance(getActivity()).loadArtistImage(artistName, mHero);
     }
 
     private void setupAlbumList() {
         mAlbums = (RecyclerView) mHeader.findViewById(R.id.albums);
         mAlbums.setHasFixedSize(true);
-        mAlbums.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
-        mAlbumAdapter = new ArtistDetailAlbumAdapter(this);
+        mAlbums.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
+        mAlbumAdapter = new ArtistDetailAlbumAdapter(getActivity());
         mAlbumAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
             @Override
             public void onPopupMenuClicked(View v, int position) {
@@ -85,18 +88,19 @@ public class ArtistDetailActivity extends DetailActivity {
         mAlbums.setAdapter(mAlbumAdapter);
     }
 
-    private void setupSongList(ViewGroup root) {
-        mSongs = (ListView)root.findViewById(R.id.songs);
-        mHeader = (ViewGroup)LayoutInflater.from(this).
+    private void setupSongList() {
+        mSongs = (ListView)mRootView.findViewById(R.id.songs);
+        mHeader = (ViewGroup)LayoutInflater.from(getActivity()).
                 inflate(R.layout.artist_detail_header, mSongs, false);
         mSongs.addHeaderView(mHeader);
         mSongs.setOnScrollListener(this);
-        mSongAdapter = new ArtistDetailSongAdapter(this);
+        mSongAdapter = new ArtistDetailSongAdapter(getActivity());
         mSongAdapter.setOnEmptyAdapterListener(new IEmptyAdapterCallback() {
             @Override
             public void onEmptyAdapter() {
-                // no results - because the user deleted the last item
-                finish();
+                // no results - because the user deleted the last item - pop our fragment
+                // from the stack
+                getContainingActivity().postRemoveFragment(ArtistDetailFragment.this);
             }
         });
         mSongAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() {
@@ -110,7 +114,7 @@ public class ArtistDetailActivity extends DetailActivity {
     }
 
     private void setupPopupMenuHelpers() {
-        mSongPopupMenuHelper = new SongPopupMenuHelper(this, getSupportFragmentManager()) {
+        mSongPopupMenuHelper = new SongPopupMenuHelper(getActivity(), getChildFragmentManager()) {
             @Override
             public Song getSong(int position) {
                 return mSongAdapter.getItem(position);
@@ -125,7 +129,7 @@ public class ArtistDetailActivity extends DetailActivity {
             }
         };
 
-        mAlbumPopupMenuHelper = new AlbumPopupMenuHelper(this, getSupportFragmentManager()) {
+        mAlbumPopupMenuHelper = new AlbumPopupMenuHelper(getActivity(), getChildFragmentManager()) {
             @Override
             public Album getAlbum(int position) {
                 return mAlbumAdapter.getItem(position);
@@ -148,10 +152,8 @@ public class ArtistDetailActivity extends DetailActivity {
 
     @Override
     public void restartLoader() {
-        super.restartLoader();
-
-        Bundle arguments = getIntent().getExtras();
-        LoaderManager lm = getSupportLoaderManager();
+        Bundle arguments = getArguments();
+        LoaderManager lm = getLoaderManager();
         lm.restartLoader(ALBUM_LOADER_ID, arguments, mAlbumAdapter);
         lm.restartLoader(SONG_LOADER_ID, arguments, mSongAdapter);
     }
index 15ff872..20cae3d 100644 (file)
 
 package com.cyngn.eleven.ui.fragments;
 
-import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
 import android.view.LayoutInflater;
@@ -31,6 +29,7 @@ import android.widget.ListView;
 import com.cyngn.eleven.MusicStateListener;
 import com.cyngn.eleven.R;
 import com.cyngn.eleven.adapters.ArtistAdapter;
+import com.cyngn.eleven.adapters.PagerAdapter;
 import com.cyngn.eleven.loaders.ArtistLoader;
 import com.cyngn.eleven.menu.DeleteDialog;
 import com.cyngn.eleven.model.Artist;
@@ -39,6 +38,7 @@ import com.cyngn.eleven.sectionadapter.SectionAdapter;
 import com.cyngn.eleven.sectionadapter.SectionCreator;
 import com.cyngn.eleven.sectionadapter.SectionListContainer;
 import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.ui.fragments.phone.MusicBrowserFragment;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.utils.NavUtils;
 import com.cyngn.eleven.utils.PopupMenuHelper;
@@ -53,15 +53,11 @@ import com.viewpagerindicator.TitlePageIndicator;
  * 
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class ArtistFragment extends Fragment implements LoaderCallbacks<SectionListContainer<Artist>>,
+public class ArtistFragment extends MusicBrowserFragment implements
+        LoaderCallbacks<SectionListContainer<Artist>>,
         OnScrollListener, OnItemClickListener, MusicStateListener {
 
     /**
-     * LoaderCallbacks identifier
-     */
-    private static final int LOADER = 0;
-
-    /**
      * Fragment UI
      */
     private ViewGroup mRootView;
@@ -87,14 +83,9 @@ public class ArtistFragment extends Fragment implements LoaderCallbacks<SectionL
     public ArtistFragment() {
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onAttach(final Activity activity) {
-        super.onAttach(activity);
-        // Register the music status listener
-        ((BaseActivity)activity).setMusicStateListenerListener(this);
+    public int getLoaderId() {
+        return PagerAdapter.MusicFragments.ARTIST.ordinal();
     }
 
     /**
@@ -152,9 +143,21 @@ public class ArtistFragment extends Fragment implements LoaderCallbacks<SectionL
         // The View for the fragment's UI
         mRootView = (ViewGroup)inflater.inflate(R.layout.list_base, null);
         initListView();
+
+        // Register the music status listener
+        ((BaseActivity)getActivity()).setMusicStateListenerListener(this);
+
         return mRootView;
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+
+        ((BaseActivity)getActivity()).removeMusicStateListenerListener(this);
+    }
+
+
     /**
      * {@inheritDoc}
      */
@@ -164,7 +167,7 @@ public class ArtistFragment extends Fragment implements LoaderCallbacks<SectionL
         // Enable the options menu
         setHasOptionsMenu(true);
         // Start the loader
-        getLoaderManager().initLoader(LOADER, null, this);
+        initLoader(null, this);
     }
 
     /**
@@ -276,7 +279,7 @@ public class ArtistFragment extends Fragment implements LoaderCallbacks<SectionL
     public void refresh() {
         // Wait a moment for the preference to change.
         SystemClock.sleep(10);
-        getLoaderManager().restartLoader(LOADER, null, this);
+        restartLoader(null, this);
     }
 
     /**
@@ -294,7 +297,7 @@ public class ArtistFragment extends Fragment implements LoaderCallbacks<SectionL
     @Override
     public void restartLoader() {
         // Update the list when the user deletes any items
-        getLoaderManager().restartLoader(LOADER, null, this);
+        restartLoader(null, this);
     }
 
     /**
diff --git a/src/com/cyngn/eleven/ui/fragments/BaseFragment.java b/src/com/cyngn/eleven/ui/fragments/BaseFragment.java
new file mode 100644 (file)
index 0000000..59dbae0
--- /dev/null
@@ -0,0 +1,66 @@
+package com.cyngn.eleven.ui.fragments;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.cyngn.eleven.MusicStateListener;
+import com.cyngn.eleven.R;
+import com.cyngn.eleven.ui.activities.HomeActivity;
+
+public abstract class BaseFragment extends Fragment implements MusicStateListener,
+    ISetupActionBar {
+
+    protected ViewGroup mRootView;
+
+    protected abstract String getTitle();
+    protected abstract int getLayoutToInflate();
+
+    @Override
+    public void setupActionBar() {
+        getContainingActivity().setupActionBar(getTitle());
+        getContainingActivity().setActionBarAlpha(255);
+        getContainingActivity().setFragmentPadding(true);
+    }
+
+    protected HomeActivity getContainingActivity() {
+        return (HomeActivity) getActivity();
+    }
+
+    @Override
+    public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        // The View for the fragment's UI
+        mRootView = (ViewGroup) inflater.inflate(getLayoutToInflate(), null);
+        // set the background color
+        mRootView.setBackgroundColor(getResources().getColor(R.color.background_color));
+
+        setupActionBar();
+
+        onViewCreated();
+
+        return mRootView;
+    }
+
+    protected void onViewCreated() {
+        getContainingActivity().setMusicStateListenerListener(this);
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+
+        getContainingActivity().removeMusicStateListenerListener(this);
+    }
+
+    @Override
+    public void onMetaChanged() {
+
+    }
+
+    @Override
+    public void onPlaylistChanged() {
+
+    }
+}
\ No newline at end of file
diff --git a/src/com/cyngn/eleven/ui/fragments/DetailFragment.java b/src/com/cyngn/eleven/ui/fragments/DetailFragment.java
new file mode 100644 (file)
index 0000000..93a6104
--- /dev/null
@@ -0,0 +1,54 @@
+package com.cyngn.eleven.ui.fragments;
+
+import android.view.View;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+
+public abstract class DetailFragment extends BaseFragment implements OnScrollListener {
+    protected static final int ACTION_BAR_DEFAULT_OPACITY = 65;
+
+    @Override
+    public void setupActionBar() {
+        super.setupActionBar();
+
+        getContainingActivity().setActionBarAlpha(ACTION_BAR_DEFAULT_OPACITY);
+        getContainingActivity().setFragmentPadding(false);
+    }
+
+    protected abstract int getHeaderHeight();
+
+    protected abstract void setHeaderPosition(float y);
+
+    @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();
+
+        int alpha = 255;
+        if (firstVisibleItem == 0) {
+            // move header to current top of list
+            setHeaderPosition(firstChildY);
+            // calculate alpha for the action bar
+            alpha = ACTION_BAR_DEFAULT_OPACITY +
+                    (int)((255 - ACTION_BAR_DEFAULT_OPACITY) * -firstChildY /
+                            (float)getHeaderHeight());
+            if(alpha > 255) { alpha = 255; }
+        } else {
+            // header off screen
+            setHeaderPosition(-getHeaderHeight());
+        }
+
+        if (getContainingActivity().getTopFragment() == this) {
+            getContainingActivity().setActionBarAlpha(alpha);
+        }
+    }
+
+    @Override // OnScrollListener
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+
+    }
+}
\ No newline at end of file
diff --git a/src/com/cyngn/eleven/ui/fragments/ISetupActionBar.java b/src/com/cyngn/eleven/ui/fragments/ISetupActionBar.java
new file mode 100644 (file)
index 0000000..6c97253
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Copyright (C) 2014 Cyanogen, Inc.
+ */
+package com.cyngn.eleven.ui.fragments;
+
+public interface ISetupActionBar {
+    public void setupActionBar();
+}
@@ -1,4 +1,4 @@
-package com.cyngn.eleven.ui.activities;
+package com.cyngn.eleven.ui.fragments;
 
 import android.database.Cursor;
 import android.net.Uri;
@@ -8,7 +8,6 @@ import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
@@ -37,7 +36,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.TreeSet;
 
-public class PlaylistDetailActivity extends DetailActivity implements
+public class PlaylistDetailFragment extends DetailFragment implements
         LoaderCallbacks<List<Song>>, OnItemClickListener, DropListener,
         RemoveListener, DragScrollProfile {
 
@@ -68,15 +67,37 @@ public class PlaylistDetailActivity extends DetailActivity implements
     private PopupMenuHelper mPopupMenuHelper;
 
     @Override
+    protected String getTitle() {
+        return getArguments().getString(Config.NAME);
+    }
+
+    @Override
     protected int getLayoutToInflate() {
         return R.layout.playlist_detail;
     }
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
+    protected void onViewCreated() {
+        super.onViewCreated();
+
+        setupHero();
+        setupSongList();
+        setupNoResultsContainer();
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        LoaderManager lm = getLoaderManager();
+        lm.initLoader(0, getArguments(), this);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mPopupMenuHelper = new SongPopupMenuHelper(this, getSupportFragmentManager()) {
+        mPopupMenuHelper = new SongPopupMenuHelper(getActivity(), getFragmentManager()) {
             @Override
             public Song getSong(int position) {
                 if (position == 0) {
@@ -97,42 +118,30 @@ public class PlaylistDetailActivity extends DetailActivity implements
             protected void removeFromPlaylist() {
                 mAdapter.remove(mSong);
                 mAdapter.notifyDataSetChanged();
-                MusicUtils.removeFromPlaylist(PlaylistDetailActivity.this, mSong.mSongId, mPlaylistId);
-                getSupportLoaderManager().restartLoader(LOADER, null, PlaylistDetailActivity.this);
+                MusicUtils.removeFromPlaylist(getActivity(), mSong.mSongId, mPlaylistId);
+                getLoaderManager().restartLoader(LOADER, null, PlaylistDetailFragment.this);
             }
         };
 
-        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);
-        setupNoResultsContainer();
-
-        LoaderManager lm = getSupportLoaderManager();
-        lm.initLoader(0, arguments, this);
+        mPlaylistId = getArguments().getLong(Config.ID);
     }
 
     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);
+        mPlaylistImageView = (ImageView)mRootView.findViewById(R.id.image);
+        mHeaderContainer = mRootView.findViewById(R.id.playlist_header);
+        mNumberOfSongs = (TextView)mRootView.findViewById(R.id.number_of_songs_text);
+        mDurationOfPlaylist = (TextView)mRootView.findViewById(R.id.duration_text);
 
-        ImageFetcher.getInstance(this).loadPlaylistArtistImage(mPlaylistId, mPlaylistImageView);
+        final ImageFetcher imageFetcher = ImageFetcher.getInstance(getActivity());
+        imageFetcher.loadPlaylistArtistImage(mPlaylistId, mPlaylistImageView);
     }
 
-    private void setupSongList(ViewGroup root) {
-        mListView = (DragSortListView) root.findViewById(R.id.list_base);
-        mListView.setOnScrollListener(this);
+    private void setupSongList() {
+        mListView = (DragSortListView) mRootView.findViewById(R.id.list_base);
+        mListView.setOnScrollListener(PlaylistDetailFragment.this);
+
         mAdapter = new ProfileSongAdapter(
-                this,
+                getActivity(),
                 R.layout.edit_track_list_item,
                 R.layout.faux_playlist_header,
                 ProfileSongAdapter.DISPLAY_PLAYLIST_SETTING
@@ -161,7 +170,7 @@ public class PlaylistDetailActivity extends DetailActivity implements
     }
 
     private void setupNoResultsContainer() {
-        mNoResultsContainer = (NoResultsContainer)findViewById(R.id.no_results_container);
+        mNoResultsContainer = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container);
         mNoResultsContainer.setMainText(R.string.empty_playlist_main);
         mNoResultsContainer.setSecondaryText(R.string.empty_playlist_secondary);
     }
@@ -187,7 +196,7 @@ public class PlaylistDetailActivity extends DetailActivity implements
         mAdapter.remove(song);
         mAdapter.notifyDataSetChanged();
         final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", mPlaylistId);
-        getContentResolver().delete(uri,
+        getActivity().getContentResolver().delete(uri,
                 MediaStore.Audio.Playlists.Members.AUDIO_ID + "=" + song.mSongId,
                 null);
     }
@@ -207,7 +216,7 @@ public class PlaylistDetailActivity extends DetailActivity implements
         mAdapter.remove(song);
         mAdapter.insert(song, realTo);
         mAdapter.notifyDataSetChanged();
-        MediaStore.Audio.Playlists.Members.moveItem(getContentResolver(),
+        MediaStore.Audio.Playlists.Members.moveItem(getActivity().getContentResolver(),
                 mPlaylistId, realFrom, realTo);
     }
 
@@ -220,17 +229,18 @@ public class PlaylistDetailActivity extends DetailActivity implements
         if (position == 0) {
             return;
         }
-        Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(this,
+        Cursor cursor = PlaylistSongLoader.makePlaylistSongCursor(getActivity(),
                 mPlaylistId);
         final long[] list = MusicUtils.getSongListForCursor(cursor);
-        MusicUtils.playAll(this, list, position - 1, false);
+        MusicUtils.playAll(getActivity(), list, position - 1, false);
         cursor.close();
         cursor = null;
     }
 
     @Override
     public void onScrollStateChanged(AbsListView view, int scrollState) {
-        // Pause disk cache access to ensure smoother scrolling
+        super.onScrollStateChanged(view, scrollState);
+
         if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING
                 || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
             mAdapter.setPauseDiskCache(true);
@@ -246,7 +256,7 @@ public class PlaylistDetailActivity extends DetailActivity implements
 
     @Override
     public Loader<List<Song>> onCreateLoader(int i, Bundle bundle) {
-        return new PlaylistSongLoader(this, mPlaylistId);
+        return new PlaylistSongLoader(getActivity(), mPlaylistId);
     }
 
     @Override
@@ -272,7 +282,8 @@ public class PlaylistDetailActivity extends DetailActivity implements
             // Return the correct count
             mAdapter.setCount(data);
             // set the number of songs
-            String numberOfSongs = MusicUtils.makeLabel(this, R.plurals.Nsongs, data.size());
+            String numberOfSongs = MusicUtils.makeLabel(getActivity(), R.plurals.Nsongs,
+                    data.size());
             mNumberOfSongs.setText(numberOfSongs);
 
             long duration = 0;
@@ -284,7 +295,7 @@ public class PlaylistDetailActivity extends DetailActivity implements
             }
 
             // set the duration
-            String durationString = MusicUtils.makeLongTimeString(this, duration);
+            String durationString = MusicUtils.makeLongTimeString(getActivity(), duration);
             mDurationOfPlaylist.setText(durationString);
         }
     }
@@ -297,8 +308,6 @@ public class PlaylistDetailActivity extends DetailActivity implements
 
     @Override
     public void restartLoader() {
-        super.restartLoader();
-
-        getSupportLoaderManager().restartLoader(0, getIntent().getExtras(), this);
+        getLoaderManager().restartLoader(0, getArguments(), this);
     }
 }
\ No newline at end of file
index 0ad8fe4..b8c639b 100644 (file)
@@ -11,7 +11,6 @@
 
 package com.cyngn.eleven.ui.fragments;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.ContentUris;
 import android.content.DialogInterface;
@@ -20,7 +19,6 @@ import android.net.Uri;
 import android.os.Bundle;
 import android.provider.MediaStore;
 import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
 import android.view.LayoutInflater;
@@ -33,11 +31,13 @@ import android.widget.ListView;
 import com.cyngn.eleven.Config.SmartPlaylistType;
 import com.cyngn.eleven.MusicStateListener;
 import com.cyngn.eleven.R;
+import com.cyngn.eleven.adapters.PagerAdapter;
 import com.cyngn.eleven.adapters.PlaylistAdapter;
 import com.cyngn.eleven.loaders.PlaylistLoader;
 import com.cyngn.eleven.model.Playlist;
 import com.cyngn.eleven.recycler.RecycleHolder;
 import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.ui.fragments.phone.MusicBrowserFragment;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.utils.NavUtils;
 import com.cyngn.eleven.utils.PopupMenuHelper;
@@ -50,15 +50,11 @@ import java.util.List;
  * 
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class PlaylistFragment extends Fragment implements LoaderCallbacks<List<Playlist>>,
+public class PlaylistFragment extends MusicBrowserFragment implements
+        LoaderCallbacks<List<Playlist>>,
         OnItemClickListener, MusicStateListener {
 
     /**
-     * LoaderCallbacks identifier
-     */
-    private static final int LOADER = 0;
-
-    /**
      * The adapter for the list
      */
     private PlaylistAdapter mAdapter;
@@ -79,14 +75,9 @@ public class PlaylistFragment extends Fragment implements LoaderCallbacks<List<P
     public PlaylistFragment() {
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onAttach(final Activity activity) {
-        super.onAttach(activity);
-        // Register the music status listener
-        ((BaseActivity)activity).setMusicStateListenerListener(this);
+    public int getLoaderId() {
+        return PagerAdapter.MusicFragments.PLAYLIST.ordinal();
     }
 
     /**
@@ -158,9 +149,21 @@ public class PlaylistFragment extends Fragment implements LoaderCallbacks<List<P
         mListView.setRecyclerListener(new RecycleHolder());
         // Play the selected song
         mListView.setOnItemClickListener(this);
+
+        // Register the music status listener
+        ((BaseActivity)getActivity()).setMusicStateListenerListener(this);
+
         return rootView;
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+
+        ((BaseActivity)getActivity()).removeMusicStateListenerListener(this);
+    }
+
+
     /**
      * {@inheritDoc}
      */
@@ -170,7 +173,7 @@ public class PlaylistFragment extends Fragment implements LoaderCallbacks<List<P
         // Enable the options menu
         setHasOptionsMenu(true);
         // Start the loader
-        getLoaderManager().initLoader(LOADER, null, this);
+        initLoader(null, this);
     }
 
     /**
@@ -231,7 +234,7 @@ public class PlaylistFragment extends Fragment implements LoaderCallbacks<List<P
      */
     @Override
     public void restartLoader() {
-        getLoaderManager().restartLoader(LOADER, null, this);
+        restartLoader(null, this);
     }
 
     @Override
index d7488e9..663a9ee 100644 (file)
@@ -13,21 +13,19 @@ package com.cyngn.eleven.ui.fragments;
 
 import android.os.Bundle;
 import android.support.v4.content.Loader;
-import android.view.Menu;
 
 import com.cyngn.eleven.Config;
-import com.cyngn.eleven.MusicStateListener;
 import com.cyngn.eleven.R;
 import com.cyngn.eleven.loaders.TopTracksLoader;
 import com.cyngn.eleven.menu.FragmentMenuItems;
 import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.sectionadapter.SectionCreator;
 import com.cyngn.eleven.sectionadapter.SectionListContainer;
+import com.cyngn.eleven.ui.activities.BaseActivity;
 import com.cyngn.eleven.ui.fragments.profile.BasicSongFragment;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.widgets.NoResultsContainer;
 
-import java.util.ArrayList;
 import java.util.TreeSet;
 
 /**
@@ -36,7 +34,7 @@ import java.util.TreeSet;
  *
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class RecentFragment extends BasicSongFragment {
+public class RecentFragment extends BasicSongFragment implements ISetupActionBar {
 
     /**
      * LoaderCallbacks identifier
@@ -85,5 +83,10 @@ public class RecentFragment extends BasicSongFragment {
         empty.setMainText(R.string.empty_recent_main);
         empty.setSecondaryText(R.string.empty_recent);
     }
+
+    @Override
+    public void setupActionBar() {
+        ((BaseActivity)getActivity()).setupActionBar(R.string.playlist_recently_played);
+    }
 }
 
index aba1be5..aaaa37f 100644 (file)
@@ -14,8 +14,10 @@ package com.cyngn.eleven.ui.fragments;
 import android.content.Context;
 import android.database.Cursor;
 import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
 import android.support.v4.content.Loader;
 
+import com.cyngn.eleven.adapters.PagerAdapter;
 import com.cyngn.eleven.loaders.SongLoader;
 import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.sectionadapter.SectionCreator;
@@ -33,11 +35,6 @@ import com.viewpagerindicator.TitlePageIndicator;
 public class SongFragment extends BasicSongFragment {
 
     /**
-     * LoaderCallbacks identifier
-     */
-    private static final int LOADER = 0;
-
-    /**
      * {@inheritDoc}
      */
     public void playAll(int position) {
@@ -70,7 +67,7 @@ public class SongFragment extends BasicSongFragment {
 
     @Override
     public int getLoaderId() {
-        return LOADER;
+        return PagerAdapter.MusicFragments.SONG.ordinal();
     }
 
     /**
@@ -104,4 +101,9 @@ public class SongFragment extends BasicSongFragment {
 
         return position;
     }
+
+    @Override
+    public LoaderManager getFragmentLoaderManager() {
+        return getParentFragment().getLoaderManager();
+    }
 }
diff --git a/src/com/cyngn/eleven/ui/fragments/phone/MusicBrowserFragment.java b/src/com/cyngn/eleven/ui/fragments/phone/MusicBrowserFragment.java
new file mode 100644 (file)
index 0000000..4a5510d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 Cyanogen, Inc.
+ */
+package com.cyngn.eleven.ui.fragments.phone;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.app.LoaderManager.LoaderCallbacks;
+
+/**
+ * This class is used for fragments under the {@link MusicBrowserFragment}
+ * Even though the containing view pager creates all the fragments, the loader
+ * does not load complete until the user navigates to that page.  To get around this
+ * we will use the containing fragment's loader manager
+ */
+public abstract class MusicBrowserFragment extends Fragment {
+    public abstract int getLoaderId();
+
+    public LoaderManager getContainingLoaderManager() {
+        return getParentFragment().getLoaderManager();
+    }
+
+    protected void initLoader(Bundle args, LoaderCallbacks<? extends Object> callback) {
+        getContainingLoaderManager().initLoader(getLoaderId(), args, callback);
+    }
+
+    protected void restartLoader(Bundle args, LoaderCallbacks<? extends Object> callback) {
+        getContainingLoaderManager().restartLoader(getLoaderId(), args, callback);
+    }
+}
index 94ccde2..5f176a8 100644 (file)
@@ -14,21 +14,18 @@ package com.cyngn.eleven.ui.fragments.phone;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.support.v4.view.ViewPager;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
 
 import com.cyngn.eleven.R;
 import com.cyngn.eleven.adapters.PagerAdapter;
 import com.cyngn.eleven.adapters.PagerAdapter.MusicFragments;
 import com.cyngn.eleven.ui.fragments.AlbumFragment;
 import com.cyngn.eleven.ui.fragments.ArtistFragment;
+import com.cyngn.eleven.ui.fragments.BaseFragment;
 import com.cyngn.eleven.ui.fragments.SongFragment;
 import com.cyngn.eleven.utils.MusicUtils;
-import com.cyngn.eleven.utils.NavUtils;
 import com.cyngn.eleven.utils.PreferenceUtils;
 import com.cyngn.eleven.utils.SortOrder;
 import com.viewpagerindicator.TitlePageIndicator;
@@ -46,7 +43,7 @@ import com.viewpagerindicator.TitlePageIndicator.OnCenterItemClickListener;
  *        Apollo for a couple of weeks or so before merging it with CM.
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class MusicBrowserPhoneFragment extends Fragment implements
+public class MusicBrowserPhoneFragment extends BaseFragment implements
         OnCenterItemClickListener {
 
     /**
@@ -67,6 +64,16 @@ public class MusicBrowserPhoneFragment extends Fragment implements
     public MusicBrowserPhoneFragment() {
     }
 
+    @Override
+    protected int getLayoutToInflate() {
+        return R.layout.fragment_music_browser_phone;
+    }
+
+    @Override
+    protected String getTitle() {
+        return getString(R.string.app_name);
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -77,25 +84,21 @@ public class MusicBrowserPhoneFragment extends Fragment implements
         mPreferences = PreferenceUtils.getInstance(getActivity());
     }
 
-    /**
-     * {@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.fragment_music_browser_phone, container, false);
+    protected void onViewCreated() {
+        super.onViewCreated();
 
-        // Initialize the adapter
-        mPagerAdapter = new PagerAdapter(getActivity());
-        final MusicFragments[] mFragments = MusicFragments.values();
-        for (final MusicFragments mFragment : mFragments) {
-            mPagerAdapter.add(mFragment.getFragmentClass(), null);
+        if (mPagerAdapter == null) {
+            // Initialize the adapter
+            mPagerAdapter = new PagerAdapter(getActivity(), getChildFragmentManager());
+            final MusicFragments[] mFragments = MusicFragments.values();
+            for (final MusicFragments mFragment : mFragments) {
+                mPagerAdapter.add(mFragment.getFragmentClass(), null);
+            }
         }
 
         // Initialize the ViewPager
-        mViewPager = (ViewPager)rootView.findViewById(R.id.fragment_home_phone_pager);
+        mViewPager = (ViewPager)mRootView.findViewById(R.id.fragment_home_phone_pager);
         // Attch the adapter
         mViewPager.setAdapter(mPagerAdapter);
         // Offscreen pager loading limit
@@ -104,13 +107,12 @@ public class MusicBrowserPhoneFragment extends Fragment implements
         mViewPager.setCurrentItem(mPreferences.getStartPage());
 
         // Initialze the TPI
-        final TitlePageIndicator pageIndicator = (TitlePageIndicator)rootView
+        final TitlePageIndicator pageIndicator = (TitlePageIndicator)mRootView
                 .findViewById(R.id.fragment_home_phone_pager_titles);
         // Attach the ViewPager
         pageIndicator.setViewPager(mViewPager);
         // Scroll to the current artist, album, or song
         pageIndicator.setOnCenterItemClickListener(this);
-        return rootView;
     }
 
     /**
@@ -291,4 +293,9 @@ public class MusicBrowserPhoneFragment extends Fragment implements
     private SongFragment getSongFragment() {
         return (SongFragment)mPagerAdapter.getFragment(MusicFragments.SONG.ordinal());
     }
+
+    @Override
+    public void restartLoader() {
+        // do nothing
+    }
 }
index 8643a58..830033e 100644 (file)
@@ -15,6 +15,7 @@ import android.app.Activity;
 import android.os.Bundle;
 import android.os.SystemClock;
 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.LayoutInflater;
@@ -78,16 +79,6 @@ public abstract class BasicSongFragment extends Fragment implements
      * {@inheritDoc}
      */
     @Override
-    public void onAttach(final Activity activity) {
-        super.onAttach(activity);
-        // Register the music status listener
-        ((BaseActivity)activity).setMusicStateListenerListener(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public void onCreate(final Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mPopupMenuHelper = new SongPopupMenuHelper(getActivity(), getFragmentManager()) {
@@ -125,6 +116,8 @@ public abstract class BasicSongFragment extends Fragment implements
                              final Bundle savedInstanceState) {
         // The View for the fragment's UI
         mRootView = (ViewGroup) inflater.inflate(R.layout.list_base, null);
+        // set the background on the root view
+        mRootView.setBackgroundColor(getResources().getColor(R.color.background_color));
         // Initialize the list
         mListView = (ListView) mRootView.findViewById(R.id.list_base);
         // Set the data behind the list
@@ -153,9 +146,19 @@ public abstract class BasicSongFragment extends Fragment implements
             }
         });
 
+        // Register the music status listener
+        ((BaseActivity)getActivity()).setMusicStateListenerListener(this);
+
         return mRootView;
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+
+        ((BaseActivity)getActivity()).removeMusicStateListenerListener(this);
+    }
+
     /**
      * This allows subclasses to customize the look and feel of the no results container
      * @param empty NoResultsContainer class
@@ -171,7 +174,7 @@ public abstract class BasicSongFragment extends Fragment implements
     public void onActivityCreated(final Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         // Start the loader
-        getLoaderManager().initLoader(getLoaderId(), null, this);
+        getFragmentLoaderManager().initLoader(getLoaderId(), null, this);
     }
 
     /**
@@ -211,7 +214,7 @@ public abstract class BasicSongFragment extends Fragment implements
     public void refresh() {
         // Wait a moment for the preference to change.
         SystemClock.sleep(10);
-        getLoaderManager().restartLoader(getLoaderId(), null, this);
+        getFragmentLoaderManager().restartLoader(getLoaderId(), null, this);
     }
 
     /**
@@ -220,7 +223,7 @@ public abstract class BasicSongFragment extends Fragment implements
     @Override
     public void restartLoader() {
         // Update the list when the user deletes any items
-        getLoaderManager().restartLoader(getLoaderId(), null, this);
+        getFragmentLoaderManager().restartLoader(getLoaderId(), null, this);
     }
 
     /**
@@ -245,6 +248,14 @@ public abstract class BasicSongFragment extends Fragment implements
         );
     }
 
+    /**
+     * Allow subclasses to specify a different loader manager
+     * @return Loader Manager to use
+     */
+    public LoaderManager getFragmentLoaderManager() {
+        return getLoaderManager();
+    }
+
     @Override
     public void onMetaChanged() {
         // do nothing
index abd115a..07e4e69 100644 (file)
@@ -11,6 +11,7 @@
 
 package com.cyngn.eleven.ui.fragments.profile;
 
+import android.app.Activity;
 import android.os.Bundle;
 import android.support.v4.content.Loader;
 
@@ -20,6 +21,8 @@ import com.cyngn.eleven.loaders.LastAddedLoader;
 import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.sectionadapter.SectionCreator;
 import com.cyngn.eleven.sectionadapter.SectionListContainer;
+import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.ui.fragments.ISetupActionBar;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.widgets.NoResultsContainer;
 
@@ -29,7 +32,7 @@ import com.cyngn.eleven.widgets.NoResultsContainer;
  *
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class LastAddedFragment extends BasicSongFragment {
+public class LastAddedFragment extends BasicSongFragment implements ISetupActionBar {
 
     /**
      * LoaderCallbacks identifier
@@ -63,4 +66,9 @@ public class LastAddedFragment extends BasicSongFragment {
         empty.setMainText(R.string.empty_last_added_main);
         empty.setSecondaryText(R.string.empty_last_added);
     }
+
+    @Override
+    public void setupActionBar() {
+        ((BaseActivity)getActivity()).setupActionBar(R.string.playlist_last_added);
+    }
 }
index dc959a1..0460f40 100644 (file)
@@ -26,6 +26,8 @@ import com.cyngn.eleven.model.Song;
 import com.cyngn.eleven.sectionadapter.SectionAdapter;
 import com.cyngn.eleven.sectionadapter.SectionCreator;
 import com.cyngn.eleven.sectionadapter.SectionListContainer;
+import com.cyngn.eleven.ui.activities.BaseActivity;
+import com.cyngn.eleven.ui.fragments.ISetupActionBar;
 import com.cyngn.eleven.utils.MusicUtils;
 import com.cyngn.eleven.widgets.NoResultsContainer;
 
@@ -35,7 +37,7 @@ import com.cyngn.eleven.widgets.NoResultsContainer;
  *
  * @author Andrew Neal (andrewdneal@gmail.com)
  */
-public class TopTracksFragment extends BasicSongFragment {
+public class TopTracksFragment extends BasicSongFragment implements ISetupActionBar {
 
     /**
      * LoaderCallbacks identifier
@@ -73,6 +75,11 @@ public class TopTracksFragment extends BasicSongFragment {
                 Config.SmartPlaylistType.TopTracks);
     }
 
+    @Override
+    public void setupActionBar() {
+        ((BaseActivity)getActivity()).setupActionBar(R.string.playlist_top_tracks);
+    }
+
     public class TopTracksAdapter extends SongAdapter {
         public TopTracksAdapter (final Activity context, final int layoutId) {
             super(context, layoutId);
index 5dbc541..f7fd50d 100644 (file)
@@ -21,13 +21,9 @@ 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.SearchActivity;
 import com.cyngn.eleven.ui.activities.SettingsActivity;
-import com.cyngn.eleven.ui.activities.SmartPlaylistDetailActivity;
 import com.devspark.appmsg.AppMsg;
 
 /**
@@ -51,8 +47,8 @@ public final class NavUtils {
         bundle.putString(Config.ARTIST_NAME, artistName);
 
         // Create the intent to launch the profile activity
-        final Intent intent = new Intent(context, ArtistDetailActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        final Intent intent = new Intent(context, HomeActivity.class);
+        intent.setAction(HomeActivity.ACTION_VIEW_ARTIST_DETAILS);
         intent.putExtras(bundle);
         context.startActivity(intent);
     }
@@ -78,15 +74,16 @@ public final class NavUtils {
         bundle.putString(Config.NAME, albumName);
 
         // Create the intent to launch the profile activity
-        final Intent intent = new Intent(context, AlbumDetailActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        final Intent intent = new Intent(context, HomeActivity.class);
+        intent.setAction(HomeActivity.ACTION_VIEW_ALBUM_DETAILS);
         intent.putExtras(bundle);
         context.startActivity(intent);
     }
 
     public static void openSmartPlaylist(final Activity context, final Config.SmartPlaylistType type) {
         // Create the intent to launch the profile activity
-        final Intent intent = new Intent(context, SmartPlaylistDetailActivity.class);
+        final Intent intent = new Intent(context, HomeActivity.class);
+        intent.setAction(HomeActivity.ACTION_VIEW_SMART_PLAYLIST);
         intent.putExtra(Config.SMART_PLAYLIST_TYPE, type.ordinal());
         context.startActivity(intent);
     }
@@ -106,7 +103,8 @@ public final class NavUtils {
         bundle.putString(Config.NAME, playlistName);
 
         // Create the intent to launch the profile activity
-        final Intent intent = new Intent(context, PlaylistDetailActivity.class);
+        final Intent intent = new Intent(context, HomeActivity.class);
+        intent.setAction(HomeActivity.ACTION_VIEW_PLAYLIST_DETAILS);
         intent.putExtras(bundle);
         context.startActivity(intent);
     }
index 1a0ce7c..2401918 100644 (file)
@@ -21,7 +21,6 @@ import com.cyngn.eleven.ui.fragments.AlbumFragment;
 import com.cyngn.eleven.ui.fragments.ArtistFragment;
 import com.cyngn.eleven.ui.fragments.SongFragment;
 import com.cyngn.eleven.ui.fragments.phone.MusicBrowserPhoneFragment;
-import com.cyngn.eleven.ui.activities.ArtistDetailActivity;
 
 /**
  * A collection of helpers designed to get and set various preferences across
@@ -236,7 +235,7 @@ public final class PreferenceUtils {
 
     /**
      * @return The sort order used for the artist album list in
-     *         {@link ArtistDetailActivity}
+     *         {@link com.cyngn.eleven.ui.fragments.ArtistDetailFragment}
      */
     public final String getArtistAlbumSortOrder() {
         return mPreferences.getString(ARTIST_ALBUM_SORT_ORDER,
index 2502374..73af3a5 100644 (file)
@@ -21,6 +21,8 @@ public class BlurScrimImage extends FrameLayout {
 
     private boolean mUsingDefaultBlur;
 
+    private String mLastLoadedKey;
+
     public BlurScrimImage(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -79,6 +81,10 @@ public class BlurScrimImage extends FrameLayout {
      * @param imageFetcher an ImageFetcher instance
      */
     public void loadBlurImage(ImageFetcher imageFetcher) {
-        imageFetcher.loadCurrentBlurredArtwork(this);
+        final String key = imageFetcher.getCurrentCacheKey();
+        if (mLastLoadedKey == null || !mLastLoadedKey.equals(key)) {
+            mLastLoadedKey = key;
+            imageFetcher.loadCurrentBlurredArtwork(this);
+        }
     }
 }