ScrollbarHelper.java revision c75143d5a673eaa023683dc38e23aecf3831e63d
1/* 2 * Copyright (C) 2014 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 */ 16package android.support.v7.widget; 17 18import android.view.View; 19 20/** 21 * A helper class to do scroll offset calculations. 22 */ 23class ScrollbarHelper { 24 25 /** 26 * @param startChild View closest to start of the list. (top or left) 27 * @param endChild View closest to end of the list (bottom or right) 28 */ 29 static int computeScrollOffset(RecyclerView.State state, OrientationHelper orientation, 30 View startChild, View endChild, RecyclerView.LayoutManager lm, 31 boolean smoothScrollbarEnabled, boolean reverseLayout) { 32 if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null || 33 endChild == null) { 34 return 0; 35 } 36 final int minPosition = Math.min(lm.getPosition(startChild), lm.getPosition(endChild)); 37 final int maxPosition = Math.max(lm.getPosition(startChild), lm.getPosition(endChild)); 38 final int itemsBefore = reverseLayout 39 ? Math.max(0, state.getItemCount() - maxPosition - 1) 40 : Math.max(0, minPosition); 41 if (!smoothScrollbarEnabled) { 42 return itemsBefore; 43 } 44 final int laidOutArea = Math.abs(orientation.getDecoratedEnd(endChild) - 45 orientation.getDecoratedStart(startChild)); 46 final int itemRange = Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1; 47 final float avgSizePerRow = (float) laidOutArea / itemRange; 48 49 return Math.round(itemsBefore * avgSizePerRow + (orientation.getStartAfterPadding() 50 - orientation.getDecoratedStart(startChild))); 51 } 52 53 /** 54 * @param startChild View closest to start of the list. (top or left) 55 * @param endChild View closest to end of the list (bottom or right) 56 */ 57 static int computeScrollExtent(RecyclerView.State state, OrientationHelper orientation, 58 View startChild, View endChild, RecyclerView.LayoutManager lm, 59 boolean smoothScrollbarEnabled) { 60 if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null || 61 endChild == null) { 62 return 0; 63 } 64 if (!smoothScrollbarEnabled) { 65 return Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1; 66 } 67 final int extend = orientation.getDecoratedEnd(endChild) 68 - orientation.getDecoratedStart(startChild); 69 return Math.min(orientation.getTotalSpace(), extend); 70 } 71 72 /** 73 * @param startChild View closest to start of the list. (top or left) 74 * @param endChild View closest to end of the list (bottom or right) 75 */ 76 static int computeScrollRange(RecyclerView.State state, OrientationHelper orientation, 77 View startChild, View endChild, RecyclerView.LayoutManager lm, 78 boolean smoothScrollbarEnabled) { 79 if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null || 80 endChild == null) { 81 return 0; 82 } 83 if (!smoothScrollbarEnabled) { 84 return state.getItemCount(); 85 } 86 // smooth scrollbar enabled. try to estimate better. 87 final int laidOutArea = orientation.getDecoratedEnd(endChild) - 88 orientation.getDecoratedStart(startChild); 89 final int laidOutRange = Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) 90 + 1; 91 // estimate a size for full list. 92 return (int) ((float) laidOutArea / laidOutRange * state.getItemCount()); 93 } 94} 95