• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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.contacts;
18 
19 import android.view.View;
20 import android.widget.AbsListView;
21 import android.widget.ListView;
22 
23 /**
24  * Handles scrolling back of a list tied to a header.
25  * <p>
26  * This is used to implement a header that scrolls up with the content of a list to be partially
27  * obscured.
28  */
29 public class BackScrollManager {
30     /** Defines the header to be scrolled. */
31     public interface ScrollableHeader {
32         /** Sets the offset by which to scroll. */
setOffset(int offset)33         public void setOffset(int offset);
34         /** Gets the maximum offset that should be applied to the header. */
getMaximumScrollableHeaderOffset()35         public int getMaximumScrollableHeaderOffset();
36     }
37 
38     private final ScrollableHeader mHeader;
39     private final ListView mListView;
40 
41     private final AbsListView.OnScrollListener mScrollListener =
42             new AbsListView.OnScrollListener() {
43                 @Override
44                 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
45                         int totalItemCount) {
46                     if (firstVisibleItem != 0) {
47                         // The first item is not shown, the header should be pinned at the top.
48                         mHeader.setOffset(mHeader.getMaximumScrollableHeaderOffset());
49                         return;
50                     }
51 
52                     View firstVisibleItemView = view.getChildAt(firstVisibleItem);
53                     if (firstVisibleItemView == null) {
54                         return;
55                     }
56                     // We scroll the header up, but at most pin it to the top of the screen.
57                     int offset = Math.min(
58                             (int) -view.getChildAt(firstVisibleItem).getY(),
59                             mHeader.getMaximumScrollableHeaderOffset());
60                     mHeader.setOffset(offset);
61                 }
62 
63                 @Override
64                 public void onScrollStateChanged(AbsListView view, int scrollState) {
65                     // Nothing to do here.
66                 }
67             };
68 
69     /**
70      * Creates a new instance of a {@link BackScrollManager} that connected the header and the list
71      * view.
72      */
bind(ScrollableHeader header, ListView listView)73     public static void bind(ScrollableHeader header, ListView listView) {
74         BackScrollManager backScrollManager = new BackScrollManager(header, listView);
75         backScrollManager.bind();
76     }
77 
BackScrollManager(ScrollableHeader header, ListView listView)78     private BackScrollManager(ScrollableHeader header, ListView listView) {
79         mHeader = header;
80         mListView = listView;
81     }
82 
bind()83     private void bind() {
84         mListView.setOnScrollListener(mScrollListener);
85         // We disable the scroll bar because it would otherwise be incorrect because of the hidden
86         // header.
87         mListView.setVerticalScrollBarEnabled(false);
88     }
89 }
90