BottomScrollView.java revision 2646e1d82ec6d133b35b775f044e156fca6d9d75
1/* 2 * Copyright (C) 2015 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 17package com.android.setupwizardlib.view; 18 19import android.content.Context; 20import android.util.AttributeSet; 21import android.view.View; 22import android.widget.ScrollView; 23 24/** 25 * An extension of ScrollView that will invoke a listener callback when the ScrollView needs 26 * scrolling, and when the ScrollView is being scrolled to the bottom. This is often used in Setup 27 * Wizard as a way to ensure that users see all the content before proceeding. 28 */ 29public class BottomScrollView extends ScrollView { 30 31 public interface BottomScrollListener { 32 void onScrolledToBottom(); 33 void onRequiresScroll(); 34 } 35 36 private BottomScrollListener mListener; 37 private int mScrollThreshold; 38 private boolean mRequiringScroll = false; 39 40 private final Runnable mCheckScrollRunnable = new Runnable() { 41 @Override 42 public void run() { 43 checkScroll(); 44 } 45 }; 46 47 public BottomScrollView(Context context) { 48 super(context); 49 } 50 51 public BottomScrollView(Context context, AttributeSet attrs) { 52 super(context, attrs); 53 } 54 55 public BottomScrollView(Context context, AttributeSet attrs, int defStyle) { 56 super(context, attrs, defStyle); 57 } 58 59 public void setBottomScrollListener(BottomScrollListener l) { 60 mListener = l; 61 } 62 63 @Override 64 protected void onLayout(boolean changed, int l, int t, int r, int b) { 65 super.onLayout(changed, l, t, r, b); 66 View child = getChildAt(0); 67 if (child != null) { 68 mScrollThreshold = Math.max(0, getChildAt(0).getHeight() - b + t 69 - getPaddingBottom()); 70 } 71 if (b - t > 0) { 72 // Post check scroll in the next run loop, so that the callback methods will be invoked 73 // after the layout pass. This way a new layout pass will be scheduled if view 74 // properties are changed in the callbacks. 75 post(mCheckScrollRunnable); 76 } 77 } 78 79 @Override 80 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 81 super.onScrollChanged(l, t, oldl, oldt); 82 if (oldt != t) { 83 checkScroll(); 84 } 85 } 86 87 private void checkScroll() { 88 if (mListener != null) { 89 if (getScrollY() >= mScrollThreshold) { 90 mListener.onScrolledToBottom(); 91 } else if (!mRequiringScroll) { 92 mRequiringScroll = true; 93 mListener.onRequiresScroll(); 94 } 95 } 96 } 97 98} 99