1 /*
2  * Copyright (C) 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.justforus;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.support.v4.app.ShareCompat;
24 import android.support.v7.app.AppCompatActivity;
25 import android.text.TextUtils;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.AdapterView;
30 import android.widget.AdapterView.OnItemClickListener;
31 import android.widget.BaseAdapter;
32 import android.widget.GridView;
33 import android.widget.ImageView;
34 import android.widget.TextView;
35 
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 /**
40  * Activity to display a grid of coupons. The number of columns varies based on screen width,
41  * and goes down to a one-column grid on a small device such as a phone.
42  *
43  * <p>A coupon consists of a photo, title, and subtitle.
44  *
45  * <p>Tapping on a coupon to redeem it brings up the Android "share"
46  * dialog with a pre-populated message based on the coupon text.
47  */
48 public class MainActivity extends AppCompatActivity implements OnItemClickListener {
49 
50     // Name of person giving out these coupons. When the user clicks on a coupon and shares
51     // to another app, this name will be part of the pre-populated text.
52     // TODO: Fill in your name here
53     private static final String SENDER_NAME = "";
54 
55     @Override
onCreate(Bundle savedInstanceState)56     protected void onCreate(Bundle savedInstanceState) {
57         super.onCreate(savedInstanceState);
58         // Set activity_main.xml to be the layout for this activity
59         setContentView(R.layout.activity_main);
60 
61         // Fetch the {@link LayoutInflater} service so that new views can be created
62         LayoutInflater inflater = (LayoutInflater) getSystemService(
63                 Context.LAYOUT_INFLATER_SERVICE);
64 
65         // Find the {@link GridView} that was already defined in the XML layout
66         GridView gridView = (GridView) findViewById(R.id.grid);
67 
68         // Initialize the adapter with all the coupons. Set the adapter on the {@link GridView}.
69         gridView.setAdapter(new CouponAdapter(inflater, createAllCoupons()));
70 
71         // Set a click listener for each coupon in the grid
72         gridView.setOnItemClickListener(this);
73     }
74 
75     /**
76      * Generate the list of all coupons.
77      * @return The list of coupons.
78      */
createAllCoupons()79     private List<Coupon> createAllCoupons() {
80         // TODO: Customize this list of coupons for your personal use.
81         // You can add a title, subtitle, and a photo (in the assets directory).
82         List<Coupon> coupons = new ArrayList<Coupon>();
83         coupons.add(new Coupon("Walk in the park" /* title */,
84                 "Take a stroll in the flower garden" /* subtitle */, "park.jpg" /* image */));
85         coupons.add(new Coupon("Trip to the zoo",
86                 "See the cute zoo animals", "zoo.jpg"));
87         coupons.add(new Coupon("Watch sunrise",
88                 "Drive out to the vista point and watch the sunrise at 6am", "sunrise.jpg"));
89         coupons.add(new Coupon("Hawaii getaway",
90                 "Relax in Hawaii by going to the beach and attending luaus", "hawaii.jpg"));
91         coupons.add(new Coupon("Spa day",
92                 "Receive a massage and enjoy the peace and quiet", "spa.jpg"));
93         coupons.add(new Coupon("Homemade dinner",
94                 "Your favorite meal cooked by yours truly", "dinner.jpg"));
95         coupons.add(new Coupon("Day on the water",
96                 "Boat ride down the river on a breezy day", "boat.jpg"));
97         coupons.add(new Coupon("Flowers",
98                 "Delivered to your front door", "rose.jpg"));
99         coupons.add(new Coupon("Picnic",
100                 "Wine, bread, and cheese at the vineyard", "picnic.jpg"));
101         coupons.add(new Coupon("Surprise gift",
102                 "Won't be revealed until redeemed", "present.jpg"));
103         return coupons;
104     }
105 
106     /**
107      * Callback method for a when a coupon is clicked. A new share intent is created with the
108      * coupon title. Then the user can select which app to share the content of the coupon with.
109      *
110      * @param parent The AdapterView where the click happened.
111      * @param view The view within the AdapterView that was clicked (this
112      *            will be a view provided by the adapter).
113      * @param position The position of the view in the adapter.
114      * @param id The row id of the item that was clicked.
115      */
116     @Override
onItemClick(AdapterView<?> parent, View view, int position, long id)117     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
118         // Find coupon that was clicked based off of position in adapter
119         Coupon coupon = (Coupon) parent.getItemAtPosition(position);
120 
121         // Create share intent
122         Intent shareIntent = ShareCompat.IntentBuilder.from(this)
123                 .setText(getShareText(coupon))
124                 .setType("image/jpeg")
125                 .setStream(coupon.mImageUri)
126                 .setChooserTitle(getString(R.string.redeem_using))
127                 .createChooserIntent();
128         startActivity(shareIntent);
129     }
130 
131     /**
132      * Create the share intent text based on the coupon title, subtitle, and whether or not
133      * there is a {@link #SENDER_NAME}.
134      *
135      * @param coupon to create the intent text for.
136      * @return string to be used in the share intent.
137      */
getShareText(Coupon coupon)138     private String getShareText(Coupon coupon) {
139         // If there is no sender name, just use the coupon title and subtitle
140         if (TextUtils.isEmpty(SENDER_NAME)) {
141             return getString(R.string.message_format_without_sender,
142                     coupon.mTitle, coupon.mSubtitle);
143         } else {
144             // Otherwise, use the other string template and pass in the {@link #SENDER_NAME} too
145             return getString(R.string.message_format_with_sender, SENDER_NAME,
146                     coupon.mTitle, coupon.mSubtitle);
147         }
148     }
149 
150     /**
151      * Adapter for grid of coupons.
152      */
153     private static class CouponAdapter extends BaseAdapter {
154 
155         private LayoutInflater mInflater;
156         private List<Coupon> mAllCoupons;
157 
158         /**
159          * Constructs a new {@link CouponAdapter}.
160          *
161          * @param inflater to create new views
162          * @param allCoupons for list of all coupons to be displayed
163          */
CouponAdapter(LayoutInflater inflater, List<Coupon> allCoupons)164         public CouponAdapter(LayoutInflater inflater, List<Coupon> allCoupons) {
165             if (allCoupons == null) {
166                 throw new IllegalStateException("Can't have null list of coupons");
167             }
168             mAllCoupons = allCoupons;
169             mInflater = inflater;
170         }
171 
172         @Override
getCount()173         public int getCount() {
174             return mAllCoupons.size();
175         }
176 
177         @Override
getItem(int position)178         public Coupon getItem(int position) {
179             return mAllCoupons.get(position);
180         }
181 
182         @Override
getItemId(int position)183         public long getItemId(int position) {
184             return position;
185         }
186 
187         @Override
getView(int position, View convertView, ViewGroup parent)188         public View getView(int position, View convertView, ViewGroup parent) {
189             View result = convertView;
190             if (result == null) {
191                 result = mInflater.inflate(R.layout.grid_item, parent, false);
192             }
193 
194             // Try to get view cache or create a new one if needed
195             ViewCache viewCache = (ViewCache) result.getTag();
196             if (viewCache == null) {
197                 viewCache = new ViewCache(result);
198                 result.setTag(viewCache);
199             }
200 
201             // Fetch item
202             Coupon coupon = getItem(position);
203 
204             // Bind the data
205             viewCache.mTitleView.setText(coupon.mTitle);
206             viewCache.mSubtitleView.setText(coupon.mSubtitle);
207             viewCache.mImageView.setImageURI(coupon.mImageUri);
208 
209             return result;
210         }
211     }
212 
213     /**
214      * Cache of views in the grid item view to make recycling of views quicker. This avoids
215      * additional {@link View#findViewById(int)} calls after the {@link ViewCache} is first
216      * created for a view. See
217      * {@link CouponAdapter#getView(int position, View convertView, ViewGroup parent)}.
218      */
219     private static class ViewCache {
220 
221         /** View that displays the title of the coupon */
222         private final TextView mTitleView;
223 
224         /** View that displays the subtitle of the coupon */
225         private final TextView mSubtitleView;
226 
227         /** View that displays the image associated with the coupon */
228         private final ImageView mImageView;
229 
230         /**
231          * Constructs a new {@link ViewCache}.
232          *
233          * @param view which contains children views that should be cached.
234          */
ViewCache(View view)235         private ViewCache(View view) {
236             mTitleView = (TextView) view.findViewById(R.id.title);
237             mSubtitleView = (TextView) view.findViewById(R.id.subtitle);
238             mImageView = (ImageView) view.findViewById(R.id.image);
239         }
240     }
241 
242     /**
243      * Model object for coupon.
244      */
245     private static class Coupon {
246 
247         /** Title of the coupon. */
248         private final String mTitle;
249 
250         /** Description of the coupon. */
251         private final String mSubtitle;
252 
253         /** Content URI of the image for the coupon. */
254         private final Uri mImageUri;
255 
256         /**
257          * Constructs a new {@link Coupon}.
258          *
259          * @param titleString is the title
260          * @param subtitleString is the description
261          * @param imageAssetFilePath is the file path from the application's assets folder for
262          *                           the image associated with this coupon
263          */
Coupon(String titleString, String subtitleString, String imageAssetFilePath)264         private Coupon(String titleString, String subtitleString, String imageAssetFilePath) {
265             mTitle = titleString;
266             mSubtitle = subtitleString;
267             mImageUri = Uri.parse("content://" + AssetProvider.CONTENT_URI + "/" +
268                     imageAssetFilePath);
269         }
270     }
271 }
272