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