Adds ENABLE_FLOATING_SEARCH_BOX flag for All Apps.

This defines how the All Apps screen should be laid out without
anchoring to the search bar at the top, as follows:
 - Header view aligns to the top instead of below search bar.
 - Same for A-Z list.
 - Scroller is aligned to the header view to receive the above
   adjustments automatically.
 - A-Z list is set above search bar to not peek from below.
 - Search bar is set to align parent bottom and translates up
   with the keyboard.
 - Button to disable work apps is raised above the search bar.

Bug: 213954333
Test: Manually with flag enabled/disabled, Always show keyboard
enabled/disabled, and work profile enabled/disabled.

Change-Id: If90bb39a890029fa7056367fe62bad0677f0b86e
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 7f9f63e..6df6212 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -33,7 +33,6 @@
         android:id="@+id/all_apps_header"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_below="@id/search_container_all_apps"
         android:clipToPadding="false"
         android:paddingTop="@dimen/all_apps_header_top_padding"
         android:paddingBottom="@dimen/all_apps_header_bottom_padding"
diff --git a/res/layout/all_apps_content_layout.xml b/res/layout/all_apps_content_layout.xml
deleted file mode 100644
index 5698977..0000000
--- a/res/layout/all_apps_content_layout.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/apps_list_view_override"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_below="@id/search_container_all_apps"
-    android:clipToPadding="false"
-    android:descendantFocusability="afterDescendants"
-    android:focusable="true"
-    android:layout_marginTop="@dimen/all_apps_header_top_padding"
-    android:orientation="vertical">
-</LinearLayout>
diff --git a/res/layout/all_apps_fast_scroller.xml b/res/layout/all_apps_fast_scroller.xml
index 5537bc6..f6a6156 100644
--- a/res/layout/all_apps_fast_scroller.xml
+++ b/res/layout/all_apps_fast_scroller.xml
@@ -21,7 +21,7 @@
         android:id="@+id/fast_scroller_popup"
         style="@style/FastScrollerPopup"
         android:layout_alignParentEnd="true"
-        android:layout_below="@+id/search_container_all_apps"
+        android:layout_alignTop="@+id/all_apps_header"
         android:layout_marginEnd="@dimen/fastscroll_popup_margin" />
 
     <com.android.launcher3.views.RecyclerViewFastScroller
@@ -30,7 +30,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:layout_alignParentEnd="true"
-        android:layout_below="@+id/search_container_all_apps"
+        android:layout_alignTop="@+id/all_apps_header"
         android:layout_marginEnd="@dimen/fastscroll_end_margin"
         launcher:canThumbDetach="true" />
 
diff --git a/res/layout/all_apps_rv_layout.xml b/res/layout/all_apps_rv_layout.xml
index c353b36..26d8ecc 100644
--- a/res/layout/all_apps_rv_layout.xml
+++ b/res/layout/all_apps_rv_layout.xml
@@ -19,7 +19,6 @@
     android:id="@+id/apps_list_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:layout_below="@id/search_container_all_apps"
     android:clipToPadding="false"
     android:descendantFocusability="afterDescendants"
     android:focusable="true" />
diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml
index de4a69d..cf68f51 100644
--- a/res/layout/all_apps_tabs.xml
+++ b/res/layout/all_apps_tabs.xml
@@ -20,7 +20,6 @@
     android:id="@+id/all_apps_tabs_view_pager"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:layout_below="@id/search_container_all_apps"
     android:layout_gravity="center_horizontal|top"
     android:layout_marginTop="@dimen/all_apps_header_pill_height"
     android:clipChildren="true"
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 070b98e..fb87f88 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -21,6 +21,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.widget.RelativeLayout;
 
 import androidx.core.graphics.ColorUtils;
 import androidx.recyclerview.widget.RecyclerView;
@@ -177,6 +178,28 @@
     }
 
     @Override
+    protected View replaceRVContainer(boolean showTabs) {
+        View rvContainer = super.replaceRVContainer(showTabs);
+        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+            alignParentTop(rvContainer);
+            layoutAboveSearchContainer(rvContainer);
+        } else {
+            layoutBelowSearchContainer(rvContainer);
+        }
+        return rvContainer;
+    }
+
+    @Override
+    void setupHeader() {
+        super.setupHeader();
+        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+            alignParentTop(mHeader);
+        } else {
+            layoutBelowSearchContainer(mHeader);
+        }
+    }
+
+    @Override
     protected void updateHeaderScroll(int scrolledOffset) {
         super.updateHeaderScroll(scrolledOffset);
         if (mSearchUiManager.getEditText() == null) {
@@ -202,6 +225,36 @@
 
     @Override
     protected int getHeaderBottom() {
+        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+            return super.getHeaderBottom();
+        }
         return super.getHeaderBottom() + mSearchContainer.getBottom();
     }
+
+    private void layoutBelowSearchContainer(View v) {
+        if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+            return;
+        }
+        RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+        layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+        layoutParams.removeRule(RelativeLayout.ABOVE);
+        layoutParams.addRule(RelativeLayout.BELOW, R.id.search_container_all_apps);
+    }
+
+    private void layoutAboveSearchContainer(View v) {
+        if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+            return;
+        }
+        RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+        layoutParams.addRule(RelativeLayout.ABOVE, R.id.search_container_all_apps);
+    }
+
+    private void alignParentTop(View v) {
+        if (!(v.getLayoutParams() instanceof RelativeLayout.LayoutParams)) {
+            return;
+        }
+        RelativeLayout.LayoutParams layoutParams = (LayoutParams) v.getLayoutParams();
+        layoutParams.removeRule(RelativeLayout.BELOW);
+        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+    }
 }
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index b257407..e8dcdbd 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -368,8 +368,7 @@
     }
 
     @Override
-    public void onDropCompleted(View target, DragObject d, boolean success) {
-    }
+    public void onDropCompleted(View target, DragObject d, boolean success) {}
 
     @Override
     public void setInsets(Rect insets) {
@@ -478,7 +477,7 @@
         return mHasWorkApps;
     }
 
-    private void replaceRVContainer(boolean showTabs) {
+    protected View replaceRVContainer(boolean showTabs) {
         for (AdapterHolder adapterHolder : mAH) {
             if (adapterHolder.mRecyclerView != null) {
                 adapterHolder.mRecyclerView.setLayoutManager(null);
@@ -503,6 +502,7 @@
             mWorkManager.detachWorkModeSwitch();
             mViewPager = null;
         }
+        return newView;
     }
 
     public View getRecyclerViewContainer() {
@@ -634,7 +634,9 @@
 
     @Override
     public void drawOnScrim(Canvas canvas) {
-        if (!mHeader.isHeaderProtectionSupported()) return;
+        if (!mHeader.isHeaderProtectionSupported()) {
+            return;
+        }
         mHeaderPaint.setColor(mHeaderColor);
         mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
         if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index 9d1b04e..bcb0d14 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -26,12 +26,14 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
+import android.view.ViewGroup;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
 
@@ -138,6 +140,15 @@
             mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate(
                     R.layout.work_mode_fab, mAllApps, false);
         }
+        int workFabMarginBottom =
+                mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.work_fab_margin);
+        if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
+            workFabMarginBottom <<= 1;  // Double margin to add space above search bar.
+            workFabMarginBottom +=
+                    mWorkModeSwitch.getResources().getDimensionPixelSize(R.dimen.qsb_widget_height);
+        }
+        ((ViewGroup.MarginLayoutParams) mWorkModeSwitch.getLayoutParams()).bottomMargin =
+                workFabMarginBottom;
         if (mWorkModeSwitch.getParent() != mAllApps) {
             mAllApps.addView(mWorkModeSwitch);
         }
@@ -158,7 +169,6 @@
         mWorkModeSwitch = null;
     }
 
-
     public WorkAdapterProvider getAdapterProvider() {
         return mAdapterProvider;
     }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 27c39a9..f765de4 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -92,6 +92,10 @@
     public static final BooleanFlag ENABLE_ONE_SEARCH = new DeviceFlag("ENABLE_ONE_SEARCH", false,
             "Use homescreen search box to complete allApps searches");
 
+    public static final BooleanFlag ENABLE_FLOATING_SEARCH_BAR =
+            getDebugFlag("ENABLE_FLOATING_SEARCH_BAR", false,
+                    "Keep All Apps search bar at the bottom (but above keyboard if open)");
+
     public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
             "COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");