• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc. All rights reserved.
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.xyztouristattractions.ui;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.location.Location;
23 import android.os.Bundle;
24 import android.support.v4.app.Fragment;
25 import android.support.v4.content.LocalBroadcastManager;
26 import android.support.v7.widget.GridLayoutManager;
27 import android.support.v7.widget.RecyclerView;
28 import android.text.TextUtils;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.ImageView;
33 import android.widget.TextView;
34 
35 import com.bumptech.glide.Glide;
36 import com.bumptech.glide.load.engine.DiskCacheStrategy;
37 import com.example.android.xyztouristattractions.R;
38 import com.example.android.xyztouristattractions.common.Attraction;
39 import com.example.android.xyztouristattractions.common.Constants;
40 import com.example.android.xyztouristattractions.common.Utils;
41 import com.example.android.xyztouristattractions.provider.TouristAttractions;
42 import com.example.android.xyztouristattractions.service.UtilityService;
43 import com.google.android.gms.location.FusedLocationProviderApi;
44 import com.google.android.gms.maps.model.LatLng;
45 import com.google.maps.android.SphericalUtil;
46 
47 import java.util.Collections;
48 import java.util.Comparator;
49 import java.util.List;
50 
51 import static com.example.android.xyztouristattractions.provider.TouristAttractions.ATTRACTIONS;
52 
53 /**
54  * The main tourist attraction fragment which contains a list of attractions
55  * sorted by distance (contained inside
56  * {@link com.example.android.xyztouristattractions.ui.AttractionListActivity}).
57  */
58 public class AttractionListFragment extends Fragment {
59 
60     private AttractionAdapter mAdapter;
61     private LatLng mLatestLocation;
62     private int mImageSize;
63 
AttractionListFragment()64     public AttractionListFragment() {}
65 
66     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)67     public View onCreateView(LayoutInflater inflater, ViewGroup container,
68                              Bundle savedInstanceState) {
69         // Load a larger size image to make the activity transition to the detail screen smooth
70         mImageSize = getResources().getDimensionPixelSize(R.dimen.image_size)
71                 * Constants.IMAGE_ANIM_MULTIPLIER;
72 
73         mLatestLocation = Utils.getLocation(getActivity());
74         List<Attraction> attractions = loadAttractionsFromLocation(mLatestLocation);
75         mAdapter = new AttractionAdapter(getActivity(), attractions);
76 
77         View view = inflater.inflate(R.layout.fragment_main, container, false);
78         AttractionsRecyclerView recyclerView =
79                 (AttractionsRecyclerView) view.findViewById(android.R.id.list);
80         recyclerView.setEmptyView(view.findViewById(android.R.id.empty));
81         recyclerView.setHasFixedSize(true);
82         recyclerView.setLayoutManager(new GridLayoutManager(
83                 getActivity(), getResources().getInteger(R.integer.list_columns)));
84         recyclerView.setAdapter(mAdapter);
85 
86         return view;
87     }
88 
89     @Override
onResume()90     public void onResume() {
91         super.onResume();
92         LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
93                 mBroadcastReceiver, UtilityService.getLocationUpdatedIntentFilter());
94     }
95 
96     @Override
onPause()97     public void onPause() {
98         super.onPause();
99         LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mBroadcastReceiver);
100     }
101 
102     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
103         @Override
104         public void onReceive(Context context, Intent intent) {
105             Location location =
106                     intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
107             if (location != null) {
108                 mLatestLocation = new LatLng(location.getLatitude(), location.getLongitude());
109                 mAdapter.mAttractionList = loadAttractionsFromLocation(mLatestLocation);
110                 mAdapter.notifyDataSetChanged();
111             }
112         }
113     };
114 
loadAttractionsFromLocation(final LatLng curLatLng)115     private static List<Attraction> loadAttractionsFromLocation(final LatLng curLatLng) {
116         String closestCity = TouristAttractions.getClosestCity(curLatLng);
117         if (closestCity != null) {
118             List<Attraction> attractions = ATTRACTIONS.get(closestCity);
119             if (curLatLng != null) {
120                 Collections.sort(attractions,
121                         new Comparator<Attraction>() {
122                             @Override
123                             public int compare(Attraction lhs, Attraction rhs) {
124                                 double lhsDistance = SphericalUtil.computeDistanceBetween(
125                                         lhs.location, curLatLng);
126                                 double rhsDistance = SphericalUtil.computeDistanceBetween(
127                                         rhs.location, curLatLng);
128                                 return (int) (lhsDistance - rhsDistance);
129                             }
130                         }
131                 );
132             }
133             return attractions;
134         }
135         return null;
136     }
137 
138     private class AttractionAdapter extends RecyclerView.Adapter<ViewHolder>
139             implements ItemClickListener {
140 
141         public List<Attraction> mAttractionList;
142         private Context mContext;
143 
AttractionAdapter(Context context, List<Attraction> attractions)144         public AttractionAdapter(Context context, List<Attraction> attractions) {
145             super();
146             mContext = context;
147             mAttractionList = attractions;
148         }
149 
150         @Override
onCreateViewHolder(ViewGroup parent, int viewType)151         public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
152             LayoutInflater inflater = LayoutInflater.from(mContext);
153             View view = inflater.inflate(R.layout.list_row, parent, false);
154             return new ViewHolder(view, this);
155         }
156 
157         @Override
onBindViewHolder(ViewHolder holder, int position)158         public void onBindViewHolder(ViewHolder holder, int position) {
159             Attraction attraction = mAttractionList.get(position);
160 
161             holder.mTitleTextView.setText(attraction.name);
162             holder.mDescriptionTextView.setText(attraction.description);
163             Glide.with(mContext)
164                     .load(attraction.imageUrl)
165                     .diskCacheStrategy(DiskCacheStrategy.SOURCE)
166                     .placeholder(R.drawable.empty_photo)
167                     .override(mImageSize, mImageSize)
168                     .into(holder.mImageView);
169 
170             String distance =
171                     Utils.formatDistanceBetween(mLatestLocation, attraction.location);
172             if (TextUtils.isEmpty(distance)) {
173                 holder.mOverlayTextView.setVisibility(View.GONE);
174             } else {
175                 holder.mOverlayTextView.setVisibility(View.VISIBLE);
176                 holder.mOverlayTextView.setText(distance);
177             }
178         }
179 
180         @Override
getItemId(int position)181         public long getItemId(int position) {
182             return position;
183         }
184 
185         @Override
getItemCount()186         public int getItemCount() {
187             return mAttractionList == null ? 0 : mAttractionList.size();
188         }
189 
190         @Override
onItemClick(View view, int position)191         public void onItemClick(View view, int position) {
192             View heroView = view.findViewById(android.R.id.icon);
193             DetailActivity.launch(
194                     getActivity(), mAdapter.mAttractionList.get(position).name, heroView);
195         }
196     }
197 
198     private static class ViewHolder extends RecyclerView.ViewHolder
199             implements View.OnClickListener {
200 
201         TextView mTitleTextView;
202         TextView mDescriptionTextView;
203         TextView mOverlayTextView;
204         ImageView mImageView;
205         ItemClickListener mItemClickListener;
206 
ViewHolder(View view, ItemClickListener itemClickListener)207         public ViewHolder(View view, ItemClickListener itemClickListener) {
208             super(view);
209             mTitleTextView = (TextView) view.findViewById(android.R.id.text1);
210             mDescriptionTextView = (TextView) view.findViewById(android.R.id.text2);
211             mOverlayTextView = (TextView) view.findViewById(R.id.overlaytext);
212             mImageView = (ImageView) view.findViewById(android.R.id.icon);
213             mItemClickListener = itemClickListener;
214             view.setOnClickListener(this);
215         }
216 
217         @Override
onClick(View v)218         public void onClick(View v) {
219             mItemClickListener.onItemClick(v, getAdapterPosition());
220         }
221     }
222 
223     interface ItemClickListener {
onItemClick(View view, int position)224         void onItemClick(View view, int position);
225     }
226 }
227