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