package com.mypopsy.staticmaps.demo.ui; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.SizeReadyCallback; import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.target.ViewTarget; import com.mypopsy.maps.StaticMap; import com.mypopsy.maps.StaticMap.GeoPoint; import com.mypopsy.maps.StaticMap.Marker; import com.mypopsy.maps.StaticMap.MarkerGroup; import com.mypopsy.maps.StaticMap.Path; import com.mypopsy.staticmaps.demo.R; import com.mypopsy.staticmaps.demo.adapter.BindableViewHolder; import com.mypopsy.staticmaps.demo.adapter.BindingArrayRecyclerAdapter; import com.mypopsy.staticmaps.demo.app.RecyclerViewFragment; import com.mypopsy.staticmaps.demo.glide.CropCircleTransformation; import com.mypopsy.staticmaps.demo.utils.PaddingItemDecoration; import java.util.List; import butterknife.Bind; import butterknife.BindDimen; import butterknife.ButterKnife; import static com.mypopsy.maps.StaticMap.Marker.Style.BLUE; import static com.mypopsy.maps.StaticMap.Marker.Style.GREEN; import static com.mypopsy.maps.StaticMap.Marker.Style.ORANGE; import static com.mypopsy.maps.StaticMap.Marker.Style.PURPLE; import static com.mypopsy.maps.StaticMap.Marker.Style.RED; import static com.mypopsy.maps.StaticMap.Type.HYBRID; import static com.mypopsy.maps.StaticMap.Type.ROADMAP; import static com.mypopsy.maps.StaticMap.Type.SATELLITE; public class DemoFragment extends RecyclerViewFragment { private static final String BASE_MARKER_URL = "http://raw.githubusercontent.com/renaudcerrato/static-maps-api/master/app/src/main/res/drawable/"; private static final String ICON_GOOGLE = BASE_MARKER_URL + "google.png"; private static final String ICON_NETFLIX = BASE_MARKER_URL + "netflix.png"; private static final String ICON_FACEBOOK = BASE_MARKER_URL + "facebook.png"; private static final String ICON_GHOSTBUSTER = BASE_MARKER_URL + "ghostbuster.png"; private final Model[] models = new Model[] { new Model("Paris", "5 most visited monuments", new GeoPoint("France"), new StaticMap() .marker(BLUE, new GeoPoint("Tour Eiffel")) .marker(RED, new GeoPoint("Cathédrale Notre Dame")) .marker(GREEN, new GeoPoint("Sacré-Coeur, 75018")) .marker(ORANGE, new GeoPoint("Musée du Louvre")) .marker(PURPLE, new GeoPoint("Arc de Triomphe")) ), new Model("New-York City", "Ghostbusters filming locations", new GeoPoint("NYC"), new StaticMap() .marker(Marker.Style.builder().icon(ICON_GHOSTBUSTER).build(), new GeoPoint(40.7195532,-74.0067987, "Firehouse")) .marker(RED.toBuilder().label('A').build(), new GeoPoint(40.7529234,-73.9827515, "Public Library")) .marker(GREEN.toBuilder().label('B').build(), new GeoPoint("Columbia University, NYC")) ), new Model("Silicon Valley", "Popular Headquarters", new GeoPoint("California, USA"), new StaticMap() .marker(Marker.Style.builder().icon(ICON_GOOGLE).build(), new GeoPoint("1600 Amphitheatre Pkwy, Mountain View, CA")) .marker(Marker.Style.builder().icon(ICON_FACEBOOK).build(), new GeoPoint("1 Hacker Way, Menlo Park, CA")) .marker(Marker.Style.builder().icon(ICON_NETFLIX).build(), new GeoPoint("100 Winchester Cir, Los Gatos, CA")) ), new Model("Bermuda Triangle", "Brrrrr.", null, new StaticMap() .path(Path.Style.builder().color(Color.TRANSPARENT).fill(0x66ff0000).build(), new GeoPoint("Miami, Florida"), new GeoPoint("San Juan, Puerto Rico"), new GeoPoint("Bermuda Island")) ), }; @BindDimen(R.dimen.activity_vertical_margin) int mVerticalPadding; @BindDimen(R.dimen.activity_horizontal_margin) int mHorizonralPadding; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); return inflater.inflate(R.layout.fragment_demo, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Adapter adapter = new Adapter(); adapter.addAll(models); RecyclerView recyclerView = getRecyclerView(); recyclerView.addItemDecoration(new PaddingItemDecoration( mHorizonralPadding/2, mVerticalPadding/2, mVerticalPadding/2, mHorizonralPadding/2)); recyclerView.setAdapter(adapter); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } static class Model { final CharSequence title; final CharSequence description; final StaticMap map; final GeoPoint icon; Model(CharSequence title, CharSequence description, GeoPoint icon, StaticMap map) { this.title = title; this.description = description; this.icon = icon; this.map = map; } } private class Adapter extends BindingArrayRecyclerAdapter { @Override public BindableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ModelViewHolder(parent); } } class ModelViewHolder extends BindableViewHolder implements Toolbar.OnMenuItemClickListener, RequestListener { private final Drawable PLACEHOLDER = new ColorDrawable(0xffadcaff); @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.map) ImageView image; @Bind(R.id.progressBar) View progress; @Bind(R.id.container_markers) ViewGroup markers; private Model model; public ModelViewHolder(ViewGroup parent) { this(LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_demo, parent, false)); } public ModelViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); toolbar.inflateMenu(R.menu.listitem); toolbar.setOnMenuItemClickListener(this); } @Override protected void bind(Model model) { this.model = model; toolbar.setTitle(model.title); toolbar.setSubtitle(model.description); progress.setVisibility(View.VISIBLE); if(model.icon != null) { Glide.with(DemoFragment.this) .load(new StaticMap().center(model.icon)) .asBitmap() .transform(new CropCircleTransformation(itemView.getContext())) .into(new ToolbarTarget(toolbar)); } else toolbar.setNavigationIcon(null); Glide.with(DemoFragment.this).load(model.map) .placeholder(PLACEHOLDER) .error(R.drawable.frown_cloud) .listener(this) .into(image); switch (model.map.type()) { case ROADMAP: toolbar.getMenu().findItem(R.id.menu_roadmap).setChecked(true); break; case SATELLITE: toolbar.getMenu().findItem(R.id.menu_satellite).setChecked(true); break; case HYBRID: toolbar.getMenu().findItem(R.id.menu_hybrid).setChecked(true); break; } markers.setVisibility(View.VISIBLE); List groups = model.map.markers(); int position = 0; for(MarkerGroup group: groups) { for(GeoPoint point: group.points) { TextView markerView = getMarkerView(position); bindMarkerView(group.style, point, markerView); position++; } } while(markers.getChildCount() > position) markers.removeViewAt(markers.getChildCount() - 1); if(markers.getChildCount() == 0) { markers.setVisibility(View.GONE); } } @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.menu_roadmap: model.map.type(ROADMAP); break; case R.id.menu_satellite: model.map.type(SATELLITE); break; case R.id.menu_hybrid: model.map.type(HYBRID); break; } getRecyclerView().getAdapter().notifyItemChanged(getAdapterPosition()); return true; } @Override public boolean onException(Exception e, StaticMap model, Target target, boolean isFirstResource) { progress.setVisibility(View.GONE); return false; } @Override public boolean onResourceReady(GlideDrawable resource, StaticMap model, Target target, boolean isFromMemoryCache, boolean isFirstResource) { progress.setVisibility(View.GONE); return false; } private TextView getMarkerView(int position) { if(position >= markers.getChildCount()) { LayoutInflater inflater = LayoutInflater.from(markers.getContext()); TextView textView = (TextView) inflater.inflate(R.layout.layout_markers, markers, false); markers.addView(textView); return textView; }else return (TextView) markers.getChildAt(position); } private void bindMarkerView(Marker.Style style, GeoPoint point, TextView textView) { Character label = style.label(); String text = point.address(); if (text == null) { text = String.format("%.6f %.6f", point.latitude(), point.longitude()); } if (label != null) { text = text + " (" + label + ")"; } textView.setText(text); if (style.icon() != null) { Glide.with(DemoFragment.this).load(style.icon()).asBitmap().into(new TextViewTarget(textView)); } else { Drawable d = DrawableCompat.wrap(getResources().getDrawable(R.drawable.ic_maps_marker)); DrawableCompat.setTint(d, style.color()); textView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null); } } } static private class ToolbarTarget extends ViewTarget { public static final int ICON_SIZE = 128; // dp public ToolbarTarget(Toolbar toolbar) { super(toolbar); } @Override public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { getView().setNavigationIcon(new BitmapDrawable(resource)); } @Override public void getSize(SizeReadyCallback cb) { cb.onSizeReady(dpToPx(ICON_SIZE), dpToPx(ICON_SIZE)); } } static private class TextViewTarget extends ViewTarget { public static final int ICON_MARGIN = 4; //dp public TextViewTarget(TextView view) { super(view); } @Override public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { Drawable d = new BitmapDrawable(getView().getResources(), resource); d = new InsetDrawable(d, dpToPx(ICON_MARGIN)); getView().setCompoundDrawablesWithIntrinsicBounds(d, null, null, null); } } static private int dpToPx(int dp){ DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); return (int) (dp * metrics.density); } }