/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. Jukefox is * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ch.ethz.dcg.pancho3.tablet.widget; import android.content.Context; import android.util.AttributeSet; import android.widget.ListView; /** * A ListView that can be asked to scroll (smoothly or otherwise) to a specific * position. This class takes advantage of similar functionality that exists in * {@link ListView} and enhances it. */ public class AutoScrollListView extends ListView { /** * Position the element at about 1/3 of the list height */ private static final float PREFERRED_SELECTION_OFFSET_FROM_TOP = 0.33f; private int mRequestedScrollPosition = -1; private boolean mSmoothScrollRequested; public AutoScrollListView(Context context) { super(context); } public AutoScrollListView(Context context, AttributeSet attrs) { super(context, attrs); } public AutoScrollListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * Brings the specified position to view by optionally performing a * jump-scroll maneuver: first it jumps to some position near the one * requested and then does a smooth scroll to the requested position. This * creates an impression of full smooth scrolling without actually * traversing the entire list. If smooth scrolling is not requested, * instantly positions the requested item at a preferred offset. */ public void requestPositionToScreen(int position, boolean smoothScroll) { mRequestedScrollPosition = position; mSmoothScrollRequested = smoothScroll; requestLayout(); } @Override protected void layoutChildren() { super.layoutChildren(); if (mRequestedScrollPosition == -1) { return; } final int position = mRequestedScrollPosition; mRequestedScrollPosition = -1; int firstPosition = getFirstVisiblePosition() + 1; int lastPosition = getLastVisiblePosition(); if (position >= firstPosition && position <= lastPosition) { return; // Already on screen } final int offset = (int) (getHeight() * PREFERRED_SELECTION_OFFSET_FROM_TOP); if (!mSmoothScrollRequested) { setSelectionFromTop(position, offset); // Since we have changed the scrolling position, we need to redo child layout // Calling "requestLayout" in the middle of a layout pass has no effect, // so we call layoutChildren explicitly super.layoutChildren(); } else { // We will first position the list a couple of screens before or after // the new selection and then scroll smoothly to it. int twoScreens = (lastPosition - firstPosition) * 2; int preliminaryPosition; if (position < firstPosition) { preliminaryPosition = position + twoScreens; if (preliminaryPosition >= getCount()) { preliminaryPosition = getCount() - 1; } if (preliminaryPosition < firstPosition) { setSelection(preliminaryPosition); super.layoutChildren(); } } else { preliminaryPosition = position - twoScreens; if (preliminaryPosition < 0) { preliminaryPosition = 0; } if (preliminaryPosition > lastPosition) { setSelection(preliminaryPosition); super.layoutChildren(); } } smoothScrollToPositionFromTop(position, offset); } } }