• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 
17 package com.example.android.swiperefreshmultipleviews;
18 
19 import com.example.android.common.dummydata.Cheeses;
20 import com.example.android.common.logger.Log;
21 
22 import android.os.AsyncTask;
23 import android.os.Bundle;
24 import android.support.v4.app.Fragment;
25 import android.support.v4.widget.SwipeRefreshLayout;
26 import android.view.LayoutInflater;
27 import android.view.Menu;
28 import android.view.MenuInflater;
29 import android.view.MenuItem;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.ArrayAdapter;
33 import android.widget.GridView;
34 
35 import java.util.List;
36 
37 /**
38  * A sample which shows how to use {@link android.support.v4.widget.SwipeRefreshLayout} to add
39  * the 'swipe-to-refresh' gesture to a layout with multiple children. In this sample,
40  * SwipeRefreshLayout contains a scrollable {@link android.widget.GridView}, along with a
41  * {@link android.widget.TextView} empty view.
42  *
43  * <p>To provide an accessible way to trigger the refresh, this app also provides a refresh
44  * action item.
45  *
46  * <p>In this sample app, the refresh updates the GridView with a random set of new items.
47  */
48 public class SwipeRefreshMultipleViewsFragment extends Fragment {
49 
50     private static final String LOG_TAG = SwipeRefreshMultipleViewsFragment.class.getSimpleName();
51 
52     private static final int LIST_ITEM_COUNT = 40;
53 
54     /**
55      * The {@link MultiSwipeRefreshLayout} that detects swipe gestures and triggers callbacks in
56      * the app.
57      */
58     private MultiSwipeRefreshLayout mSwipeRefreshLayout;
59 
60     /**
61      * The {@link android.widget.GridView} that displays the content that should be refreshed.
62      */
63     private GridView mGridView;
64 
65     /**
66      * The {@link android.widget.ListAdapter} used to populate the {@link android.widget.GridView}
67      * defined in the previous statement.
68      */
69     private ArrayAdapter<String> mListAdapter;
70 
71     /**
72      * The {@link View} which is displayed when the GridView is empty.
73      */
74     private View mEmptyView;
75 
76     @Override
onCreate(Bundle savedInstanceState)77     public void onCreate(Bundle savedInstanceState) {
78         super.onCreate(savedInstanceState);
79 
80         // Notify the system to allow an options menu for this fragment.
81         setHasOptionsMenu(true);
82     }
83 
84     // BEGIN_INCLUDE (inflate_view)
85     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)86     public View onCreateView(LayoutInflater inflater, ViewGroup container,
87             Bundle savedInstanceState) {
88         View view = inflater.inflate(R.layout.fragment_sample, container, false);
89 
90         // Retrieve the SwipeRefreshLayout and GridView instances
91         mSwipeRefreshLayout = (MultiSwipeRefreshLayout) view.findViewById(R.id.swiperefresh);
92 
93         // BEGIN_INCLUDE (change_colors)
94         // Set the color scheme of the SwipeRefreshLayout by providing 4 color resource ids
95         mSwipeRefreshLayout.setColorScheme(
96                 R.color.swipe_color_1, R.color.swipe_color_2,
97                 R.color.swipe_color_3, R.color.swipe_color_4);
98         // END_INCLUDE (change_colors)
99 
100         // Retrieve the GridView
101         mGridView = (GridView) view.findViewById(android.R.id.list);
102 
103         // Retrieve the empty view
104         mEmptyView = view.findViewById(android.R.id.empty);
105 
106         return view;
107     }
108     // END_INCLUDE (inflate_view)
109 
110     // BEGIN_INCLUDE (setup_views)
111     @Override
onViewCreated(View view, Bundle savedInstanceState)112     public void onViewCreated(View view, Bundle savedInstanceState) {
113         super.onViewCreated(view, savedInstanceState);
114 
115         /**
116          * Create an ArrayAdapter to contain the data for the GridView. Each item in the GridView
117          * uses the system-defined simple_list_item_1 layout that contains one TextView. Initially
118          */
119         mListAdapter = new ArrayAdapter<String>(
120                 getActivity(),
121                 android.R.layout.simple_list_item_1,
122                 android.R.id.text1);
123 
124         // Set the adapter between the GridView and its backing data.
125         mGridView.setAdapter(mListAdapter);
126 
127         // Set the empty view so that it is displayed as needed
128         mGridView.setEmptyView(mEmptyView);
129 
130         // BEGIN_INCLUDE (setup_swipeable_children)
131         // Tell the MultiSwipeRefreshLayout which views are swipeable. In this case, the GridView
132         // and empty view.
133         mSwipeRefreshLayout.setSwipeableChildren(android.R.id.list, android.R.id.empty);
134         // END_INCLUDE (setup_swipeable_children)
135 
136         // BEGIN_INCLUDE (setup_refreshlistener)
137         /**
138          * Implement {@link SwipeRefreshLayout.OnRefreshListener}. When users do the "swipe to
139          * refresh" gesture, SwipeRefreshLayout invokes
140          * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}. In
141          * {@link SwipeRefreshLayout.OnRefreshListener#onRefresh onRefresh()}, call a method that
142          * refreshes the content. Call the same method in response to the Refresh action from the
143          * action bar.
144          */
145         mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
146             @Override
147             public void onRefresh() {
148                 Log.i(LOG_TAG, "onRefresh called from SwipeRefreshLayout");
149 
150                 initiateRefresh();
151             }
152         });
153         // END_INCLUDE (setup_refreshlistener)
154     }
155     // END_INCLUDE (setup_views)
156 
157     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)158     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
159         inflater.inflate(R.menu.main_menu, menu);
160     }
161 
162     // BEGIN_INCLUDE (setup_refresh_menu_listener)
163     /**
164      * Respond to the user's selection of the Refresh action item. Start the SwipeRefreshLayout
165      * progress bar, then initiate the background task that refreshes the content.
166      */
167     @Override
onOptionsItemSelected(MenuItem item)168     public boolean onOptionsItemSelected(MenuItem item) {
169         switch (item.getItemId()) {
170             case R.id.menu_clear:
171                 Log.i(LOG_TAG, "Clear menu item selected");
172                 mListAdapter.clear();
173                 return true;
174 
175             case R.id.menu_refresh:
176                 Log.i(LOG_TAG, "Refresh menu item selected");
177 
178                 // We make sure that the SwipeRefreshLayout is displaying it's refreshing indicator
179                 if (!mSwipeRefreshLayout.isRefreshing()) {
180                     mSwipeRefreshLayout.setRefreshing(true);
181                 }
182 
183                 // Start our refresh background task
184                 initiateRefresh();
185 
186                 return true;
187         }
188 
189         return super.onOptionsItemSelected(item);
190     }
191     // END_INCLUDE (setup_refresh_menu_listener)
192 
193     // BEGIN_INCLUDE (initiate_refresh)
194     /**
195      * By abstracting the refresh process to a single method, the app allows both the
196      * SwipeGestureLayout onRefresh() method and the Refresh action item to refresh the content.
197      */
initiateRefresh()198     private void initiateRefresh() {
199         Log.i(LOG_TAG, "initiateRefresh");
200 
201         /**
202          * Execute the background task, which uses {@link android.os.AsyncTask} to load the data.
203          */
204         new DummyBackgroundTask().execute();
205     }
206     // END_INCLUDE (initiate_refresh)
207 
208     // BEGIN_INCLUDE (refresh_complete)
209     /**
210      * When the AsyncTask finishes, it calls onRefreshComplete(), which updates the data in the
211      * ListAdapter and turns off the progress bar.
212      */
onRefreshComplete(List<String> result)213     private void onRefreshComplete(List<String> result) {
214         Log.i(LOG_TAG, "onRefreshComplete");
215 
216         // Remove all items from the ListAdapter, and then replace them with the new items
217         mListAdapter.clear();
218         for (String cheese : result) {
219             mListAdapter.add(cheese);
220         }
221 
222         // Stop the refreshing indicator
223         mSwipeRefreshLayout.setRefreshing(false);
224     }
225     // END_INCLUDE (refresh_complete)
226 
227     /**
228      * Dummy {@link AsyncTask} which simulates a long running task to fetch new cheeses.
229      */
230     private class DummyBackgroundTask extends AsyncTask<Void, Void, List<String>> {
231 
232         static final int TASK_DURATION = 3 * 1000; // 3 seconds
233 
234         @Override
doInBackground(Void... params)235         protected List<String> doInBackground(Void... params) {
236             // Sleep for a small amount of time to simulate a background-task
237             try {
238                 Thread.sleep(TASK_DURATION);
239             } catch (InterruptedException e) {
240                 e.printStackTrace();
241             }
242 
243             // Return a new random list of cheeses
244             return Cheeses.randomList(LIST_ITEM_COUNT);
245         }
246 
247         @Override
onPostExecute(List<String> result)248         protected void onPostExecute(List<String> result) {
249             super.onPostExecute(result);
250 
251             // Tell the Fragment that the refresh has completed
252             onRefreshComplete(result);
253         }
254 
255     }
256 }