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 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 79 @Override 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 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); 93 94 // Retrieve the ListView 95 mListView = (ListView) view.findViewById(android.R.id.list); 96 97 return view; 98 } 100 102 @Override 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 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 }); 137 } 139 140 @Override 141 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 142 inflater.inflate(R.menu.main_menu, menu); 143 } 144 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 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 } 170 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 */ 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 } 185 187 /** 188 * When the AsyncTask finishes, it calls onRefreshComplete(), which updates the data in the 189 * ListAdapter and turns off the progress bar. 190 */ 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 } 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 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 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 }