1cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes/*
2cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * Copyright (C) 2016 The Android Open Source Project
3cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes *
4cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * you may not use this file except in compliance with the License.
6cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * You may obtain a copy of the License at
7cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes *
8cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes *
10cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * Unless required by applicable law or agreed to in writing, software
11cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * See the License for the specific language governing permissions and
14cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes * limitations under the License.
15cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes */
16cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes
17cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banespackage android.support.v4.widget;
18cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes
19cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banesimport android.os.Build;
20cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banesimport android.support.annotation.NonNull;
219b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikasimport android.view.View;
22cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banesimport android.widget.ListView;
23cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes
24cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes/**
259df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov * Helper for accessing features in {@link ListView}
26cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes */
27cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banespublic final class ListViewCompat {
28cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes
29cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes    /**
30cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes     * Scrolls the list items within the view by a specified number of pixels.
31cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes     *
32cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes     * @param listView the list to scroll
33cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes     * @param y the amount of pixels to scroll by vertically
34cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes     */
35cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes    public static void scrollListBy(@NonNull ListView listView, int y) {
36cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes        if (Build.VERSION.SDK_INT >= 19) {
379df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            // Call the framework version directly
389b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            listView.scrollListBy(y);
39cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes        } else {
409df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            // provide backport on earlier versions
419b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            final int firstPosition = listView.getFirstVisiblePosition();
429b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            if (firstPosition == ListView.INVALID_POSITION) {
439b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas                return;
449b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            }
459b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas
469b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            final View firstView = listView.getChildAt(0);
479b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            if (firstView == null) {
489b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas                return;
499b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            }
509b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas
519b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            final int newTop = firstView.getTop() - y;
529b1c00c9dcde0d65352a2e7d9aaa38710b18d1b9Aurimas Liutikas            listView.setSelectionFromTop(firstPosition, newTop);
53cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes        }
54cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes    }
55cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes
569df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov    /**
579df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     * Check if the items in the list can be scrolled in a certain direction.
589df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     *
599df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     * @param direction Negative to check scrolling up, positive to check
609df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     *            scrolling down.
619df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     * @return true if the list can be scrolled in the specified direction,
629df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     *         false otherwise.
639df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     * @see #scrollListBy(ListView, int)
649df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov     */
659df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov    public static boolean canScrollList(@NonNull ListView listView, int direction) {
669df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov        if (Build.VERSION.SDK_INT >= 19) {
679df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            // Call the framework version directly
689df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            return listView.canScrollList(direction);
699df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov        } else {
709df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            // provide backport on earlier versions
719df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            final int childCount = listView.getChildCount();
729df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            if (childCount == 0) {
739df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                return false;
749df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            }
759df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov
769df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            final int firstPosition = listView.getFirstVisiblePosition();
779df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            if (direction > 0) {
789df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                final int lastBottom = listView.getChildAt(childCount - 1).getBottom();
799df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                final int lastPosition = firstPosition + childCount;
809df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                return lastPosition < listView.getCount()
819df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                        || (lastBottom > listView.getHeight() - listView.getListPaddingBottom());
829df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            } else {
839df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                final int firstTop = listView.getChildAt(0).getTop();
849df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov                return firstPosition > 0 || firstTop < listView.getListPaddingTop();
859df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov            }
869df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov        }
879df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov    }
889df73e86fb0949ee8c5afee0bf519982f59c016dKirill Grouchnikov
89cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes    private ListViewCompat() {}
90cc7e6ffce76f2066838b626ac04536b95a0689c3Chris Banes}
91