Add RecyclerView animations for change actions

Issue #15691746 RecyclerView item animations for changed/resizing item views

Change-Id: Ibe735eefa704189d17f63406de941d76282e9272
diff --git a/samples/Support7Demos/res/layout/animated_recycler_view.xml b/samples/Support7Demos/res/layout/animated_recycler_view.xml
index 8fed40c..b719f1a 100644
--- a/samples/Support7Demos/res/layout/animated_recycler_view.xml
+++ b/samples/Support7Demos/res/layout/animated_recycler_view.xml
@@ -25,6 +25,13 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"/>
 
+        <CheckBox
+                android:id="@+id/enableChangeAnimations"
+                android:checked="false"
+                android:text="@string/enableChangeAnimations"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+
     </LinearLayout>
 
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/samples/Support7Demos/res/layout/selectable_item.xml b/samples/Support7Demos/res/layout/selectable_item.xml
index 65a23cc..3cab6fb 100644
--- a/samples/Support7Demos/res/layout/selectable_item.xml
+++ b/samples/Support7Demos/res/layout/selectable_item.xml
@@ -2,6 +2,7 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:orientation="horizontal"
+              android:onClick="itemClicked"
               android:layout_width="match_parent"
               android:layout_height="match_parent">
 
@@ -11,9 +12,20 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"/>
 
-    <TextView
-            android:id="@+id/text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+        <TextView
+                android:id="@+id/text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+
+        <TextView
+                android:id="@+id/expandedText"
+                android:visibility="gone"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+    </LinearLayout>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/samples/Support7Demos/res/values/strings.xml b/samples/Support7Demos/res/values/strings.xml
index 876f24b..3ae6be7 100644
--- a/samples/Support7Demos/res/values/strings.xml
+++ b/samples/Support7Demos/res/values/strings.xml
@@ -102,8 +102,9 @@
     <string name="checkbox_reverse">Rev.</string>
     <string name="checkbox_layout_dir">Layout Dir</string>
     <string name="checkbox_stack_from_end">Stack From End</string>
-    <string name="enableAnimations">Animate Changes</string>
-    <string name="enablePredictiveAnimations">Predictive Animations</string>
+    <string name="enableAnimations">Animate</string>
+    <string name="enablePredictiveAnimations">Predictive</string>
+    <string name="enableChangeAnimations">Change Anims</string>
     <string name="add_item">Add</string>
     <string name="delete_item">Del</string>
     <string name="add_delete_item">A+D</string>
diff --git a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java
index f4165ac..1125685 100644
--- a/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java
+++ b/samples/Support7Demos/src/com/example/android/supportv7/widget/AnimatedRecyclerView.java
@@ -15,6 +15,7 @@
  */
 package com.example.android.supportv7.widget;
 
+import android.support.v4.util.ArrayMap;
 import android.widget.CompoundButton;
 import com.example.android.supportv7.R;
 import android.app.Activity;
@@ -47,6 +48,7 @@
 
     boolean mAnimationsEnabled = true;
     boolean mPredictiveAnimationsEnabled = true;
+    RecyclerView.ItemAnimator mCachedAnimator = null;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -55,6 +57,7 @@
 
         ViewGroup container = (ViewGroup) findViewById(R.id.container);
         mRecyclerView = new RecyclerView(this);
+        mCachedAnimator = mRecyclerView.getItemAnimator();
         mRecyclerView.setLayoutManager(new MyLayoutManager(this));
         mRecyclerView.setHasFixedSize(true);
         mRecyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
@@ -70,6 +73,11 @@
         enableAnimations.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                if (isChecked && mRecyclerView.getItemAnimator() == null) {
+                    mRecyclerView.setItemAnimator(mCachedAnimator);
+                } else if (!isChecked && mRecyclerView.getItemAnimator() != null) {
+                    mRecyclerView.setItemAnimator(null);
+                }
                 mAnimationsEnabled = isChecked;
             }
         });
@@ -82,6 +90,15 @@
                 mPredictiveAnimationsEnabled = isChecked;
             }
         });
+
+        CheckBox enableChangeAnimations =
+                (CheckBox) findViewById(R.id.enableChangeAnimations);
+        enableChangeAnimations.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                mCachedAnimator.setSupportsChangeAnimations(isChecked);
+            }
+        });
     }
 
     @Override
@@ -104,6 +121,13 @@
         mAdapter.selectItem(holder, selected);
     }
 
+    public void itemClicked(View view) {
+        ViewGroup parent = (ViewGroup) view;
+        MyViewHolder holder = (MyViewHolder) mRecyclerView.getChildViewHolder(parent);
+        mAdapter.toggleExpanded(holder);
+        mAdapter.notifyItemChanged(holder.getPosition());
+    }
+
     public void deleteItem(View view) {
         int numItems = mItems.size();
         if (numItems > 0) {
@@ -135,6 +159,7 @@
     private void addAtPosition(int position, String text) {
         mItems.add(position, text);
         mAdapter.mSelected.put(text, Boolean.FALSE);
+        mAdapter.mExpanded.put(text, Boolean.FALSE);
         mAdapter.notifyItemInserted(position);
     }
 
@@ -399,7 +424,8 @@
     class MyAdapter extends RecyclerView.Adapter {
         private int mBackground;
         List<String> mData;
-        HashMap<String, Boolean> mSelected = new HashMap<String, Boolean>();
+        ArrayMap<String, Boolean> mSelected = new ArrayMap<String, Boolean>();
+        ArrayMap<String, Boolean> mExpanded = new ArrayMap<String, Boolean>();
 
         public MyAdapter(List<String> data) {
             TypedValue val = new TypedValue();
@@ -409,6 +435,7 @@
             mData = data;
             for (String itemText : mData) {
                 mSelected.put(itemText, Boolean.FALSE);
+                mExpanded.put(itemText, Boolean.FALSE);
             }
         }
 
@@ -426,11 +453,20 @@
         public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
             String itemText = mData.get(position);
             ((MyViewHolder) holder).textView.setText(itemText);
+            ((MyViewHolder) holder).expandedText.setText("More text for the expanded version");
             boolean selected = false;
             if (mSelected.get(itemText) != null) {
                 selected = mSelected.get(itemText);
             }
             ((MyViewHolder) holder).checkBox.setChecked(selected);
+            Boolean expanded = mExpanded.get(itemText);
+            if (expanded != null && expanded) {
+                ((MyViewHolder) holder).expandedText.setVisibility(View.VISIBLE);
+                ((MyViewHolder) holder).textView.setVisibility(View.GONE);
+            } else {
+                ((MyViewHolder) holder).expandedText.setVisibility(View.GONE);
+                ((MyViewHolder) holder).textView.setVisibility(View.VISIBLE);
+            }
         }
 
         @Override
@@ -445,14 +481,21 @@
         public void selectItem(MyViewHolder holder, boolean selected) {
             mSelected.put((String) holder.textView.getText(), selected);
         }
+
+        public void toggleExpanded(MyViewHolder holder) {
+            String text = (String) holder.textView.getText();
+            mExpanded.put(text, !mExpanded.get(text));
+        }
     }
 
     static class MyViewHolder extends RecyclerView.ViewHolder {
+        public TextView expandedText;
         public TextView textView;
         public CheckBox checkBox;
 
         public MyViewHolder(View v) {
             super(v);
+            expandedText = (TextView) v.findViewById(R.id.expandedText);
             textView = (TextView) v.findViewById(R.id.text);
             checkBox = (CheckBox) v.findViewById(R.id.selected);
         }
@@ -461,4 +504,5 @@
         public String toString() {
             return super.toString() + " \"" + textView.getText() + "\"";
         }
-    }}
+    }
+}