Merge pull request #766 from psh/nearby-list

Converted nearby list to recycler view
This commit is contained in:
Josephine Lim 2017-07-11 15:53:39 +10:00 committed by GitHub
commit e132012afc
15 changed files with 299 additions and 192 deletions

View file

@ -15,6 +15,7 @@ dependencies {
compile "com.android.support:design:${project.supportLibVersion}" compile "com.android.support:design:${project.supportLibVersion}"
compile 'com.google.code.gson:gson:2.7' compile 'com.google.code.gson:gson:2.7'
compile "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION" compile "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION"
compile 'com.github.pedrovgs:renderers:3.3.0'
annotationProcessor "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION" annotationProcessor "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION"
compile 'com.jakewharton.timber:timber:4.5.1' compile 'com.jakewharton.timber:timber:4.5.1'
compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0@aar'){ compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0@aar'){
@ -25,6 +26,9 @@ dependencies {
compile "com.google.guava:guava:${GUAVA_VERSION}" compile "com.google.guava:guava:${GUAVA_VERSION}"
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile ('org.robolectric:robolectric:3.3.2') {
exclude module: 'guava'
}
androidTestCompile "com.android.support:support-annotations:${project.supportLibVersion}" androidTestCompile "com.android.support:support-annotations:${project.supportLibVersion}"
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'

View file

@ -30,8 +30,8 @@ import java.util.List;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.theme.NavigationBaseActivity; import fr.free.nrw.commons.theme.NavigationBaseActivity;
@ -41,8 +41,7 @@ import timber.log.Timber;
public class NearbyActivity extends NavigationBaseActivity { public class NearbyActivity extends NavigationBaseActivity {
@BindView(R.id.progressBar) @BindView(R.id.progressBar) ProgressBar progressBar;
ProgressBar progressBar;
private boolean isMapViewActive = false; private boolean isMapViewActive = false;
private static final int LOCATION_REQUEST = 1; private static final int LOCATION_REQUEST = 1;
@ -133,7 +132,7 @@ public class NearbyActivity extends NavigationBaseActivity {
} }
} }
protected void checkGps() { private void checkGps() {
LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE); LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Timber.d("GPS is not enabled"); Timber.d("GPS is not enabled");
@ -202,15 +201,11 @@ public class NearbyActivity extends NavigationBaseActivity {
} }
} }
protected void refreshView() { private void refreshView() {
nearbyAsyncTask = new NearbyAsyncTask(this); nearbyAsyncTask = new NearbyAsyncTask(this);
nearbyAsyncTask.execute(); nearbyAsyncTask.execute();
} }
public LocationServiceManager getLocationManager() {
return locationManager;
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
@ -221,17 +216,12 @@ public class NearbyActivity extends NavigationBaseActivity {
private class NearbyAsyncTask extends AsyncTask<Void, Integer, List<Place>> { private class NearbyAsyncTask extends AsyncTask<Void, Integer, List<Place>> {
private Context mContext; private final Context mContext;
private NearbyAsyncTask (Context context) { private NearbyAsyncTask (Context context) {
mContext = context; mContext = context;
} }
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override @Override
protected void onProgressUpdate(Integer... values) { protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values); super.onProgressUpdate(values);
@ -284,7 +274,7 @@ public class NearbyActivity extends NavigationBaseActivity {
/** /**
* Calls fragment for map view. * Calls fragment for map view.
*/ */
public void setMapFragment() { private void setMapFragment() {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = new NearbyMapFragment(); Fragment fragment = new NearbyMapFragment();
fragment.setArguments(bundle); fragment.setArguments(bundle);
@ -295,7 +285,7 @@ public class NearbyActivity extends NavigationBaseActivity {
/** /**
* Calls fragment for list view. * Calls fragment for list view.
*/ */
public void setListFragment() { private void setListFragment() {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = new NearbyListFragment(); Fragment fragment = new NearbyListFragment();
fragment.setArguments(bundle); fragment.setArguments(bundle);

View file

@ -1,44 +0,0 @@
package fr.free.nrw.commons.nearby;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import fr.free.nrw.commons.R;
import timber.log.Timber;
public class NearbyAdapter extends ArrayAdapter<Place> {
/** Accepts activity context and list of places.
* @param context activity context
*/
public NearbyAdapter(Context context) {
super(context, R.layout.item_place);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Place place = getItem(position);
Timber.v(String.valueOf(place));
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext())
.inflate(R.layout.item_place, parent, false);
}
NearbyViewHolder viewHolder = new NearbyViewHolder(convertView);
viewHolder.bindModel(getContext(), place);
// Return the completed view to render on screen
return convertView;
}
@Override
public long getItemId(int position) {
// TODO: use Wikidata Q-ID instead?
return position;
}
}

View file

@ -0,0 +1,24 @@
package fr.free.nrw.commons.nearby;
import com.pedrogomez.renderers.ListAdapteeCollection;
import com.pedrogomez.renderers.RVRendererAdapter;
import com.pedrogomez.renderers.RendererBuilder;
import java.util.Collections;
import java.util.List;
class NearbyAdapterFactory {
private PlaceRenderer.PlaceClickedListener listener;
NearbyAdapterFactory(PlaceRenderer.PlaceClickedListener listener) {
this.listener = listener;
}
public RVRendererAdapter<Place> create(List<Place> placeList) {
RendererBuilder<Place> builder = new RendererBuilder<Place>()
.bind(Place.class, new PlaceRenderer(listener));
ListAdapteeCollection<Place> collection = new ListAdapteeCollection<>(
placeList != null ? placeList : Collections.<Place>emptyList());
return new RVRendererAdapter<>(builder, collection);
}
}

View file

@ -17,16 +17,11 @@ import fr.free.nrw.commons.utils.UriSerializer;
public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBaseMarker> { public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBaseMarker> {
private Place place; private Place place;
public NearbyBaseMarker() {
NearbyBaseMarker() {
} }
public NearbyBaseMarker place(Place place) { private NearbyBaseMarker(Parcel in) {
this.place = place;
return getThis();
}
public NearbyBaseMarker(Parcel in) {
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer()) .registerTypeAdapter(Uri.class, new UriDeserializer())
.create(); .create();
@ -42,6 +37,11 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
place(gson.fromJson(gsonString, Place.class)); place(gson.fromJson(gsonString, Place.class));
} }
public NearbyBaseMarker place(Place place) {
this.place = place;
return this;
}
@Override @Override
public NearbyBaseMarker getThis() { public NearbyBaseMarker getThis() {
return this; return this;
@ -52,6 +52,10 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
return new NearbyMarker(this, place); return new NearbyMarker(this, place);
} }
public Place getPlace() {
return place;
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
@ -71,10 +75,6 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
dest.writeString(gson.toJson(place)); dest.writeString(gson.toJson(place));
} }
public Place getPlace() {
return place;
}
public static final Parcelable.Creator<NearbyBaseMarker> CREATOR public static final Parcelable.Creator<NearbyBaseMarker> CREATOR
= new Parcelable.Creator<NearbyBaseMarker>() { = new Parcelable.Creator<NearbyBaseMarker>() {
public NearbyBaseMarker createFromParcel(Parcel in) { public NearbyBaseMarker createFromParcel(Parcel in) {

View file

@ -29,19 +29,12 @@ public class NearbyInfoDialog extends OverlayDialog {
private final static String ARG_LONGITUDE = "longitude"; private final static String ARG_LONGITUDE = "longitude";
private final static String ARG_SITE_LINK = "sitelink"; private final static String ARG_SITE_LINK = "sitelink";
@BindView(R.id.link_preview_title) @BindView(R.id.link_preview_title) TextView placeTitle;
TextView placeTitle; @BindView(R.id.link_preview_extract) TextView placeDescription;
@BindView(R.id.link_preview_extract) @BindView(R.id.link_preview_go_button) TextView goToButton;
TextView placeDescription; @BindView(R.id.link_preview_overflow_button) ImageView overflowButton;
@BindView(R.id.link_preview_go_button)
TextView goToButton;
@BindView(R.id.link_preview_overflow_button)
ImageView overflowButton;
private Unbinder unbinder; private Unbinder unbinder;
private LatLng location; private LatLng location;
private Sitelinks sitelinks; private Sitelinks sitelinks;
@ -64,7 +57,7 @@ public class NearbyInfoDialog extends OverlayDialog {
private void getArticleLink(Bundle bundle) { private void getArticleLink(Bundle bundle) {
this.sitelinks = bundle.getParcelable(ARG_SITE_LINK); this.sitelinks = bundle.getParcelable(ARG_SITE_LINK);
if (sitelinks.getWikipediaLink().equals(Uri.EMPTY)) { if (sitelinks == null || Uri.EMPTY.equals(sitelinks.getWikipediaLink())) {
goToButton.setVisibility(View.GONE); goToButton.setVisibility(View.GONE);
} }
@ -99,7 +92,7 @@ public class NearbyInfoDialog extends OverlayDialog {
|| !sitelinks.getWikidataLink().equals(Uri.EMPTY); || !sitelinks.getWikidataLink().equals(Uri.EMPTY);
} }
private PopupMenu.OnMenuItemClickListener menuListener = new PopupMenu private final PopupMenu.OnMenuItemClickListener menuListener = new PopupMenu
.OnMenuItemClickListener() { .OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {

View file

@ -2,37 +2,37 @@ package fr.free.nrw.commons.nearby;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.ListFragment; import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ListView;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List; import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnItemClick;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.utils.UriDeserializer; import fr.free.nrw.commons.utils.UriDeserializer;
import timber.log.Timber; import timber.log.Timber;
public class NearbyListFragment extends ListFragment { public class NearbyListFragment extends Fragment {
private List<Place> placeList; private static final Type LIST_TYPE = new TypeToken<List<Place>>() {
}.getType();
private static final Type CUR_LAT_LNG_TYPE = new TypeToken<LatLng>() {
}.getType();
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer())
.create();
@BindView(R.id.listView) ListView listview; private NearbyAdapterFactory adapterFactory;
private RecyclerView recyclerView;
private NearbyAdapter adapter;
public NearbyListFragment() {
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -41,55 +41,39 @@ public class NearbyListFragment extends ListFragment {
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
Timber.d("NearbyListFragment created"); Timber.d("NearbyListFragment created");
View view = inflater.inflate(R.layout.fragment_nearby, container, false); View view = inflater.inflate(R.layout.fragment_nearby, container, false);
ButterKnife.bind(this, view); recyclerView = (RecyclerView) view.findViewById(R.id.listView);
adapter = new NearbyAdapter(getActivity()); recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
listview.setAdapter(adapter); adapterFactory = new NearbyAdapterFactory(new PlaceRenderer.PlaceClickedListener() {
@Override
public void placeClicked(Place place) {
NearbyInfoDialog.showYourself(getActivity(), place);
}
});
return view; return view;
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
// Check that this is the first time view is created, // Check that this is the first time view is created,
// to avoid double list when screen orientation changed // to avoid double list when screen orientation changed
List<Place> placeList = Collections.emptyList();
Bundle bundle = this.getArguments(); Bundle bundle = this.getArguments();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer())
.create();
if (bundle != null) { if (bundle != null) {
String gsonPlaceList = bundle.getString("PlaceList"); String gsonPlaceList = bundle.getString("PlaceList");
placeList = gson.fromJson(gsonPlaceList, LIST_TYPE);
String gsonLatLng = bundle.getString("CurLatLng"); String gsonLatLng = bundle.getString("CurLatLng");
Type listType = new TypeToken<List<Place>>() {}.getType(); LatLng curLatLng = gson.fromJson(gsonLatLng, CUR_LAT_LNG_TYPE);
placeList = gson.fromJson(gsonPlaceList, listType);
Type curLatLngType = new TypeToken<LatLng>() {}.getType();
LatLng curLatLng = gson.fromJson(gsonLatLng, curLatLngType);
placeList = NearbyController.loadAttractionsFromLocationToPlaces(curLatLng, placeList); placeList = NearbyController.loadAttractionsFromLocationToPlaces(curLatLng, placeList);
} }
if (savedInstanceState == null) {
adapter.clear();
Timber.d("Saved instance state is null, populating ListView");
}
adapter.clear(); recyclerView.setAdapter(adapterFactory.create(placeList));
adapter.addAll(placeList);
adapter.notifyDataSetChanged();
}
@OnItemClick(R.id.listView)
void onItemClicked(int position) {
Place place = (Place) listview.getItemAtPosition(position);
LatLng placeLatLng = place.location;
double latitude = placeLatLng.getLatitude();
double longitude = placeLatLng.getLongitude();
Timber.d("Item at position %d has coords: Lat: %f Long: %f", position, latitude, longitude);
NearbyInfoDialog.showYourself(getActivity(), place);
} }
} }

View file

@ -5,7 +5,6 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -39,7 +38,6 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment {
private fr.free.nrw.commons.location.LatLng curLatLng; private fr.free.nrw.commons.location.LatLng curLatLng;
public NearbyMapFragment() { public NearbyMapFragment() {
} }
@Override @Override
@ -123,7 +121,7 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment {
* which represents the user's position with an accuracy * which represents the user's position with an accuracy
* of 95%. * of 95%.
*/ */
public void addCurrentLocationMarker(MapboxMap mapboxMap) { private void addCurrentLocationMarker(MapboxMap mapboxMap) {
MarkerOptions currentLocationMarker = new MarkerOptions() MarkerOptions currentLocationMarker = new MarkerOptions()
.position(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude())); .position(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude()));
mapboxMap.addMarker(currentLocationMarker); mapboxMap.addMarker(currentLocationMarker);
@ -146,7 +144,7 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment {
* *
* @return List List of LatLng points of the circle. * @return List List of LatLng points of the circle.
*/ */
public List<LatLng> createCircleArray( private List<LatLng> createCircleArray(
double centerLat, double centerLong, float radius, int nodes) { double centerLat, double centerLong, float radius, int nodes) {
List<LatLng> circle = new ArrayList<>(); List<LatLng> circle = new ArrayList<>();
float radiusKilometer = radius / 1000; float radiusKilometer = radius / 1000;
@ -164,11 +162,6 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment {
return circle; return circle;
} }
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override @Override
public void onStart() { public void onStart() {
if (mapView != null) { if (mapView != null) {

View file

@ -2,8 +2,8 @@ package fr.free.nrw.commons.nearby;
import com.mapbox.mapboxsdk.annotations.Marker; import com.mapbox.mapboxsdk.annotations.Marker;
public class NearbyMarker extends Marker { class NearbyMarker extends Marker {
private Place place; private final Place place;
private NearbyBaseMarker nearbyBaseMarker; private NearbyBaseMarker nearbyBaseMarker;
/** /**
@ -11,21 +11,17 @@ public class NearbyMarker extends Marker {
* *
* @param baseMarkerOptions The builder used to construct the Marker. * @param baseMarkerOptions The builder used to construct the Marker.
*/ */
public NearbyMarker(NearbyBaseMarker baseMarkerOptions, Place place) { NearbyMarker(NearbyBaseMarker baseMarkerOptions, Place place) {
super(baseMarkerOptions); super(baseMarkerOptions);
this.place = place; this.place = place;
this.nearbyBaseMarker = baseMarkerOptions; this.nearbyBaseMarker = baseMarkerOptions;
} }
public NearbyBaseMarker getNearbyBaseMarker() { NearbyBaseMarker getNearbyBaseMarker() {
return nearbyBaseMarker; return nearbyBaseMarker;
} }
public Place getPlace() { public Place getPlace() {
return place; return place;
} }
public void setNearbyBaseMarker(NearbyBaseMarker nearbyBaseMarker) {
this.nearbyBaseMarker = nearbyBaseMarker;
}
} }

View file

@ -34,8 +34,7 @@ public class NearbyPlaces {
public NearbyPlaces() { public NearbyPlaces() {
try { try {
String query = FileUtils.readFromResource("/assets/queries/nearby_query.rq"); wikidataQuery = FileUtils.readFromResource("/assets/queries/nearby_query.rq");
wikidataQuery = query;
Timber.v(wikidataQuery); Timber.v(wikidataQuery);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -106,8 +105,8 @@ public class NearbyPlaces {
String wikiDataLink = Utils.stripLocalizedString(fields[1]); String wikiDataLink = Utils.stripLocalizedString(fields[1]);
String icon = fields[5]; String icon = fields[5];
double latitude = 0; double latitude;
double longitude = 0; double longitude;
Matcher matcher = Matcher matcher =
Pattern.compile("Point\\(([^ ]+) ([^ ]+)\\)").matcher(point); Pattern.compile("Point\\(([^ ]+) ([^ ]+)\\)").matcher(point);
if (!matcher.find()) { if (!matcher.find()) {

View file

@ -1,35 +0,0 @@
package fr.free.nrw.commons.nearby;
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.ViewHolder;
public class NearbyViewHolder implements ViewHolder<Place> {
@BindView(R.id.tvName) TextView tvName;
@BindView(R.id.tvDesc) TextView tvDesc;
@BindView(R.id.distance) TextView distance;
@BindView(R.id.icon) ImageView icon;
public NearbyViewHolder(View view) {
ButterKnife.bind(this, view);
}
@Override
public void bindModel(Context context, Place place) {
// Populate the data into the template view using the data object
tvName.setText(place.name);
String descriptionText = place.getDescription().getText();
if (descriptionText.equals("?")) {
descriptionText = context.getString(R.string.no_description_found);
}
tvDesc.setText(descriptionText);
distance.setText(place.distance);
icon.setImageResource(place.getDescription().getIcon());
}
}

View file

@ -14,14 +14,14 @@ public class Place {
public final String name; public final String name;
private final Description description; private final Description description;
public final String longDescription; private final String longDescription;
public final Uri secondaryImageUrl; private final Uri secondaryImageUrl;
public final LatLng location; public final LatLng location;
public Bitmap image; public Bitmap image;
public Bitmap secondaryImage; public Bitmap secondaryImage;
public String distance; public String distance;
public Sitelinks siteLinks; public final Sitelinks siteLinks;
public Place(String name, Description description, String longDescription, public Place(String name, Description description, String longDescription,

View file

@ -0,0 +1,64 @@
package fr.free.nrw.commons.nearby;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.pedrogomez.renderers.Renderer;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
class PlaceRenderer extends Renderer<Place> {
@BindView(R.id.tvName) TextView tvName;
@BindView(R.id.tvDesc) TextView tvDesc;
@BindView(R.id.distance) TextView distance;
@BindView(R.id.icon) ImageView icon;
private final PlaceClickedListener listener;
PlaceRenderer(PlaceClickedListener listener) {
this.listener = listener;
}
@Override
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
return layoutInflater.inflate(R.layout.item_place, viewGroup, false);
}
@Override
protected void setUpView(View view) {
ButterKnife.bind(this, view);
}
@Override
protected void hookListeners(View view) {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.placeClicked(getContent());
}
}
});
}
@Override
public void render() {
Place place = getContent();
tvName.setText(place.name);
String descriptionText = place.getDescription().getText();
if (descriptionText.equals("?")) {
descriptionText = getContext().getString(R.string.no_description_found);
}
tvDesc.setText(descriptionText);
distance.setText(place.distance);
icon.setImageResource(place.getDescription().getIcon());
}
interface PlaceClickedListener {
void placeClicked(Place place);
}
}

View file

@ -4,7 +4,7 @@
android:orientation="vertical" android:orientation="vertical"
> >
<ListView <android.support.v7.widget.RecyclerView
android:id="@+id/listView" android:id="@+id/listView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View file

@ -0,0 +1,139 @@
package fr.free.nrw.commons.nearby;
import android.support.annotation.NonNull;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.pedrogomez.renderers.RVRendererAdapter;
import com.pedrogomez.renderers.RendererViewHolder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowDrawable;
import java.util.Collections;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.location.LatLng;
import static org.junit.Assert.*;
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class NearbyAdapterFactoryTest {
private static final Place PLACE = new Place("name", Place.Description.AIRPORT,
"desc", null, new LatLng(38.6270, -90.1994, 0), null);
private static final Place UNKNOWN_PLACE = new Place("name", Place.Description.UNKNOWN,
"desc", null, new LatLng(39.7392, -104.9903, 0), null);
private Place clickedPlace;
@Test
public void factoryHandlesNullListAndNullListener() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(null);
RVRendererAdapter<Place> result = testObject.create(null);
assertNotNull(result);
assertEquals(0, result.getItemCount());
}
@Test
public void factoryHandlesEmptyListAndNullListener() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(null);
RVRendererAdapter<Place> result = testObject.create(Collections.<Place>emptyList());
assertNotNull(result);
assertEquals(0, result.getItemCount());
}
@Test
public void factoryHandlesNonEmptyListAndNullListener() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(null);
RVRendererAdapter<Place> result = testObject.create(Collections.singletonList(PLACE));
assertNotNull(result);
assertEquals(1, result.getItemCount());
assertEquals(PLACE, result.getItem(0));
}
@Test
public void rendererCorrectlyBound() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(null);
RVRendererAdapter<Place> result = testObject.create(Collections.singletonList(PLACE));
RendererViewHolder viewHolder = renderComponent(result);
assertNotNull(viewHolder.itemView.findViewById(R.id.tvName));
assertEquals("name",
((TextView) viewHolder.itemView.findViewById(R.id.tvName)).getText().toString());
assertNotNull(viewHolder.itemView.findViewById(R.id.tvDesc));
assertEquals("airport",
((TextView) viewHolder.itemView.findViewById(R.id.tvDesc)).getText().toString());
assertNotNull(viewHolder.itemView.findViewById(R.id.distance));
assertEquals("",
((TextView) viewHolder.itemView.findViewById(R.id.distance)).getText().toString());
assertNotNull(viewHolder.itemView.findViewById(R.id.icon));
ImageView imageView = (ImageView) viewHolder.itemView.findViewById(R.id.icon);
ShadowDrawable shadow = Shadows.shadowOf(imageView.getDrawable());
assertEquals(R.drawable.round_icon_airport, shadow.getCreatedFromResId());
}
@Test
public void rendererCorrectlyBoundForUnknownPlace() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(null);
RVRendererAdapter<Place> result = testObject.create(Collections.singletonList(UNKNOWN_PLACE));
RendererViewHolder viewHolder = renderComponent(result);
assertNotNull(viewHolder.itemView.findViewById(R.id.tvDesc));
assertEquals("no description found",
((TextView) viewHolder.itemView.findViewById(R.id.tvDesc)).getText().toString());
assertNotNull(viewHolder.itemView.findViewById(R.id.icon));
ImageView imageView = (ImageView) viewHolder.itemView.findViewById(R.id.icon);
ShadowDrawable shadow = Shadows.shadowOf(imageView.getDrawable());
assertEquals(R.drawable.round_icon_unknown, shadow.getCreatedFromResId());
}
@Test
public void clickView() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(new MockPlaceClickedListener());
RVRendererAdapter<Place> result = testObject.create(Collections.singletonList(PLACE));
RendererViewHolder viewHolder = renderComponent(result);
viewHolder.itemView.performClick();
assertEquals(PLACE, clickedPlace);
}
@Test
public void clickViewHandlesMisconfiguredListener() {
NearbyAdapterFactory testObject = new NearbyAdapterFactory(null);
RVRendererAdapter<Place> result = testObject.create(Collections.singletonList(PLACE));
RendererViewHolder viewHolder = renderComponent(result);
viewHolder.itemView.performClick();
}
@NonNull
private RendererViewHolder renderComponent(RVRendererAdapter<Place> result) {
FrameLayout viewGroup = new FrameLayout(RuntimeEnvironment.application);
int itemViewType = result.getItemViewType(0);
RendererViewHolder viewHolder = result.onCreateViewHolder(viewGroup, itemViewType);
assertNotNull(viewHolder);
result.bindViewHolder(viewHolder, 0);
return viewHolder;
}
private class MockPlaceClickedListener implements PlaceRenderer.PlaceClickedListener {
@Override
public void placeClicked(Place place) {
clickedPlace = place;
}
}
}