| /* |
| * Copyright 2014 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 com.example.android.swiperefreshlistfragment; |
| |
| import android.content.Context; |
| import android.os.Bundle; |
| import android.support.v4.app.ListFragment; |
| import android.support.v4.view.ViewCompat; |
| import android.support.v4.widget.SwipeRefreshLayout; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.ListView; |
| |
| /** |
| * Subclass of {@link android.support.v4.app.ListFragment} which provides automatic support for |
| * providing the 'swipe-to-refresh' UX gesture by wrapping the the content view in a |
| * {@link android.support.v4.widget.SwipeRefreshLayout}. |
| */ |
| public class SwipeRefreshListFragment extends ListFragment { |
| |
| private SwipeRefreshLayout mSwipeRefreshLayout; |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| |
| // Create the list fragment's content view by calling the super method |
| final View listFragmentView = super.onCreateView(inflater, container, savedInstanceState); |
| |
| // Now create a SwipeRefreshLayout to wrap the fragment's content view |
| mSwipeRefreshLayout = new ListFragmentSwipeRefreshLayout(container.getContext()); |
| |
| // Add the list fragment's content view to the SwipeRefreshLayout, making sure that it fills |
| // the SwipeRefreshLayout |
| mSwipeRefreshLayout.addView(listFragmentView, |
| ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); |
| |
| // Make sure that the SwipeRefreshLayout will fill the fragment |
| mSwipeRefreshLayout.setLayoutParams( |
| new ViewGroup.LayoutParams( |
| ViewGroup.LayoutParams.MATCH_PARENT, |
| ViewGroup.LayoutParams.MATCH_PARENT)); |
| |
| // Now return the SwipeRefreshLayout as this fragment's content view |
| return mSwipeRefreshLayout; |
| } |
| |
| /** |
| * Set the {@link android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener} to listen for |
| * initiated refreshes. |
| * |
| * @see android.support.v4.widget.SwipeRefreshLayout#setOnRefreshListener(android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener) |
| */ |
| public void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener) { |
| mSwipeRefreshLayout.setOnRefreshListener(listener); |
| } |
| |
| /** |
| * Returns whether the {@link android.support.v4.widget.SwipeRefreshLayout} is currently |
| * refreshing or not. |
| * |
| * @see android.support.v4.widget.SwipeRefreshLayout#isRefreshing() |
| */ |
| public boolean isRefreshing() { |
| return mSwipeRefreshLayout.isRefreshing(); |
| } |
| |
| /** |
| * Set whether the {@link android.support.v4.widget.SwipeRefreshLayout} should be displaying |
| * that it is refreshing or not. |
| * |
| * @see android.support.v4.widget.SwipeRefreshLayout#setRefreshing(boolean) |
| */ |
| public void setRefreshing(boolean refreshing) { |
| mSwipeRefreshLayout.setRefreshing(refreshing); |
| } |
| |
| /** |
| * Set the color scheme for the {@link android.support.v4.widget.SwipeRefreshLayout}. |
| * |
| * @see android.support.v4.widget.SwipeRefreshLayout#setColorScheme(int, int, int, int) |
| */ |
| public void setColorScheme(int colorRes1, int colorRes2, int colorRes3, int colorRes4) { |
| mSwipeRefreshLayout.setColorScheme(colorRes1, colorRes2, colorRes3, colorRes4); |
| } |
| |
| /** |
| * @return the fragment's {@link android.support.v4.widget.SwipeRefreshLayout} widget. |
| */ |
| public SwipeRefreshLayout getSwipeRefreshLayout() { |
| return mSwipeRefreshLayout; |
| } |
| |
| /** |
| * Sub-class of {@link android.support.v4.widget.SwipeRefreshLayout} for use in this |
| * {@link android.support.v4.app.ListFragment}. The reason that this is needed is because |
| * {@link android.support.v4.widget.SwipeRefreshLayout} only supports a single child, which it |
| * expects to be the one which triggers refreshes. In our case the layout's child is the content |
| * view returned from |
| * {@link android.support.v4.app.ListFragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)} |
| * which is a {@link android.view.ViewGroup}. |
| * |
| * <p>To enable 'swipe-to-refresh' support via the {@link android.widget.ListView} we need to |
| * override the default behavior and properly signal when a gesture is possible. This is done by |
| * overriding {@link #canChildScrollUp()}. |
| */ |
| private class ListFragmentSwipeRefreshLayout extends SwipeRefreshLayout { |
| |
| public ListFragmentSwipeRefreshLayout(Context context) { |
| super(context); |
| } |
| |
| /** |
| * As mentioned above, we need to override this method to properly signal when a |
| * 'swipe-to-refresh' is possible. |
| * |
| * @return true if the {@link android.widget.ListView} is visible and can scroll up. |
| */ |
| @Override |
| public boolean canChildScrollUp() { |
| final ListView listView = getListView(); |
| if (listView.getVisibility() == View.VISIBLE) { |
| return canListViewScrollUp(listView); |
| } else { |
| return false; |
| } |
| } |
| |
| } |
| |
| // BEGIN_INCLUDE (check_list_can_scroll) |
| /** |
| * Utility method to check whether a {@link ListView} can scroll up from it's current position. |
| * Handles platform version differences, providing backwards compatible functionality where |
| * needed. |
| */ |
| private static boolean canListViewScrollUp(ListView listView) { |
| if (android.os.Build.VERSION.SDK_INT >= 14) { |
| // For ICS and above we can call canScrollVertically() to determine this |
| return ViewCompat.canScrollVertically(listView, -1); |
| } else { |
| // Pre-ICS we need to manually check the first visible item and the child view's top |
| // value |
| return listView.getChildCount() > 0 && |
| (listView.getFirstVisiblePosition() > 0 |
| || listView.getChildAt(0).getTop() < listView.getPaddingTop()); |
| } |
| } |
| // END_INCLUDE (check_list_can_scroll) |
| |
| } |