changed the java LiteListDemo to use RecyclerView

This commit is contained in:
Bella Mangunsong 2018-01-18 17:50:07 +11:00
parent 1a5a5d16e1
commit bf92d73028
7 changed files with 197 additions and 164 deletions

View File

@ -26,4 +26,6 @@ dependencies {
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation 'com.google.android.gms:play-services-maps:11.6.2'
implementation 'com.android.support:support-v4:27.0.2'
// Needed for the LiteListDemo
implementation "com.android.support:recyclerview-v7:27.0.2"
}

View File

@ -24,18 +24,18 @@ import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.HashSet;
/**
* This shows to include a map in lite mode in a ListView.
* Note the use of the view holder pattern with the
@ -43,169 +43,171 @@ import java.util.HashSet;
*/
public class LiteListDemoActivity extends AppCompatActivity {
private ListFragment mList;
private RecyclerView mRecyclerView;
private MapAdapter mAdapter;
private LinearLayoutManager mLinearLayoutManager;
private GridLayoutManager mGridLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lite_list_demo);
// Set a custom list adapter for a list of locations
mAdapter = new MapAdapter(this, LIST_LOCATIONS);
mList = (ListFragment) getSupportFragmentManager().findFragmentById(R.id.list);
mList.setListAdapter(mAdapter);
mGridLayoutManager = new GridLayoutManager(this, 2);
mLinearLayoutManager = new LinearLayoutManager(this);
// Set a RecyclerListener to clean up MapView from ListView
AbsListView lv = mList.getListView();
lv.setRecyclerListener(mRecycleListener);
// Set up the RecyclerView
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mRecyclerView.setAdapter(new MapAdapter(LIST_LOCATIONS));
mRecyclerView.setRecyclerListener(mRecycleListener);
}
/** Create a menu to switch between Linear and Grid LayoutManager. */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.lite_list_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.layout_linear:
mRecyclerView.setLayoutManager(mLinearLayoutManager);
break;
case R.id.layout_grid:
mRecyclerView.setLayoutManager(mGridLayoutManager);
break;
}
return true;
}
/**
* Adapter that displays a title and {@link com.google.android.gms.maps.MapView} for each item.
* The layout is defined in <code>lite_list_demo_row.xml</code>. It contains a MapView
* that is programatically initialised in
* {@link #getView(int, android.view.View, android.view.ViewGroup)}
* {@link #(int, android.view.View, android.view.ViewGroup)}
*/
private class MapAdapter extends ArrayAdapter<NamedLocation> {
private class MapAdapter extends RecyclerView.Adapter<MapAdapter.ViewHolder> {
private final HashSet<MapView> mMaps = new HashSet<MapView>();
private NamedLocation[] namedLocations;
public MapAdapter(Context context, NamedLocation[] locations) {
super(context, R.layout.lite_list_demo_row, R.id.lite_listrow_text, locations);
private MapAdapter(NamedLocation[] locations) {
super();
namedLocations = locations;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
// Check if a view can be reused, otherwise inflate a layout and set up the view holder
if (row == null) {
// Inflate view from layout file
row = getLayoutInflater().inflate(R.layout.lite_list_demo_row, null);
// Set up holder and assign it to the View
holder = new ViewHolder();
holder.mapView = (MapView) row.findViewById(R.id.lite_listrow_map);
holder.title = (TextView) row.findViewById(R.id.lite_listrow_text);
// Set holder as tag for row for more efficient access.
row.setTag(holder);
// Initialise the MapView
holder.initializeMapView();
// Keep track of MapView
mMaps.add(holder.mapView);
} else {
// View has already been initialised, get its holder
holder = (ViewHolder) row.getTag();
}
// Get the NamedLocation for this item and attach it to the MapView
NamedLocation item = getItem(position);
holder.mapView.setTag(item);
// Ensure the map has been initialised by the on map ready callback in ViewHolder.
// If it is not ready yet, it will be initialised with the NamedLocation set as its tag
// when the callback is received.
if (holder.map != null) {
// The map is already ready to be used
setMapLocation(holder.map, item);
}
// Set the text label for this item
holder.title.setText(item.name);
return row;
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.lite_list_demo_row, parent, false));
}
/**
* Retuns the set of all initialised {@link MapView} objects.
*
* @return All MapViews that have been initialised programmatically by this adapter
* This function is called when the user scrolls through the screen and a new item needs
* to be shown. So we will need to bind the holder with the details of the next item.
*/
public HashSet<MapView> getMaps() {
return mMaps;
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder == null) {
return;
}
holder.bindView(position);
}
}
/**
* Displays a {@link LiteListDemoActivity.NamedLocation} on a
* {@link com.google.android.gms.maps.GoogleMap}.
* Adds a marker and centers the camera on the NamedLocation with the normal map type.
*/
private static void setMapLocation(GoogleMap map, NamedLocation data) {
// Add a marker for this item and set the camera
map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f));
map.addMarker(new MarkerOptions().position(data.location));
// Set the map type back to normal.
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
/**
* Holder for Views used in the {@link LiteListDemoActivity.MapAdapter}.
* Once the the <code>map</code> field is set, otherwise it is null.
* When the {@link #onMapReady(com.google.android.gms.maps.GoogleMap)} callback is received and
* the {@link com.google.android.gms.maps.GoogleMap} is ready, it stored in the {@link #map}
* field. The map is then initialised with the NamedLocation that is stored as the tag of the
* MapView. This ensures that the map is initialised with the latest data that it should
* display.
*/
class ViewHolder implements OnMapReadyCallback {
MapView mapView;
TextView title;
GoogleMap map;
@Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(getApplicationContext());
map = googleMap;
NamedLocation data = (NamedLocation) mapView.getTag();
if (data != null) {
setMapLocation(map, data);
}
public int getItemCount() {
return namedLocations.length;
}
/**
* Initialises the MapView by calling its lifecycle methods.
* Holder for Views used in the {@link LiteListDemoActivity.MapAdapter}.
* Once the the <code>map</code> field is set, otherwise it is null.
* When the {@link #onMapReady(com.google.android.gms.maps.GoogleMap)} callback is received and
* the {@link com.google.android.gms.maps.GoogleMap} is ready, it stored in the {@link #map}
* field. The map is then initialised with the NamedLocation that is stored as the tag of the
* MapView. This ensures that the map is initialised with the latest data that it should
* display.
*/
public void initializeMapView() {
if (mapView != null) {
// Initialise the MapView
mapView.onCreate(null);
// Set the map ready callback to receive the GoogleMap object
mapView.getMapAsync(this);
class ViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback {
MapView mapView;
TextView title;
GoogleMap map;
View layout;
private ViewHolder(View itemView) {
super(itemView);
layout = itemView;
mapView = layout.findViewById(R.id.lite_listrow_map);
title = layout.findViewById(R.id.lite_listrow_text);
if (mapView != null) {
// Initialise the MapView
mapView.onCreate(null);
// Set the map ready callback to receive the GoogleMap object
mapView.getMapAsync(this);
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(getApplicationContext());
map = googleMap;
setMapLocation();
}
/**
* Displays a {@link LiteListDemoActivity.NamedLocation} on a
* {@link com.google.android.gms.maps.GoogleMap}.
* Adds a marker and centers the camera on the NamedLocation with the normal map type.
*/
private void setMapLocation() {
if (map == null) return;
NamedLocation data = (NamedLocation) mapView.getTag();
if (data == null) return;
// Add a marker for this item and set the camera
map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 13f));
map.addMarker(new MarkerOptions().position(data.location));
// Set the map type back to normal.
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
private void bindView(int pos) {
NamedLocation item = namedLocations[pos];
// Store a reference of the ViewHolder object in the layout.
layout.setTag(this);
// Store a reference to the item in the mapView's tag. We use it to get the
// coordinate of a location, when setting the map location.
mapView.setTag(item);
setMapLocation();
title.setText(item.name);
}
}
}
/**
* RecycleListener that completely clears the {@link com.google.android.gms.maps.GoogleMap}
* attached to a row in the ListView.
* attached to a row in the RecyclerView.
* Sets the map type to {@link com.google.android.gms.maps.GoogleMap#MAP_TYPE_NONE} and clears
* the map.
*/
private AbsListView.RecyclerListener mRecycleListener = new AbsListView.RecyclerListener() {
private RecyclerView.RecyclerListener mRecycleListener = new RecyclerView.RecyclerListener() {
@Override
public void onMovedToScrapHeap(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (holder != null && holder.map != null) {
// Clear the map and free up resources by changing the map type to none
holder.map.clear();
holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
public void onViewRecycled(RecyclerView.ViewHolder holder) {
MapAdapter.ViewHolder mapHolder = (MapAdapter.ViewHolder) holder;
if (mapHolder != null && mapHolder.map != null) {
// Clear the map and free up resources by changing the map type to none.
// Also reset the map when it gets reattached to layout, so the previous map would
// not be displayed.
mapHolder.map.clear();
mapHolder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}
};
@ -216,7 +218,6 @@ public class LiteListDemoActivity extends AppCompatActivity {
private static class NamedLocation {
public final String name;
public final LatLng location;
NamedLocation(String name, LatLng location) {

View File

@ -1,26 +1,22 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2014 The Android Open Source Project
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/list"
class="android.support.v4.app.ListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
android:layout_height="match_parent" />

View File

@ -1,29 +1,30 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2014 The Android Open Source Project
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="5dp">
<TextView
android:id="@+id/lite_listrow_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge" />
<!-- MapView in lite mode. Note that it needs to be initialised

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/layout_linear"
android:title="@string/linear"
app:showAsAction="never" />
<item
android:id="@+id/layout_grid"
android:title="@string/grid"
app:showAsAction="never" />
</menu>

View File

@ -177,14 +177,16 @@
<string name="pattern_mixed">Mixed</string>
<!-- Lite Mode -->
<string name="grid">Grid</string>
<string name="lite_demo_label">Lite Mode</string>
<string name="lite_demo_description">Demonstrates some features on a map in lite mode.</string>
<string name="lite_demo_intro">Click the map with no, one or multiple markers displayed to open the Google Maps Mobile app.</string>
<string name="lite_go_to_darwin">Go to Darwin (No Markers)</string>
<string name="lite_go_to_adelaide">Go to Adelaide (One Marker)</string>
<string name="lite_go_to_australia">Go to Australia (Five Markers)</string>
<string name="lite_list_demo_label">Lite Mode ListView</string>
<string name="lite_list_demo_description">Demonstrates using maps in lite mode in a ListView.</string>
<string name="linear">Linear</string>
<string name="lite_list_demo_label">Lite Mode List</string>
<string name="lite_list_demo_description">Demonstrates using maps in lite mode in a RecyclerView using LinearLayoutManager and GridLayoutManager.</string>
<!-- Indoor -->
<string name="activate_higher_level">Activate Higher Level</string>

View File

@ -1,6 +1,6 @@
#Tue Jun 06 10:13:43 AEST 2017
#Thu Jan 18 10:58:29 AEDT 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip