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