Updates the GridViewPager sample app

BUG: 18459358
Change-Id: I6ddfa14b66f285f40039a44af2c9425e842560b3
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/CustomFragment.java b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/CustomFragment.java
new file mode 100644
index 0000000..aff3665
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/CustomFragment.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.example.android.wearable.gridviewpager;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CustomFragment extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.custom_fragment, container, false);
+    }
+}
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/SampleGridPagerAdapter.java b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/SampleGridPagerAdapter.java
index 8f9bcf9..4d329c5 100644
--- a/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/SampleGridPagerAdapter.java
+++ b/wearable/wear/GridViewPager/Wearable/src/main/java/com/example/android/wearable/gridviewpager/SampleGridPagerAdapter.java
@@ -19,22 +19,104 @@
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.TransitionDrawable;
+import android.os.AsyncTask;
+import android.support.v4.util.LruCache;
 import android.support.wearable.view.CardFragment;
 import android.support.wearable.view.FragmentGridPagerAdapter;
-import android.support.wearable.view.ImageReference;
-import android.view.Gravity;
+import android.support.wearable.view.GridPagerAdapter;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
- * Constructs fragments as requested by the GridViewPager. For each row a
- * different background is provided.
+ * Constructs fragments as requested by the GridViewPager. For each row a different background is
+ * provided.
+ * <p>
+ * Always avoid loading resources from the main thread. In this sample, the background images are
+ * loaded from an background task and then updated using {@link #notifyRowBackgroundChanged(int)}
+ * and {@link #notifyPageBackgroundChanged(int, int)}.
  */
 public class SampleGridPagerAdapter extends FragmentGridPagerAdapter {
+    private static final int TRANSITION_DURATION_MILLIS = 100;
 
     private final Context mContext;
+    private List<Row> mRows;
+    private ColorDrawable mDefaultBg;
+
+    private ColorDrawable mClearBg;
 
     public SampleGridPagerAdapter(Context ctx, FragmentManager fm) {
         super(fm);
         mContext = ctx;
+
+        mRows = new ArrayList<SampleGridPagerAdapter.Row>();
+
+        mRows.add(new Row(cardFragment(R.string.welcome_title, R.string.welcome_text)));
+        mRows.add(new Row(cardFragment(R.string.about_title, R.string.about_text)));
+        mRows.add(new Row(
+                cardFragment(R.string.cards_title, R.string.cards_text),
+                cardFragment(R.string.expansion_title, R.string.expansion_text)));
+        mRows.add(new Row(
+                cardFragment(R.string.backgrounds_title, R.string.backgrounds_text),
+                cardFragment(R.string.columns_title, R.string.columns_text)));
+        mRows.add(new Row(new CustomFragment()));
+        mRows.add(new Row(cardFragment(R.string.dismiss_title, R.string.dismiss_text)));
+        mDefaultBg = new ColorDrawable(R.color.dark_grey);
+        mClearBg = new ColorDrawable(android.R.color.transparent);
+    }
+
+    LruCache<Integer, Drawable> mRowBackgrounds = new LruCache<Integer, Drawable>(3) {
+        @Override
+        protected Drawable create(final Integer row) {
+            int resid = BG_IMAGES[row % BG_IMAGES.length];
+            new DrawableLoadingTask(mContext) {
+                @Override
+                protected void onPostExecute(Drawable result) {
+                    TransitionDrawable background = new TransitionDrawable(new Drawable[] {
+                            mDefaultBg,
+                            result
+                    });
+                    mRowBackgrounds.put(row, background);
+                    notifyRowBackgroundChanged(row);
+                    background.startTransition(TRANSITION_DURATION_MILLIS);
+                }
+            }.execute(resid);
+            return mDefaultBg;
+        }
+    };
+
+    LruCache<Point, Drawable> mPageBackgrounds = new LruCache<Point, Drawable>(3) {
+        @Override
+        protected Drawable create(final Point page) {
+            // place bugdroid as the background at row 2, column 1
+            if (page.y == 2 && page.x == 1) {
+                int resid = R.drawable.bugdroid_large;
+                new DrawableLoadingTask(mContext) {
+                    @Override
+                    protected void onPostExecute(Drawable result) {
+                        TransitionDrawable background = new TransitionDrawable(new Drawable[] {
+                                mClearBg,
+                                result
+                        });
+                        mPageBackgrounds.put(page, background);
+                        notifyPageBackgroundChanged(page.y, page.x);
+                        background.startTransition(TRANSITION_DURATION_MILLIS);
+                    }
+                }.execute(resid);
+            }
+            return GridPagerAdapter.BACKGROUND_NONE;
+        }
+    };
+
+    private Fragment cardFragment(int titleRes, int textRes) {
+        Resources res = mContext.getResources();
+        return CardFragment.create(res.getText(titleRes), res.getText(textRes));
     }
 
     static final int[] BG_IMAGES = new int[] {
@@ -45,90 +127,67 @@
             R.drawable.debug_background_5
     };
 
-    /** A simple container for static data in each page */
-    private static class Page {
-        int titleRes;
-        int textRes;
-        int iconRes;
-        int cardGravity = Gravity.BOTTOM;
-        boolean expansionEnabled = true;
-        float expansionFactor = 1.0f;
-        int expansionDirection = CardFragment.EXPAND_DOWN;
+    /** A convenient container for a row of fragments. */
+    private class Row {
+        final List<Fragment> columns = new ArrayList<Fragment>();
 
-        public Page(int titleRes, int textRes, boolean expansion) {
-            this(titleRes, textRes, 0);
-            this.expansionEnabled = expansion;
+        public Row(Fragment... fragments) {
+            for (Fragment f : fragments) {
+                add(f);
+            }
         }
 
-        public Page(int titleRes, int textRes, boolean expansion, float expansionFactor) {
-            this(titleRes, textRes, 0);
-            this.expansionEnabled = expansion;
-            this.expansionFactor = expansionFactor;
+        public void add(Fragment f) {
+            columns.add(f);
         }
 
-        public Page(int titleRes, int textRes, int iconRes) {
-            this.titleRes = titleRes;
-            this.textRes = textRes;
-            this.iconRes = iconRes;
+        Fragment getColumn(int i) {
+            return columns.get(i);
         }
 
-        public Page(int titleRes, int textRes, int iconRes, int gravity) {
-            this.titleRes = titleRes;
-            this.textRes = textRes;
-            this.iconRes = iconRes;
-            this.cardGravity = gravity;
+        public int getColumnCount() {
+            return columns.size();
         }
     }
 
-    private final Page[][] PAGES = {
-            {
-                    new Page(R.string.welcome_title, R.string.welcome_text, R.drawable.bugdroid,
-                            Gravity.CENTER_VERTICAL),
-            },
-            {
-                    new Page(R.string.about_title, R.string.about_text, false),
-            },
-            {
-                    new Page(R.string.cards_title, R.string.cards_text, true, 2),
-                    new Page(R.string.expansion_title, R.string.expansion_text, true, 10),
-            },
-            {
-                    new Page(R.string.backgrounds_title, R.string.backgrounds_text, true, 2),
-                    new Page(R.string.columns_title, R.string.columns_text, true, 2)
-            },
-            {
-                    new Page(R.string.dismiss_title, R.string.dismiss_text, R.drawable.bugdroid,
-                            Gravity.CENTER_VERTICAL),
-            },
-
-    };
-
     @Override
     public Fragment getFragment(int row, int col) {
-        Page page = PAGES[row][col];
-        String title = page.titleRes != 0 ? mContext.getString(page.titleRes) : null;
-        String text = page.textRes != 0 ? mContext.getString(page.textRes) : null;
-        CardFragment fragment = CardFragment.create(title, text, page.iconRes);
-        // Advanced settings
-        fragment.setCardGravity(page.cardGravity);
-        fragment.setExpansionEnabled(page.expansionEnabled);
-        fragment.setExpansionDirection(page.expansionDirection);
-        fragment.setExpansionFactor(page.expansionFactor);
-        return fragment;
+        Row adapterRow = mRows.get(row);
+        return adapterRow.getColumn(col);
     }
 
     @Override
-    public ImageReference getBackground(int row, int column) {
-        return ImageReference.forDrawable(BG_IMAGES[row % BG_IMAGES.length]);
+    public Drawable getBackgroundForRow(final int row) {
+        return mRowBackgrounds.get(row);
+    }
+
+    @Override
+    public Drawable getBackgroundForPage(final int row, final int column) {
+        return mPageBackgrounds.get(new Point(column, row));
     }
 
     @Override
     public int getRowCount() {
-        return PAGES.length;
+        return mRows.size();
     }
 
     @Override
     public int getColumnCount(int rowNum) {
-        return PAGES[rowNum].length;
+        return mRows.get(rowNum).getColumnCount();
+    }
+
+    class DrawableLoadingTask extends AsyncTask<Integer, Void, Drawable> {
+        private static final String TAG = "Loader";
+        private Context context;
+
+        DrawableLoadingTask(Context context) {
+            this.context = context;
+        }
+
+        @Override
+        protected Drawable doInBackground(Integer... params) {
+            Log.d(TAG, "Loading asset 0x" + Integer.toHexString(params[0]));
+            return context.getResources().getDrawable(params[0]);
+        }
     }
 }
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-nodpi/bugdroid_large.png b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-nodpi/bugdroid_large.png
new file mode 100644
index 0000000..7b393b2
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable-nodpi/bugdroid_large.png
Binary files differ
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/gradient.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/gradient.xml
new file mode 100644
index 0000000..7077043
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/gradient.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <gradient
+        android:angle="45"
+        android:endColor="#87CEEB"
+        android:centerColor="#768087"
+        android:startColor="#000"
+        android:type="linear" />
+
+</shape>
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/shape.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/shape.xml
new file mode 100644
index 0000000..a6306c7
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/drawable/shape.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <stroke
+        android:dashGap="4dp"
+        android:dashWidth="10dp"
+        android:width="6dp"
+        android:color="@color/black" />
+
+    <solid android:color="@color/white" />
+
+    <padding
+        android:bottom="20dp"
+        android:left="20dp"
+        android:right="20dp"
+        android:top="20dp" />
+
+</shape>
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/layout/custom_fragment.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/layout/custom_fragment.xml
new file mode 100644
index 0000000..13b02f2
--- /dev/null
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/layout/custom_fragment.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/gradient" >
+
+    <TextView
+        android:id="@+id/text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_margin="8dp"
+        android:background="@drawable/shape"
+        android:text="@string/custom_fragment_text" 
+        android:textColor="@color/primary_text_light"/>
+
+</FrameLayout>
diff --git a/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml b/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml
index 404119b..ab4e663 100644
--- a/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml
+++ b/wearable/wear/GridViewPager/Wearable/src/main/res/values/strings.xml
@@ -18,39 +18,25 @@
 
     <string name="app_name">GridViewPager Sample</string>
     <string name="welcome_title">GridViewPager</string>
-    <string name="welcome_text">Welcome!</string>
+    <string name="welcome_text">Sample App</string>
 
     <string name="about_title">About</string>
-    <string name="about_text">Content is organized into multiple pages. Swipe
-        between cards to view other content.</string>
+    <string name="about_text">Content is organized into multiple pages. Swipe between cards to view other content.</string>
 
     <string name="cards_title">Cards</string>
-    <string name="cards_text">Each page is created using a CardFragment. A
-        layout is placed inside the card and the rest is handled
-        automatically.</string>
+    <string name="cards_text">Each page is created using a CardFragment. A layout is placed inside the card and the rest is handled automatically.</string>
 
     <string name="expansion_title">Expansion</string>
-    <string name="expansion_text">By default, each card will grow taller to
-        accommodate extra content. Tall cards can be scrolled through
-        like any scrollable view. The maximum height is controlled by
-        setExpansionFactor() with a default of 10 pages. After that
-        you\'ll notice a faded edge to indicate there is more. Expansion
-        can be disabled completely using setExpansionEnabled(false).
-        With this, the content will be clipped if it\'s taller than one
-        page.</string>
+    <string name="expansion_text">By default, each card will grow taller to accommodate extra content. Tall cards can be scrolled through like any scrollable view. The maximum height is controlled by setExpansionFactor() with a default of 10 pages. After that you\'ll notice a faded edge to indicate there is more. Expansion can be disabled completely using setExpansionEnabled(false). With this, the content will be clipped if it\'s taller than one page.</string>
 
     <string name="backgrounds_title">Backgrounds</string>
-    <string name="backgrounds_text">Backgrounds are supplied by the adapter\'s
-        getBackground method. Parallax and crossfade effects are applied
-        automatically.</string>
+    <string name="backgrounds_text">Backgrounds are supplied by the adapter\'s getBackground method. Parallax and crossfade effects are applied automatically.</string>
 
     <string name="columns_title">Columns</string>
-    <string name="columns_text">When moving between rows, the pager always
-        returns to column 0. This is adjustable in the adapter. See
-        method getCurrentColumnForRow().</string>
+    <string name="columns_text">When moving between rows, the pager always returns to column 0. This is adjustable in the adapter. See method getCurrentColumnForRow().</string>
 
     <string name="dismiss_title">Dismiss</string>
-    <string name="dismiss_text">To exit the application, swipe from left to
-        right.</string>
+    <string name="dismiss_text">To exit the application, swipe from left to right.</string>
+    <string name="custom_fragment_text">"GridViewPager will accept any fragment. This is an example of a custom fragment with it's own background."</string>
 
 </resources>