Make Snackbar work with translucent navigation bars

Also fixed an issue in ViewCompat.setOnApplyWindowInsetsListener
which makes it NPE when given a null listener.

BUG: 29075380
Change-Id: I9c91437a33eee99326f2bbfe9719667f598e005a
diff --git a/compat/java/android/support/v4/view/ViewCompat.java b/compat/java/android/support/v4/view/ViewCompat.java
index 79b1a43..124751e 100644
--- a/compat/java/android/support/v4/view/ViewCompat.java
+++ b/compat/java/android/support/v4/view/ViewCompat.java
@@ -1622,6 +1622,11 @@
         @Override
         public void setOnApplyWindowInsetsListener(View view,
                 final OnApplyWindowInsetsListener listener) {
+            if (listener == null) {
+                ViewCompatLollipop.setOnApplyWindowInsetsListener(view, null);
+                return;
+            }
+
             ViewCompatLollipop.OnApplyWindowInsetsListenerBridge bridge =
                     new ViewCompatLollipop.OnApplyWindowInsetsListenerBridge() {
                         @Override
diff --git a/design/res/layout/design_layout_snackbar.xml b/design/res/layout/design_layout_snackbar.xml
index 604aafc..8f3f0d6 100644
--- a/design/res/layout/design_layout_snackbar.xml
+++ b/design/res/layout/design_layout_snackbar.xml
@@ -20,4 +20,5 @@
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
+      android:theme="@style/ThemeOverlay.AppCompat.Dark"
       style="@style/Widget.Design.Snackbar" />
\ No newline at end of file
diff --git a/design/res/values/styles.xml b/design/res/values/styles.xml
index c5c6051..1010d11 100644
--- a/design/res/values/styles.xml
+++ b/design/res/values/styles.xml
@@ -92,7 +92,6 @@
     </style>
 
     <style name="Widget.Design.Snackbar" parent="android:Widget">
-        <item name="android:theme">@style/ThemeOverlay.AppCompat.Dark</item>
         <item name="android:minWidth">@dimen/design_snackbar_min_width</item>
         <item name="android:maxWidth">@dimen/design_snackbar_max_width</item>
         <item name="android:background">@drawable/design_snackbar_background</item>
diff --git a/design/src/android/support/design/widget/Snackbar.java b/design/src/android/support/design/widget/Snackbar.java
index 657e9ce..2c1de6c 100644
--- a/design/src/android/support/design/widget/Snackbar.java
+++ b/design/src/android/support/design/widget/Snackbar.java
@@ -29,8 +29,10 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.StringRes;
 import android.support.design.R;
+import android.support.v4.view.OnApplyWindowInsetsListener;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
+import android.support.v4.view.WindowInsetsCompat;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -689,6 +691,20 @@
                     ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE);
             ViewCompat.setImportantForAccessibility(this,
                     ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
+
+            // Make sure that we fit system windows and have a listener to apply any insets
+            ViewCompat.setFitsSystemWindows(this, true);
+            ViewCompat.setOnApplyWindowInsetsListener(this,
+                    new android.support.v4.view.OnApplyWindowInsetsListener() {
+                @Override
+                public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
+                    // Copy over the bottom inset as padding so that we're displayed above the
+                    // navigation bar
+                    v.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
+                            v.getPaddingRight(), insets.getSystemWindowInsetBottom());
+                    return insets;
+                }
+            });
         }
 
         @Override
@@ -778,6 +794,8 @@
             if (mOnAttachStateChangeListener != null) {
                 mOnAttachStateChangeListener.onViewAttachedToWindow(this);
             }
+
+            ViewCompat.requestApplyInsets(this);
         }
 
         @Override
diff --git a/design/tests/AndroidManifest.xml b/design/tests/AndroidManifest.xml
index f500372..e4951dd 100755
--- a/design/tests/AndroidManifest.xml
+++ b/design/tests/AndroidManifest.xml
@@ -38,6 +38,10 @@
                 android:name="android.support.design.widget.SnackbarActivity"/>
 
         <activity
+            android:theme="@style/Theme.TranslucentNavBar"
+            android:name="android.support.design.widget.SnackbarActivityWithTranslucentNavBar"/>
+
+        <activity
                 android:theme="@style/Theme.TranslucentStatus"
                 android:name="android.support.design.widget.DynamicCoordinatorLayoutActivity"/>
 
@@ -47,10 +51,6 @@
 
         <activity
                 android:theme="@style/Theme.AppCompat.NoActionBar"
-                android:name="android.support.design.widget.SnackbarBucketTestsActivity"/>
-
-        <activity
-                android:theme="@style/Theme.AppCompat.NoActionBar"
                 android:name="android.support.design.widget.BottomSheetBehaviorActivity"/>
 
         <activity
diff --git a/design/tests/res/layout/test_design_snackbar.xml b/design/tests/res/layout/test_design_snackbar.xml
index b7bab1e..cb3643a 100644
--- a/design/tests/res/layout/test_design_snackbar.xml
+++ b/design/tests/res/layout/test_design_snackbar.xml
@@ -18,4 +18,5 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:id="@+id/col"/>
\ No newline at end of file
+        android:id="@+id/col"
+        android:fitsSystemWindows="true"/>
\ No newline at end of file
diff --git a/design/tests/res/values/styles.xml b/design/tests/res/values/styles.xml
index 44b58eb..c964cbd 100644
--- a/design/tests/res/values/styles.xml
+++ b/design/tests/res/values/styles.xml
@@ -27,4 +27,8 @@
         <item name="android:statusBarColor">@android:color/transparent</item>
     </style>
 
+    <style name="Theme.TranslucentNavBar" parent="Theme.AppCompat.Light.NoActionBar">
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+    </style>
+
 </resources>
\ No newline at end of file
diff --git a/design/tests/src/android/support/design/widget/SnackbarActivityWithTranslucentNavBar.java b/design/tests/src/android/support/design/widget/SnackbarActivityWithTranslucentNavBar.java
new file mode 100644
index 0000000..7ccf69c
--- /dev/null
+++ b/design/tests/src/android/support/design/widget/SnackbarActivityWithTranslucentNavBar.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 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 android.support.design.widget;
+
+import android.support.design.test.R;
+
+public class SnackbarActivityWithTranslucentNavBar extends BaseTestActivity {
+    @Override
+    protected int getContentViewLayoutResId() {
+        return R.layout.test_design_snackbar;
+    }
+}
\ No newline at end of file
diff --git a/design/tests/src/android/support/design/widget/SnackbarTestWithTranslucentNavBar.java b/design/tests/src/android/support/design/widget/SnackbarTestWithTranslucentNavBar.java
new file mode 100644
index 0000000..83eee70
--- /dev/null
+++ b/design/tests/src/android/support/design/widget/SnackbarTestWithTranslucentNavBar.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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 android.support.design.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.support.design.test.R;
+import android.support.design.testutils.SnackbarUtils;
+import android.support.test.filters.SdkSuppress;
+import android.support.v4.view.WindowInsetsCompat;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@SdkSuppress(minSdkVersion = 21)
+public class SnackbarTestWithTranslucentNavBar
+        extends BaseInstrumentationTestCase<SnackbarActivityWithTranslucentNavBar> {
+
+    private static final String MESSAGE_TEXT = "Test Message";
+
+    private CoordinatorLayout mCoordinatorLayout;
+
+    public SnackbarTestWithTranslucentNavBar() {
+        super(SnackbarActivityWithTranslucentNavBar.class);
+    }
+
+    @Before
+    public void setup() {
+        mCoordinatorLayout =
+                (CoordinatorLayout) mActivityTestRule.getActivity().findViewById(R.id.col);
+    }
+
+    @Test
+    @MediumTest
+    public void testDrawsAboveNavigationBar() {
+        // Show a simple Snackbar and wait for it to be shown
+        final Snackbar snackbar = Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT,
+                Snackbar.LENGTH_SHORT);
+        SnackbarUtils.showSnackbarAndWaitUntilFullyShown(snackbar);
+
+        final WindowInsetsCompat colLastInsets = mCoordinatorLayout.getLastWindowInsets();
+        assertNotNull(colLastInsets);
+
+        // Check that the Snackbar view has padding set to display above the nav bar
+        final View view = snackbar.getView();
+        assertNotNull(view);
+        assertEquals(colLastInsets.getSystemWindowInsetBottom(), view.getPaddingBottom());
+    }
+}
diff --git a/samples/SupportDesignDemos/AndroidManifest.xml b/samples/SupportDesignDemos/AndroidManifest.xml
index ec97037..58113bd 100644
--- a/samples/SupportDesignDemos/AndroidManifest.xml
+++ b/samples/SupportDesignDemos/AndroidManifest.xml
@@ -111,7 +111,7 @@
 
         <activity android:name=".widget.SnackbarUsage"
                   android:label="@string/design_snackbar_basic"
-                  android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
+                  android:theme="@style/Theme.Design.Snackbar">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.example.android.support.design.SAMPLE_CODE" />
diff --git a/samples/SupportDesignDemos/res/layout/design_snackbar.xml b/samples/SupportDesignDemos/res/layout/design_snackbar.xml
index ea5508a..06273eb 100644
--- a/samples/SupportDesignDemos/res/layout/design_snackbar.xml
+++ b/samples/SupportDesignDemos/res/layout/design_snackbar.xml
@@ -19,7 +19,8 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/content_view"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="match_parent"
+        android:fitsSystemWindows="true">
 
     <LinearLayout android:layout_width="match_parent"
                   android:layout_height="wrap_content"
diff --git a/samples/SupportDesignDemos/res/values-v21/styles.xml b/samples/SupportDesignDemos/res/values-v21/styles.xml
index 298dcf3..866837f 100644
--- a/samples/SupportDesignDemos/res/values-v21/styles.xml
+++ b/samples/SupportDesignDemos/res/values-v21/styles.xml
@@ -19,9 +19,14 @@
 
     <style name="Theme.Design.TransparentStatus">
         <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:windowTranslucentNavigation">true</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
     </style>
 
+    <style name="Theme.Design.Snackbar">
+        <item name="android:windowTranslucentNavigation">true</item>
+    </style>
+
     <style name="Theme.Navigation" parent="Theme.Navigation.Base">
         <item name="android:statusBarColor">@android:color/transparent</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
diff --git a/samples/SupportDesignDemos/res/values/styles.xml b/samples/SupportDesignDemos/res/values/styles.xml
index 432bc3e..38afe49 100644
--- a/samples/SupportDesignDemos/res/values/styles.xml
+++ b/samples/SupportDesignDemos/res/values/styles.xml
@@ -23,8 +23,9 @@
         <item name="colorAccent">#FFAB40</item>
     </style>
 
-    <style name="Theme.Design.TransparentStatus">
-    </style>
+    <style name="Theme.Design.TransparentStatus" />
+
+    <style name="Theme.Design.Snackbar" />
 
     <style name="Theme.FAB" parent="Theme.AppCompat.Light.NoActionBar">
         <item name="colorPrimary">#ff00bcd4</item>