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