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 }