• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.widget;
18 
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.support.annotation.VisibleForTesting;
22 import android.support.v7.widget.RecyclerView;
23 import android.view.View;
24 
25 import com.android.settingslib.core.lifecycle.Lifecycle;
26 import com.android.settingslib.core.lifecycle.LifecycleObserver;
27 import com.android.settingslib.core.lifecycle.events.OnStart;
28 import com.android.settingslib.core.lifecycle.events.OnStop;
29 
30 /**
31  * A controller that adds shadow to actionbar when content view scrolls.
32  * <p/>
33  * It also works on custom views acting as an actionbar.
34  */
35 public class ActionBarShadowController implements LifecycleObserver, OnStart, OnStop {
36 
37     @VisibleForTesting
38     static final float ELEVATION_HIGH = 8;
39     @VisibleForTesting
40     static final float ELEVATION_LOW = 0;
41 
42     @VisibleForTesting
43     ScrollChangeWatcher mScrollChangeWatcher;
44     private RecyclerView mRecyclerView;
45     private boolean isScrollWatcherAttached;
46 
attachToRecyclerView(Activity activity, Lifecycle lifecycle, RecyclerView recyclerView)47     public static ActionBarShadowController attachToRecyclerView(Activity activity,
48             Lifecycle lifecycle, RecyclerView recyclerView) {
49         return new ActionBarShadowController(activity, lifecycle, recyclerView);
50     }
51 
attachToRecyclerView(View anchorView, Lifecycle lifecycle, RecyclerView recyclerView)52     public static ActionBarShadowController attachToRecyclerView(View anchorView,
53             Lifecycle lifecycle, RecyclerView recyclerView) {
54         return new ActionBarShadowController(anchorView, lifecycle, recyclerView);
55     }
56 
ActionBarShadowController(Activity activity, Lifecycle lifecycle, RecyclerView recyclerView)57     private ActionBarShadowController(Activity activity, Lifecycle lifecycle,
58             RecyclerView recyclerView) {
59         mScrollChangeWatcher = new ScrollChangeWatcher(activity);
60         mRecyclerView = recyclerView;
61         attachScrollWatcher();
62         lifecycle.addObserver(this);
63     }
64 
ActionBarShadowController(View anchorView, Lifecycle lifecycle, RecyclerView recyclerView)65     private ActionBarShadowController(View anchorView, Lifecycle lifecycle,
66             RecyclerView recyclerView) {
67         mScrollChangeWatcher = new ScrollChangeWatcher(anchorView);
68         mRecyclerView = recyclerView;
69         attachScrollWatcher();
70         lifecycle.addObserver(this);
71     }
72 
73     @Override
onStop()74     public void onStop() {
75         detachScrollWatcher();
76     }
77 
detachScrollWatcher()78     private void detachScrollWatcher() {
79         mRecyclerView.removeOnScrollListener(mScrollChangeWatcher);
80         isScrollWatcherAttached = false;
81     }
82 
83     @Override
onStart()84     public void onStart() {
85         attachScrollWatcher();
86     }
87 
attachScrollWatcher()88     private void attachScrollWatcher() {
89         if (!isScrollWatcherAttached) {
90             isScrollWatcherAttached = true;
91             mRecyclerView.addOnScrollListener(mScrollChangeWatcher);
92             mScrollChangeWatcher.updateDropShadow(mRecyclerView);
93         }
94     }
95 
96     /**
97      * Update the drop shadow as the scrollable entity is scrolled.
98      */
99     final class ScrollChangeWatcher extends RecyclerView.OnScrollListener {
100 
101         private final Activity mActivity;
102         private final View mAnchorView;
103 
ScrollChangeWatcher(Activity activity)104         public ScrollChangeWatcher(Activity activity) {
105             mActivity = activity;
106             mAnchorView = null;
107         }
108 
ScrollChangeWatcher(View anchorView)109         public ScrollChangeWatcher(View anchorView) {
110             mAnchorView = anchorView;
111             mActivity = null;
112         }
113 
114         // RecyclerView scrolled.
115         @Override
onScrolled(RecyclerView view, int dx, int dy)116         public void onScrolled(RecyclerView view, int dx, int dy) {
117             updateDropShadow(view);
118         }
119 
updateDropShadow(View view)120         public void updateDropShadow(View view) {
121             final boolean shouldShowShadow = view.canScrollVertically(-1);
122             if (mAnchorView != null) {
123                 mAnchorView.setElevation(shouldShowShadow ? ELEVATION_HIGH : ELEVATION_LOW);
124             } else if (mActivity != null) { // activity can become null when running monkey
125                 final ActionBar actionBar = mActivity.getActionBar();
126                 if (actionBar != null) {
127                     actionBar.setElevation(shouldShowShadow ? ELEVATION_HIGH : ELEVATION_LOW);
128                 }
129             }
130         }
131     }
132 
133 }
134