OSDN Git Service

Add shadow to searchbar when user scrolls vertically
authorFan Zhang <zhfan@google.com>
Wed, 19 Jul 2017 23:44:28 +0000 (16:44 -0700)
committerFan Zhang <zhfan@google.com>
Thu, 20 Jul 2017 20:32:09 +0000 (20:32 +0000)
Bug: 63528057
Test: robotests

Change-Id: Ib85676d78b43be38aab1eacd0820d0755a601f60

res/layout/search_panel.xml
res/layout/settings_main_dashboard.xml
src/com/android/settings/dashboard/DashboardSummary.java
src/com/android/settings/dashboard/conditional/CellularDataCondition.java
src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
src/com/android/settings/search/SearchFragment.java
src/com/android/settings/widget/ActionBarShadowController.java
tests/robotests/src/com/android/settings/widget/ActionBarShadowControllerTest.java

index 6d76001..48a1d4c 100644 (file)
@@ -22,6 +22,7 @@
     android:orientation="vertical">
 
     <FrameLayout
+        android:id="@+id/search_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@color/suggestion_condition_background">
index d62ae1d..95299ae 100644 (file)
@@ -23,6 +23,7 @@
     android:layout_height="match_parent"
     android:orientation="vertical">
     <FrameLayout
+        android:id="@+id/search_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@color/suggestion_condition_background">
index 4078c9f..a8163e2 100644 (file)
@@ -40,6 +40,7 @@ import com.android.settings.dashboard.suggestions.SuggestionDismissController;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionsChecks;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.ActionBarShadowController;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.SettingsDrawerActivity;
@@ -193,12 +194,14 @@ public class DashboardSummary extends InstrumentedFragment
         mDashboard.setLayoutManager(mLayoutManager);
         mDashboard.setHasFixedSize(true);
         mDashboard.setListener(this);
-        Log.d(TAG, "adapter created");
         mAdapter = new DashboardAdapter(getContext(), bundle, mConditionManager.getConditions(),
             mSuggestionParser, this /* SuggestionDismissController.Callback */);
         mDashboard.setAdapter(mAdapter);
         mDashboard.setItemAnimator(new DashboardItemAnimator());
         mSummaryLoader.setSummaryConsumer(mAdapter);
+        ActionBarShadowController.attachToRecyclerView(
+                getActivity().findViewById(R.id.search_bar_container), getLifecycle(), mDashboard);
+
         if (DEBUG_TIMING) {
             Log.d(TAG, "onViewCreated took "
                     + (System.currentTimeMillis() - startTime) + " ms");
index 6842422..64d263f 100644 (file)
@@ -44,7 +44,7 @@ public class CellularDataCondition extends Condition {
             setActive(false);
             return;
         }
-        setActive(!telephony.getDataEnabled());
+        setActive(!telephony.isDataEnabled());
     }
 
     @Override
index b4e5ded..e4f58d7 100644 (file)
@@ -28,7 +28,6 @@ import android.support.annotation.VisibleForTesting;
 import android.text.format.DateUtils;
 import android.util.Log;
 
-import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.Settings.AmbientDisplayPickupSuggestionActivity;
 import com.android.settings.Settings.AmbientDisplaySuggestionActivity;
@@ -64,7 +63,6 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
 
     private final SuggestionRanker mSuggestionRanker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
-    private final AmbientDisplayConfiguration mAmbientDisplayConfig;
 
     @Override
     public boolean isSuggestionEnabled(Context context) {
@@ -116,7 +114,6 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
                 new SuggestionFeaturizer(new EventStore(appContext)));
         mMetricsFeatureProvider = FeatureFactory.getFactory(appContext)
                 .getMetricsFeatureProvider();
-        mAmbientDisplayConfig = new AmbientDisplayConfiguration(appContext);
     }
 
     @Override
index 9600241..38605ff 100644 (file)
@@ -49,6 +49,7 @@ import com.android.settings.Utils;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.instrumentation.MetricsFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.ActionBarShadowController;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -215,6 +216,8 @@ public class SearchFragment extends InstrumentedFragment implements SearchView.O
             params.setMarginStart(0);
             editFrame.setLayoutParams(params);
         }
+        ActionBarShadowController.attachToRecyclerView(
+                view.findViewById(R.id.search_bar_container), getLifecycle(), mResultsRecyclerView);
         return view;
     }
 
index 75bdf0e..0c6b02f 100644 (file)
@@ -18,6 +18,7 @@ package com.android.settings.widget;
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.widget.RecyclerView;
 import android.view.View;
 
@@ -26,9 +27,20 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
 
+/**
+ * A controller that adds shadow to actionbar when content view scrolls.
+ * <p/>
+ * It also works on custom views acting as an actionbar.
+ */
 public class ActionBarShadowController implements LifecycleObserver, OnStart, OnStop {
 
-    private ScrollChangeWatcher mScrollChangeWatcher;
+    @VisibleForTesting
+    static final float ELEVATION_HIGH = 8;
+    @VisibleForTesting
+    static final float ELEVATION_LOW = 0;
+
+    @VisibleForTesting
+    ScrollChangeWatcher mScrollChangeWatcher;
     private RecyclerView mRecyclerView;
     private boolean isScrollWatcherAttached;
 
@@ -37,6 +49,11 @@ public class ActionBarShadowController implements LifecycleObserver, OnStart, On
         return new ActionBarShadowController(activity, lifecycle, recyclerView);
     }
 
+    public static ActionBarShadowController attachToRecyclerView(View anchorView,
+            Lifecycle lifecycle, RecyclerView recyclerView) {
+        return new ActionBarShadowController(anchorView, lifecycle, recyclerView);
+    }
+
     private ActionBarShadowController(Activity activity, Lifecycle lifecycle,
             RecyclerView recyclerView) {
         mScrollChangeWatcher = new ScrollChangeWatcher(activity);
@@ -45,6 +62,14 @@ public class ActionBarShadowController implements LifecycleObserver, OnStart, On
         lifecycle.addObserver(this);
     }
 
+    private ActionBarShadowController(View anchorView, Lifecycle lifecycle,
+            RecyclerView recyclerView) {
+        mScrollChangeWatcher = new ScrollChangeWatcher(anchorView);
+        mRecyclerView = recyclerView;
+        attachScrollWatcher();
+        lifecycle.addObserver(this);
+    }
+
     @Override
     public void onStop() {
         detachScrollWatcher();
@@ -71,12 +96,19 @@ public class ActionBarShadowController implements LifecycleObserver, OnStart, On
     /**
      * Update the drop shadow as the scrollable entity is scrolled.
      */
-    private final class ScrollChangeWatcher extends RecyclerView.OnScrollListener {
+    final class ScrollChangeWatcher extends RecyclerView.OnScrollListener {
 
-        private Activity mActivity;
+        private final Activity mActivity;
+        private final View mAnchorView;
 
         public ScrollChangeWatcher(Activity activity) {
             mActivity = activity;
+            mAnchorView = null;
+        }
+
+        public ScrollChangeWatcher(View anchorView) {
+            mAnchorView = anchorView;
+            mActivity = null;
         }
 
         // RecyclerView scrolled.
@@ -87,9 +119,13 @@ public class ActionBarShadowController implements LifecycleObserver, OnStart, On
 
         public void updateDropShadow(View view) {
             final boolean shouldShowShadow = view.canScrollVertically(-1);
-            final ActionBar actionBar = mActivity.getActionBar();
-            if (actionBar != null) {
-                actionBar.setElevation(shouldShowShadow ? 8 : 0);
+            if (mAnchorView != null) {
+                mAnchorView.setElevation(shouldShowShadow ? ELEVATION_HIGH : ELEVATION_LOW);
+            } else {
+                final ActionBar actionBar = mActivity.getActionBar();
+                if (actionBar != null) {
+                    actionBar.setElevation(shouldShowShadow ? ELEVATION_HIGH : ELEVATION_LOW);
+                }
             }
         }
     }
index 2fbf03e..be50d77 100644 (file)
 package com.android.settings.widget;
 
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.ActionBar;
 import android.app.Activity;
 import android.support.v7.widget.RecyclerView;
+import android.view.View;
 
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 
@@ -31,17 +38,12 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 import java.util.List;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ActionBarShadowControllerTest {
@@ -53,11 +55,13 @@ public class ActionBarShadowControllerTest {
     @Mock
     private ActionBar mActionBar;
     private Lifecycle mLifecycle;
+    private View mView;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         when(mActivity.getActionBar()).thenReturn(mActionBar);
+        mView = new View(RuntimeEnvironment.application);
         mLifecycle = new Lifecycle();
     }
 
@@ -67,9 +71,23 @@ public class ActionBarShadowControllerTest {
 
         ActionBarShadowController.attachToRecyclerView(mActivity, mLifecycle, mRecyclerView);
 
-        verify(mActionBar).setElevation(0);
+        verify(mActionBar).setElevation(ActionBarShadowController.ELEVATION_LOW);
     }
 
+    @Test
+    public void attachToRecyclerView_customViewAsActionBar_shouldUpdateElevationOnScroll() {
+        // Setup
+        mView.setElevation(50);
+        when(mRecyclerView.canScrollVertically(-1)).thenReturn(false);
+        final ActionBarShadowController controller =
+                ActionBarShadowController.attachToRecyclerView(mView, mLifecycle, mRecyclerView);
+        assertThat(mView.getElevation()).isEqualTo(ActionBarShadowController.ELEVATION_LOW);
+
+        // Scroll
+        when(mRecyclerView.canScrollVertically(-1)).thenReturn(true);
+        controller.mScrollChangeWatcher.onScrolled(mRecyclerView, 10 /* dx */, 10 /* dy */);
+        assertThat(mView.getElevation()).isEqualTo(ActionBarShadowController.ELEVATION_HIGH);
+    }
 
     @Test
     public void attachToRecyclerView_lifecycleChange_shouldAttachDetach() {