Android sample: RecyclerViewSample

Update to RecyclerViewSample to include use of GridLayoutManager
and log onClick events.

Change-Id: I6872a1d4a55efeb738336a48ed605ff1e4ad0970
diff --git a/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/CustomAdapter.java b/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/CustomAdapter.java
index f8e3bae..40f9375 100644
--- a/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/CustomAdapter.java
+++ b/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/CustomAdapter.java
@@ -34,21 +34,29 @@
 
     // BEGIN_INCLUDE(recyclerViewSampleViewHolder)
     /**
-     * Provide a reference to the type of views that you are using (custom viewholder)
+     * Provide a reference to the type of views that you are using (custom ViewHolder)
      */
     public static class ViewHolder extends RecyclerView.ViewHolder {
-        private final TextView mTextView;
+        private final TextView textView;
 
         public ViewHolder(View v) {
             super(v);
-            mTextView = (TextView) v.findViewById(R.id.textView);
+            // Define click listener for the ViewHolder's View.
+            v.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Log.d(TAG, "Element " + getPosition() + " clicked.");
+                }
+            });
+            textView = (TextView) v.findViewById(R.id.textView);
         }
 
-        public TextView getmTextView() {
-            return mTextView;
+        public TextView getTextView() {
+            return textView;
         }
     }
     // END_INCLUDE(recyclerViewSampleViewHolder)
+
     /**
      * Initialize the dataset of the Adapter.
      *
@@ -61,25 +69,24 @@
     // BEGIN_INCLUDE(recyclerViewOnCreateViewHolder)
     // Create new views (invoked by the layout manager)
     @Override
-    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
+    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
         // Create a new view.
         View v = LayoutInflater.from(viewGroup.getContext())
                 .inflate(R.layout.text_row_item, viewGroup, false);
 
-        ViewHolder vh = new ViewHolder(v);
-        return vh;
+        return new ViewHolder(v);
     }
     // END_INCLUDE(recyclerViewOnCreateViewHolder)
 
     // BEGIN_INCLUDE(recyclerViewOnBindViewHolder)
     // Replace the contents of a view (invoked by the layout manager)
     @Override
-    public void onBindViewHolder(ViewHolder viewHolder, int position) {
+    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
         Log.d(TAG, "Element " + position + " set.");
 
         // Get element from your dataset at this position and replace the contents of the view
         // with that element
-        viewHolder.getmTextView().setText(mDataSet[position]);
+        viewHolder.getTextView().setText(mDataSet[position]);
     }
     // END_INCLUDE(recyclerViewOnBindViewHolder)
 
diff --git a/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/RecyclerViewFragment.java b/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/RecyclerViewFragment.java
index 4f4a596..019657f 100644
--- a/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/RecyclerViewFragment.java
+++ b/ui/views/RecyclerView/Application/src/main/java/com/example/android/recyclerview/RecyclerViewFragment.java
@@ -18,21 +18,37 @@
 
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
+import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.RadioButton;
 
 /**
- * Demonstrates the use of RecyclerView with a LinearLayoutManager.
+ * Demonstrates the use of {@link RecyclerView} with a {@link LinearLayoutManager} and a
+ * {@link GridLayoutManager}.
  */
 public class RecyclerViewFragment extends Fragment {
 
     private static final String TAG = "RecyclerViewFragment";
+    private static final String KEY_LAYOUT_MANAGER = "layoutManager";
+    private static final int SPAN_COUNT = 2;
+    private static final int DATASET_COUNT = 60;
+
+    private enum LayoutManagerType {
+        GRID_LAYOUT_MANAGER,
+        LINEAR_LAYOUT_MANAGER
+    }
+
+    protected LayoutManagerType mCurrentLayoutManagerType;
+
+    protected RadioButton mLinearLayoutRadioButton;
+    protected RadioButton mGridLayoutRadioButton;
 
     protected RecyclerView mRecyclerView;
-    protected RecyclerView.Adapter mAdapter;
+    protected CustomAdapter mAdapter;
     protected RecyclerView.LayoutManager mLayoutManager;
     protected String[] mDataset;
 
@@ -58,23 +74,86 @@
         // to the way ListView would layout elements. The RecyclerView.LayoutManager defines how
         // elements are laid out.
         mLayoutManager = new LinearLayoutManager(getActivity());
-        mRecyclerView.setLayoutManager(mLayoutManager);
+
+        mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
+
+        if (savedInstanceState != null) {
+            // Restore saved layout manager type.
+            mCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState
+                    .getSerializable(LAYOUT_MANAGER_KEY);
+        }
+        setRecyclerViewLayoutManager(mCurrentLayoutManagerType);
 
         mAdapter = new CustomAdapter(mDataset);
         // Set CustomAdapter as the adapter for RecyclerView.
         mRecyclerView.setAdapter(mAdapter);
         // END_INCLUDE(initializeRecyclerView)
 
+        mLinearLayoutRadioButton = (RadioButton) rootView.findViewById(R.id.linear_layout_rb);
+        mLinearLayoutRadioButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                setRecyclerViewLayoutManager(LayoutManagerType.LINEAR_LAYOUT_MANAGER);
+            }
+        });
+
+        mGridLayoutRadioButton = (RadioButton) rootView.findViewById(R.id.grid_layout_rb);
+        mGridLayoutRadioButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                setRecyclerViewLayoutManager(LayoutManagerType.GRID_LAYOUT_MANAGER);
+            }
+        });
+
         return rootView;
     }
 
     /**
+     * Set RecyclerView's LayoutManager to the one given.
+     *
+     * @param layoutManagerType Type of layout manager to switch to.
+     */
+    public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
+        int scrollPosition = 0;
+
+        // If a layout manager has already been set, get current scroll position.
+        if (mRecyclerView.getLayoutManager() != null) {
+            scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
+                    .findFirstCompletelyVisibleItemPosition();
+        }
+
+        switch (layoutManagerType) {
+            case GRID_LAYOUT_MANAGER:
+                mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
+                mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
+                break;
+            case LINEAR_LAYOUT_MANAGER:
+                mLayoutManager = new LinearLayoutManager(getActivity());
+                mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
+                break;
+            default:
+                mLayoutManager = new LinearLayoutManager(getActivity());
+                mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
+        }
+
+        mRecyclerView.setLayoutManager(mLayoutManager);
+        mRecyclerView.scrollToPosition(scrollPosition);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle savedInstanceState) {
+        // Save currently selected layout manager.
+        savedInstanceState.putSerializable(LAYOUT_MANAGER_KEY, mCurrentLayoutManagerType);
+        super.onSaveInstanceState(savedInstanceState);
+    }
+
+    /**
      * Generates Strings for RecyclerView's adapter. This data would usually come
      * from a local content provider or remote server.
      */
     private void initDataset() {
-        mDataset = new String[60];
-        for (int i=0; i < 60; i++) {
+        mDataset = new String[DATASET_COUNT];
+        for (int i = 0; i < DATASET_COUNT; i++) {
             mDataset[i] = "This is element #" + i;
         }
     }
diff --git a/ui/views/RecyclerView/Application/src/main/res/layout/recycler_view_frag.xml b/ui/views/RecyclerView/Application/src/main/res/layout/recycler_view_frag.xml
index 6682468..dda99ce 100644
--- a/ui/views/RecyclerView/Application/src/main/res/layout/recycler_view_frag.xml
+++ b/ui/views/RecyclerView/Application/src/main/res/layout/recycler_view_frag.xml
@@ -15,14 +15,28 @@
  limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
+    <RadioGroup
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        android:orientation="horizontal"
+        android:checkedButton="@+id/linear_layout_rb">
+        <RadioButton android:id="@+id/linear_layout_rb"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/linear_layout_manager"/>
+        <RadioButton android:id="@+id/grid_layout_rb"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/grid_layout_manager"/>
+    </RadioGroup>
 
     <android.support.v7.widget.RecyclerView
         android:id="@+id/recyclerView"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</FrameLayout>
+        android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/ui/views/RecyclerView/Application/src/main/res/layout/text_row_item.xml b/ui/views/RecyclerView/Application/src/main/res/layout/text_row_item.xml
index d552e0e..9b94684 100644
--- a/ui/views/RecyclerView/Application/src/main/res/layout/text_row_item.xml
+++ b/ui/views/RecyclerView/Application/src/main/res/layout/text_row_item.xml
@@ -15,17 +15,16 @@
  limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_margin="@dimen/margin_small"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content">
-
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/list_item_height"
+    android:layout_marginLeft="@dimen/margin_medium"
+    android:layout_marginRight="@dimen/margin_medium"
+    android:gravity="center_vertical">
 
     <TextView
+        android:id="@+id/textView"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="@string/element_text"
-        android:id="@+id/textView"
-        android:layout_gravity="center_horizontal"/>
-</LinearLayout>
\ No newline at end of file
+        android:text="@string/element_text"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/ui/views/RecyclerView/Application/src/main/res/values/dimens.xml b/ui/views/RecyclerView/Application/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..5af7e9e
--- /dev/null
+++ b/ui/views/RecyclerView/Application/src/main/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+-->
+
+<resources>
+    <dimen name="list_item_height">72dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/ui/views/RecyclerView/Application/src/main/res/values/strings.xml b/ui/views/RecyclerView/Application/src/main/res/values/strings.xml
index 179529c..642e022 100644
--- a/ui/views/RecyclerView/Application/src/main/res/values/strings.xml
+++ b/ui/views/RecyclerView/Application/src/main/res/values/strings.xml
@@ -17,4 +17,6 @@
 
 <resources>
     <string name="element_text">Element</string>
+    <string name="grid_layout_manager">Grid Layout Manager</string>
+    <string name="linear_layout_manager">Linear Layout Manager</string>
 </resources>
\ No newline at end of file
diff --git a/ui/views/RecyclerView/template-params.xml b/ui/views/RecyclerView/template-params.xml
index 76fbd83..6e616d2 100644
--- a/ui/views/RecyclerView/template-params.xml
+++ b/ui/views/RecyclerView/template-params.xml
@@ -31,11 +31,24 @@
     <strings>
         <intro>
             <![CDATA[
-            Demonstration of using RecyclerView with a LayoutManager to create a vertical ListView.
+                Demonstration of using RecyclerView with a LinearLayoutManager and GridLayoutManager
+                to create a vertical list. Tap \"SHOW LOG\" to view elements as they are bound to
+                their ViewHolder. The log also displays elements that you tap.
             ]]>
         </intro>
     </strings>
 
+    <colors>
+        <color>
+            <name>colorPrimary</name>
+            <hexval>#00BCD4</hexval>
+        </color>
+        <color>
+            <name>colorPrimaryDark</name>
+            <hexval>#00838F</hexval>
+        </color>
+    </colors>
+
     <template src="base"/>
     <template src="FragmentView"/>
     <common src="logger"/>