Merge "Merge ViewUtils and ViewHelper" into pi-car-dev
diff --git a/car-apps-common/src/com/android/car/apps/common/util/ViewHelper.java b/car-apps-common/src/com/android/car/apps/common/util/ViewHelper.java
deleted file mode 100644
index fc7addd..0000000
--- a/car-apps-common/src/com/android/car/apps/common/util/ViewHelper.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2019 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.android.car.apps.common.util;
-
-import android.view.View;
-
-import androidx.annotation.Nullable;
-
-/** Static helper methods for {@link View}. */
-public class ViewHelper {
-
-    /** Sets the visibility of the (optional) view to {@link View#VISIBLE} or {@link View#GONE}. */
-    public static void setVisible(@Nullable View view, boolean visible) {
-        if (view != null) {
-            view.setVisibility(visible ? View.VISIBLE : View.GONE);
-        }
-    }
-
-    /**
-     * Sets the visibility of the (optional) view to {@link View#INVISIBLE} or {@link View#VISIBLE}.
-     */
-    public static void setInvisible(@Nullable View view, boolean invisible) {
-        if (view != null) {
-            view.setVisibility(invisible ? View.INVISIBLE : View.VISIBLE);
-        }
-    }
-}
diff --git a/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java b/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
new file mode 100644
index 0000000..259600c
--- /dev/null
+++ b/car-apps-common/src/com/android/car/apps/common/util/ViewUtils.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2019 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.android.car.apps.common.util;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.NonNull;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+/**
+ * Utility methods to operate over views.
+ */
+public class ViewUtils {
+    /**
+     * Hides a view using a fade-out animation
+     *
+     * @param view {@link View} to be hidden
+     * @param duration animation duration in milliseconds.
+     */
+    public static void hideViewAnimated(@NonNull View view, int duration) {
+        // Cancel existing animation to avoid race condition
+        // if show and hide are called at the same time
+        view.animate().cancel();
+
+        if (!view.isLaidOut()) {
+            // If the view hasn't been displayed yet, just adjust visibility without animation
+            view.setVisibility(View.GONE);
+            return;
+        }
+
+        view.animate()
+                .setDuration(duration)
+                .setListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        view.setVisibility(View.GONE);
+                    }
+                })
+                .alpha(0f);
+    }
+
+    /**
+     * Shows a view using a fade-in animation
+     *
+     * @param view {@link View} to be shown
+     * @param duration animation duration in milliseconds.
+     */
+    public static void showViewAnimated(@NonNull View view, int duration) {
+        // Cancel existing animation to avoid race condition
+        // if show and hide are called at the same time
+        view.animate().cancel();
+
+        if (!view.isLaidOut()) {
+            // If the view hasn't been displayed yet, just adjust visibility without animation
+            view.setVisibility(View.VISIBLE);
+            return;
+        }
+
+        view.animate()
+                .setDuration(duration)
+                .setListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        view.setVisibility(View.VISIBLE);
+                    }
+                })
+                .alpha(1f);
+    }
+
+    /** Sets the visibility of the (optional) view to {@link View#VISIBLE} or {@link View#GONE}. */
+    public static void setVisible(@Nullable View view, boolean visible) {
+        if (view != null) {
+            view.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    /**
+     * Sets the visibility of the (optional) view to {@link View#INVISIBLE} or {@link View#VISIBLE}.
+     */
+    public static void setInvisible(@Nullable View view, boolean invisible) {
+        if (view != null) {
+            view.setVisibility(invisible ? View.INVISIBLE : View.VISIBLE);
+        }
+    }
+}
diff --git a/car-media-common/src/com/android/car/media/common/MediaAppSelectorWidget.java b/car-media-common/src/com/android/car/media/common/MediaAppSelectorWidget.java
index f797691..9b772e7 100644
--- a/car-media-common/src/com/android/car/media/common/MediaAppSelectorWidget.java
+++ b/car-media-common/src/com/android/car/media/common/MediaAppSelectorWidget.java
@@ -28,7 +28,7 @@
 
 import androidx.fragment.app.FragmentActivity;
 
-import com.android.car.apps.common.util.ViewHelper;
+import com.android.car.apps.common.util.ViewUtils;
 import com.android.car.media.common.source.MediaSourceViewModel;
 
 /**
@@ -95,7 +95,7 @@
         if (mSwitchingEnabled) {
             setOnClickListener(view -> onAppSwitchClicked());
         } else {
-            ViewHelper.setInvisible(mAppSwitchIcon, true);
+            ViewUtils.setInvisible(mAppSwitchIcon, true);
         }
     }
 
diff --git a/car-media-common/src/com/android/car/media/common/MetadataController.java b/car-media-common/src/com/android/car/media/common/MetadataController.java
index 1933b84..239da77 100644
--- a/car-media-common/src/com/android/car/media/common/MetadataController.java
+++ b/car-media-common/src/com/android/car/media/common/MetadataController.java
@@ -42,7 +42,7 @@
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
 
-import com.android.car.apps.common.util.ViewHelper;
+import com.android.car.apps.common.util.ViewUtils;
 import com.android.car.media.common.playback.AlbumArtLiveData;
 import com.android.car.media.common.playback.PlaybackViewModel;
 
@@ -112,14 +112,14 @@
         if (albumTitle != null) {
             mModel.getAlbumTitle().observe(lifecycleOwner, albumName -> {
                 albumTitle.setText(albumName);
-                ViewHelper.setInvisible(albumTitle, TextUtils.isEmpty(albumName));
+                ViewUtils.setInvisible(albumTitle, TextUtils.isEmpty(albumName));
             });
         }
 
         if (artist != null) {
             mModel.getArtist().observe(lifecycleOwner, artistName -> {
                 artist.setText(artistName);
-                ViewHelper.setInvisible(artist, TextUtils.isEmpty(artistName));
+                ViewUtils.setInvisible(artist, TextUtils.isEmpty(artistName));
             });
         }
 
@@ -140,14 +140,14 @@
                     // The text of outerSeparator is not empty. when albumTitle is empty,
                     // the visibility of outerSeparator should be View.GONE instead of
                     // View.INVISIBLE so that currentTime can be aligned to the left .
-                    visible -> ViewHelper.setVisible(outerSeparator, visible));
+                    visible -> ViewUtils.setVisible(outerSeparator, visible));
         }
 
         mModel.hasTime().observe(lifecycleOwner,
                 visible -> {
-                    ViewHelper.setInvisible(currentTime, !visible);
-                    ViewHelper.setInvisible(innerSeparator, !visible);
-                    ViewHelper.setInvisible(maxTime, !visible);
+                    ViewUtils.setInvisible(currentTime, !visible);
+                    ViewUtils.setInvisible(innerSeparator, !visible);
+                    ViewUtils.setInvisible(maxTime, !visible);
                 });
 
         if (currentTime != null) {
diff --git a/car-media-common/src/com/android/car/media/common/PlaybackFragment.java b/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
index d682594..4d2c29f 100644
--- a/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
+++ b/car-media-common/src/com/android/car/media/common/PlaybackFragment.java
@@ -37,7 +37,7 @@
 import androidx.lifecycle.ViewModelProviders;
 
 import com.android.car.apps.common.CrossfadeImageView;
-import com.android.car.apps.common.util.ViewHelper;
+import com.android.car.apps.common.util.ViewUtils;
 import com.android.car.media.common.playback.AlbumArtLiveData;
 import com.android.car.media.common.playback.PlaybackViewModel;
 import com.android.car.media.common.source.MediaSource;
@@ -70,7 +70,7 @@
         PlaybackControlsActionBar playbackControls = view.findViewById(R.id.playback_controls);
         playbackControls.setModel(playbackViewModel, getViewLifecycleOwner());
         playbackViewModel.getPlaybackStateWrapper().observe(getViewLifecycleOwner(),
-                state -> ViewHelper.setVisible(playbackControls,
+                state -> ViewUtils.setVisible(playbackControls,
                         (state != null) && state.shouldDisplay()));
 
         TextView appName = view.findViewById(R.id.app_name);