1*90c8c64dSAndroid Build Coastguard Worker /* 2*90c8c64dSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker * 4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker * 8*90c8c64dSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker * 10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker */ 16*90c8c64dSAndroid Build Coastguard Worker 17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.swiperefreshmultipleviews; 18*90c8c64dSAndroid Build Coastguard Worker 19*90c8c64dSAndroid Build Coastguard Worker import android.content.Context; 20*90c8c64dSAndroid Build Coastguard Worker import android.support.v4.view.ViewCompat; 21*90c8c64dSAndroid Build Coastguard Worker import android.support.v4.widget.SwipeRefreshLayout; 22*90c8c64dSAndroid Build Coastguard Worker import android.util.AttributeSet; 23*90c8c64dSAndroid Build Coastguard Worker import android.view.View; 24*90c8c64dSAndroid Build Coastguard Worker import android.widget.AbsListView; 25*90c8c64dSAndroid Build Coastguard Worker 26*90c8c64dSAndroid Build Coastguard Worker /** 27*90c8c64dSAndroid Build Coastguard Worker * A descendant of {@link android.support.v4.widget.SwipeRefreshLayout} which supports multiple 28*90c8c64dSAndroid Build Coastguard Worker * child views triggering a refresh gesture. You set the views which can trigger the gesture via 29*90c8c64dSAndroid Build Coastguard Worker * {@link #setSwipeableChildren(int...)}, providing it the child ids. 30*90c8c64dSAndroid Build Coastguard Worker */ 31*90c8c64dSAndroid Build Coastguard Worker public class MultiSwipeRefreshLayout extends SwipeRefreshLayout { 32*90c8c64dSAndroid Build Coastguard Worker 33*90c8c64dSAndroid Build Coastguard Worker private View[] mSwipeableChildren; 34*90c8c64dSAndroid Build Coastguard Worker MultiSwipeRefreshLayout(Context context)35*90c8c64dSAndroid Build Coastguard Worker public MultiSwipeRefreshLayout(Context context) { 36*90c8c64dSAndroid Build Coastguard Worker super(context); 37*90c8c64dSAndroid Build Coastguard Worker } 38*90c8c64dSAndroid Build Coastguard Worker MultiSwipeRefreshLayout(Context context, AttributeSet attrs)39*90c8c64dSAndroid Build Coastguard Worker public MultiSwipeRefreshLayout(Context context, AttributeSet attrs) { 40*90c8c64dSAndroid Build Coastguard Worker super(context, attrs); 41*90c8c64dSAndroid Build Coastguard Worker } 42*90c8c64dSAndroid Build Coastguard Worker 43*90c8c64dSAndroid Build Coastguard Worker /** 44*90c8c64dSAndroid Build Coastguard Worker * Set the children which can trigger a refresh by swiping down when they are visible. These 45*90c8c64dSAndroid Build Coastguard Worker * views need to be a descendant of this view. 46*90c8c64dSAndroid Build Coastguard Worker */ setSwipeableChildren(final int... ids)47*90c8c64dSAndroid Build Coastguard Worker public void setSwipeableChildren(final int... ids) { 48*90c8c64dSAndroid Build Coastguard Worker assert ids != null; 49*90c8c64dSAndroid Build Coastguard Worker 50*90c8c64dSAndroid Build Coastguard Worker // Iterate through the ids and find the Views 51*90c8c64dSAndroid Build Coastguard Worker mSwipeableChildren = new View[ids.length]; 52*90c8c64dSAndroid Build Coastguard Worker for (int i = 0; i < ids.length; i++) { 53*90c8c64dSAndroid Build Coastguard Worker mSwipeableChildren[i] = findViewById(ids[i]); 54*90c8c64dSAndroid Build Coastguard Worker } 55*90c8c64dSAndroid Build Coastguard Worker } 56*90c8c64dSAndroid Build Coastguard Worker 57*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(can_child_scroll_up) 58*90c8c64dSAndroid Build Coastguard Worker /** 59*90c8c64dSAndroid Build Coastguard Worker * This method controls when the swipe-to-refresh gesture is triggered. By returning false here 60*90c8c64dSAndroid Build Coastguard Worker * we are signifying that the view is in a state where a refresh gesture can start. 61*90c8c64dSAndroid Build Coastguard Worker * 62*90c8c64dSAndroid Build Coastguard Worker * <p>As {@link android.support.v4.widget.SwipeRefreshLayout} only supports one direct child by 63*90c8c64dSAndroid Build Coastguard Worker * default, we need to manually iterate through our swipeable children to see if any are in a 64*90c8c64dSAndroid Build Coastguard Worker * state to trigger the gesture. If so we return false to start the gesture. 65*90c8c64dSAndroid Build Coastguard Worker */ 66*90c8c64dSAndroid Build Coastguard Worker @Override canChildScrollUp()67*90c8c64dSAndroid Build Coastguard Worker public boolean canChildScrollUp() { 68*90c8c64dSAndroid Build Coastguard Worker if (mSwipeableChildren != null && mSwipeableChildren.length > 0) { 69*90c8c64dSAndroid Build Coastguard Worker // Iterate through the scrollable children and check if any of them can not scroll up 70*90c8c64dSAndroid Build Coastguard Worker for (View view : mSwipeableChildren) { 71*90c8c64dSAndroid Build Coastguard Worker if (view != null && view.isShown() && !canViewScrollUp(view)) { 72*90c8c64dSAndroid Build Coastguard Worker // If the view is shown, and can not scroll upwards, return false and start the 73*90c8c64dSAndroid Build Coastguard Worker // gesture. 74*90c8c64dSAndroid Build Coastguard Worker return false; 75*90c8c64dSAndroid Build Coastguard Worker } 76*90c8c64dSAndroid Build Coastguard Worker } 77*90c8c64dSAndroid Build Coastguard Worker } 78*90c8c64dSAndroid Build Coastguard Worker return true; 79*90c8c64dSAndroid Build Coastguard Worker } 80*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(can_child_scroll_up) 81*90c8c64dSAndroid Build Coastguard Worker 82*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(can_view_scroll_up) 83*90c8c64dSAndroid Build Coastguard Worker /** 84*90c8c64dSAndroid Build Coastguard Worker * Utility method to check whether a {@link View} can scroll up from it's current position. 85*90c8c64dSAndroid Build Coastguard Worker * Handles platform version differences, providing backwards compatible functionality where 86*90c8c64dSAndroid Build Coastguard Worker * needed. 87*90c8c64dSAndroid Build Coastguard Worker */ canViewScrollUp(View view)88*90c8c64dSAndroid Build Coastguard Worker private static boolean canViewScrollUp(View view) { 89*90c8c64dSAndroid Build Coastguard Worker if (android.os.Build.VERSION.SDK_INT >= 14) { 90*90c8c64dSAndroid Build Coastguard Worker // For ICS and above we can call canScrollVertically() to determine this 91*90c8c64dSAndroid Build Coastguard Worker return ViewCompat.canScrollVertically(view, -1); 92*90c8c64dSAndroid Build Coastguard Worker } else { 93*90c8c64dSAndroid Build Coastguard Worker if (view instanceof AbsListView) { 94*90c8c64dSAndroid Build Coastguard Worker // Pre-ICS we need to manually check the first visible item and the child view's top 95*90c8c64dSAndroid Build Coastguard Worker // value 96*90c8c64dSAndroid Build Coastguard Worker final AbsListView listView = (AbsListView) view; 97*90c8c64dSAndroid Build Coastguard Worker return listView.getChildCount() > 0 && 98*90c8c64dSAndroid Build Coastguard Worker (listView.getFirstVisiblePosition() > 0 99*90c8c64dSAndroid Build Coastguard Worker || listView.getChildAt(0).getTop() < listView.getPaddingTop()); 100*90c8c64dSAndroid Build Coastguard Worker } else { 101*90c8c64dSAndroid Build Coastguard Worker // For all other view types we just check the getScrollY() value 102*90c8c64dSAndroid Build Coastguard Worker return view.getScrollY() > 0; 103*90c8c64dSAndroid Build Coastguard Worker } 104*90c8c64dSAndroid Build Coastguard Worker } 105*90c8c64dSAndroid Build Coastguard Worker } 106*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(can_view_scroll_up) 107*90c8c64dSAndroid Build Coastguard Worker } 108