I have a map where i display markers that are stored in a db (MySQL),each marker have different fields with it (for example: name, email, addres, etc), since "MarkerOptions" only let me use ".tittle",".snippet"some of the fields that i want to attach are left out, i know now that i have to use a custom infowindow to show all the fields that i want to. How can i do this?
My code:
Main:
ArrayList<HashMap<String, String>> location = null;
String url = "http://appserver.eco.mx/movil/getLanLong.php";
try {
JSONArray data = new JSONArray(getHttpGet(url));
location = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map;
for(int i = 0; i < data.length(); i++){
JSONObject c = data.getJSONObject(i);
map = new HashMap<String, String>();
map.put("id", c.getString("id"));
map.put("campo_latitud", c.getString("campo_latitud"));
map.put("campo_longitud", c.getString("campo_longitud"));
map.put("campo_categoria", c.getString("campo_categoria"));
map.put("campo_estado", c.getString("campo_estado"));
location.add(map);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String campouno = "";
if(!TextUtils.isEmpty(campouno)){
double campo_latitud = Double.parseDouble(campouno);
}
//campo_latitud = Double.parseDouble(location.get(0).get("Latitude").toString());
String campodos = "";
if(!TextUtils.isEmpty(campodos)){
double campo_longitud = Double.parseDouble(campodos);
}
for (int i = 0; i < location.size(); i++) {
if(!TextUtils.isEmpty(location.get(i).get("campo_latitud").toString())&&!TextUtils.isEmpty(location.get(i).get("campo_longitud").toString())) {
campo_latitud = Double.parseDouble(location.get(i).get("campo_latitud").toString());
campo_longitud = Double.parseDouble(location.get(i).get("campo_longitud").toString());
}
String name = location.get(i).get("campo_categoria").toString();
//String des = location.get(i).get("campo_descripcion").toString();
if(location.get(i).get("campo_categoria").toString().equals("Obras publicas")){
//System.out.println(location.get(i).get("campo_descripcion").toString());
googleMap.addMarker(new MarkerOptions().position(new LatLng(campo_latitud, campo_longitud)).title(name).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_op)));
}
}}
XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#android:color/white">
<TextView
android:id="#+id/info_window_nombre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:paddingLeft="5dp"
android:text="Carlo Estrada Solano" />
<TextView
android:id="#+id/info_window_placas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="20sp"
android:layout_below="#id/info_window_nombre"
android:paddingLeft="5dp"
android:text="Placas: SX5487" />
<TextView
android:id="#+id/info_window_estado"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/info_window_placas"
android:paddingLeft="5dp"
android:text="Estado: Activo" />
</LinearLayout>
InfoWindow class:
public class AdaptadorInforWindow implements GoogleMap.InfoWindowAdapter {
private static final String TAG = "CustomInfoWindowAdapter";
private LayoutInflater inflater;
public AdaptadorInforWindow(LayoutInflater inflater){
this.inflater = inflater;
}
#Override
public View getInfoWindow(Marker marker) {
//Carga layout personalizado.
View v = inflater.inflate(R.layout.infowindow_layout, null);
String[] info = marker.getTitle().split("&");
String url = marker.getSnippet();
((TextView)v.findViewById(R.id.info_window_nombre)).setText("Lina Cortés");
((TextView)v.findViewById(R.id.info_window_placas)).setText("Placas: SRX32");
((TextView)v.findViewById(R.id.info_window_estado)).setText("Estado: Activo");
return v;
}
#Override
public View getInfoContents(Marker marker) {
return null;
}
}
set googlemap:
myGoogleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(LayoutInflater.from(getActivity())));
Store markers in Hashmap by Using the marker key. Then use the Custom infowindow using hashmap object to retrieve the others information.
When you will click marker it will show the related information.
or you can watch this video from 8:00 on wards.
Click Here
So I've just made a CustomInfoWindow for my app. Here's how you can achieve this.
First Create a method in your database file just to access all the data related to your marker and the code is as follows:
Cursor getDetails(Marker marker){
db = getReadableDatabase();
String query = "select Name, Email, Address from YourTableName where Name = '"+marker.getTitle()+"';";
return db.rawQuery(query,null);
}
Then tune your AdaptadorInforWindow's code as follows:
YourDatabaseClass db = new YourDatabaseClass(context);
Cursor c = db.getDetails(); //Method you'll create in database class
((TextView)v.findViewById(R.id.info_window_name)).setText(c.getString(0));
((TextView)v.findViewById(R.id.info_window_email)).setText(c.getString(1));
((TextView)v.findViewById(R.id.info_window_address)).setText(c.getString(2));
c.close();
See, getString is used because I guess you've used Text/String datatype to store your Name, Email and Address Values. Remember if datatype changes, then you have to use the appropriate method as c.getInt(index) for int and so on.
Also, Indices 0,1,2 are same as in query: Name Email Address.
This way you'll have your data shown in your CustomInfoWindow.
Same is working in mine superbly and I'm pretty sure this will work.
Related
I am trying to display list of users from an online database
id username
1 aaaaa
2 bbbbb
3 ccccc
I'm getting the above result, now I want to add another column/TextView besides those username, perhaps firstname, or lastname,
id username lastname
1 aaaaa please
2 bbbbb help
3 ccccc me
I believe this part of the code populates the ListView
private void showEmployee(){
JSONObject jsonObject = null;
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String, String>>();
try {
jsonObject = new JSONObject(JSON_STRING);
JSONArray result = jsonObject.getJSONArray(Config.TAG_JSON_ARRAY);
for(int i = 0; i<result.length(); i++){
JSONObject jo = result.getJSONObject(i);
String id = jo.getString(Config.TAG_ID);
String username = jo.getString(Config.TAG_UNAME);
//String firstname = jo.getString(Config.TAG_FNAME);
HashMap<String,String> employees = new HashMap<>();
employees.put(Config.TAG_ID,id);
employees.put(Config.TAG_UNAME,username);
// employees.put(Config.TAG_UNAME,username);
list.add(employees);
}
} catch (JSONException e) {
e.printStackTrace();
}
ListAdapter adapter = new SimpleAdapter(
act_viewAllusers.this, list, R.layout.list_item,
new String[]{Config.TAG_ID,Config.TAG_UNAME},
new int[]{R.id.id, R.id.username});
/*** ListAdapter adapter = new SimpleAdapter(
act_viewAllusers.this, list, R.layout.list_item,
new String[]{Config.TAG_ID,Config.TAG_UNAME,Config.TAG_FNAME},
new int[]{R.id.id, R.id.username,R.id.fname}); ***/
listView.setAdapter(adapter);
}
I have a separate Java class named Config.java which contains some URLs and JSON tags which currently I can't really understand.
Here's some part of it
//JSON Tags
public static final String TAG_JSON_ARRAY="result";
public static final String TAG_ID = "id";
public static final String TAG_UNAME = "username";
public static final String TAG_PWORD = "password";
public static final String TAG_FNAME = "firstname";
public static final String TAG_LNAME = "lastname";
public static final String TAG_BDAY = "birthday";
public static final String TAG_GENDER = "gender";
Here's the XML for my ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http:// schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_marginRight="10dp"
android:id="#+id/id"
android:layout_width="40dp"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/fname"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/lname"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Another XML file for the ListView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_act_view_allusers"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.bayona.lesson1.act_viewAllusers">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listView" />
</LinearLayout>
Perhaps it's imposible to add another column or TextView; it's fine, but what bothers me is that I can't change the username displays.
For instance, I want to display lastname besides the id number
LinearLayout provides an android:weightSum attribute. You can set this to 4 to get even column distribution. Each TextView can be given a android:layout_weight and a android:width="0dp" in that case to fill the weight of the column.
Or you can use a GridLayout and put 4 cells in one row.
Or you can use a TableRow.
Point being, you have options. However, you shouldn't think of a ListView as a "spreadsheet". You can make each "row" as complex as you want.
Personally, maybe something like this in each row.
ID Username
Lastname, FirstName
Or don't even show the id and add # before the username...
Firstname Lastname
#Username
Just use the XML editor to create whatever layout you want.
As far as the Java code is concerned. You only have two values being set.
ListAdapter adapter = new SimpleAdapter(
act_viewAllusers.this,
list, // data
R.layout.list_item, // layout
new String[]{Config.TAG_ID,Config.TAG_UNAME}, // from[]
new int[]{R.id.id, R.id.username}); // to[]
So, you add more strings into the from array which are set into the XML id's in the to array from that layout.
Try Like This
ListAdapter adapter = new SimpleAdapter(
act_viewAllusers.this, list, R.layout.list_item,
new String[]{Config.TAG_ID,Config.TAG_UNAME,
Config.NextTAg,Config.NextTag2},
new int[]{R.id.id, R.id.username,R.id.id1,R.id.id2});
Check this if not done
try {
jsonObject = new JSONObject(JSON_STRING);
JSONArray result = jsonObject.getJSONArray(Config.TAG_JSON_ARRAY);
for(int i = 0; i<result.length(); i++){
JSONObject jo = result.getJSONObject(i);
String id = jo.getString(Config.TAG_ID);
String username = jo.getString(Config.TAG_UNAME);
//-----------------
String varName=jo.getString(Config.REQ_TAG);
//-------------
//String firstname = jo.getString(Config.TAG_FNAME);
HashMap<String,String> employees = new HashMap<>();
employees.put(Config.TAG_ID,id);
employees.put(Config.TAG_UNAME,username);
//--------------
employees.put(Config.REQ_TAG,varName);
//-----------
// employees.put(Config.TAG_UNAME,username);
list.add(employees);
}
I am using the following to show a corresponding marker image based on the returned business name using Google Places and Maps:
if (name.contains("walmart")) {
mIcon = R.drawable.ic_wm_poi;
} if (name.contains("speedco")) {
mIcon = R.drawable.ic_poi_speedco;
}
The logcat shows "Unkown icon: business name" which does correspond with one of my if statements but doesn't show the corresponding icon. I've tried using if/else and switch statements. I've also tried name.contains, name.equals and name.contentEquals. For example, if I search "Walmart", the response returns the business name "Walmart" as shown in the logcat, and the marker shows the name "Walmart" once clicked yet the corresponding icon doesn't show. I am setting the marker icon like so:
markerOptions.icon(BitmapDescriptorFactory.fromResource(markerIcon(placeName)));
EDIT
After implementing crickets' comment, the icons for the various locations still don't show. This is what I have:
public class MarkerIcons {
public static HashMap<String, Integer> poiIcons;
public static HashMap<String, Integer> getpoiIcons(){
poiIcons = new HashMap<>();
poiIcons.put("Walmart", R.drawable.ic_wm_poi);
poiIcons.put("Walmart Supercenter", R.drawable.ic_wm_poi);
poiIcons.put("Walmart Neighborhood Market", R.drawable.ic_wm_poi);
return poiIcons;
}
public static Integer markerIcon(String name){
String TAG_MI = "marker";
Log.d(TAG_MI, "Loc Name: " + name);
int mIcon = 0;
if(getpoiIcons().containsKey(name)){
mIcon = getpoiIcons().get(name).intValue();
return mIcon;
}else{
mIcon = R.drawable.default_marker;
return mIcon;
}
}
}
How I am calling these functions:
Get Place Class
public class GetNearbyBusinessData extends AsyncTask<Object, String, String> {
private String TAG = "getplace";
private String googlePlacesData;
private GoogleMap mMap;
private String url;
#Override
protected String doInBackground(Object... params) {
try {
Log.d(TAG, "doInBackground entered");
mMap = (GoogleMap) params[0];
url = (String) params[1];
DownloadUrl downloadUrl = new DownloadUrl();
googlePlacesData = downloadUrl.readUrl(url);
Log.d(TAG, "doInBackground Exit");
} catch (Exception e) {
Log.d(TAG, e.toString());
}
return googlePlacesData;
}
#Override
protected void onPostExecute(String result) {
Log.d(TAG, "onPostExecute Entered");
List<HashMap<String, String>> nearbyPlacesList;
DataParser dataParser = new DataParser();
nearbyPlacesList = dataParser.parse(result);
ShowNearbyBusiness(nearbyPlacesList);
Log.d(TAG, "onPostExecute Exit");
Log.d(TAG, result);
}
private void ShowNearbyBusiness(List<HashMap<String, String>> nearbyPlacesList) {
for (int i = 0; i < nearbyPlacesList.size(); i++) {
Log.d(TAG,"Entered into showing business");
MarkerOptions markerOptions = new MarkerOptions();
HashMap<String, String> googlePlace = nearbyPlacesList.get(i);
double lat = Double.parseDouble(googlePlace.get("lat"));
double lng = Double.parseDouble(googlePlace.get("lng"));
String placeName = googlePlace.get("place_name");
String vicinity = googlePlace.get("vicinity");
LatLng latLng = new LatLng(lat, lng);
markerOptions.position(latLng);
markerOptions.title(placeName + "-" + vicinity);
markerOptions.icon(BitmapDescriptorFactory.fromResource(markerIcon(placeName)));
mMap.addMarker(markerOptions);
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
}
}
EDIT 2
After setting break points for the markerIcon method and the line that calls the markerIcon method, the debug log shows that the returned response string is in fact "Walmart". Which is matching the key value in the HashMap. The returned icon for the marker is being returned as "0" though. It isn't returning the "value" from the hash map. I am setting the marker icon using this line:
mIcon = getpoiIcons().get(name).intValue();
Given the options available, I assumed that getting the matching "key" (in this case the string "name") would return its int "value". Am I missing something?
Even though the logcat shows the returned business names of Walmart, Walmart Supercenter and Walmart Neighborhood Market, it still shows the default marker. I have no idea why it is not showing the correct marker icon. Also, if it helps, my marker icons are vector images.
I think every thing work fine. but the error is, so far i have seen your code is,
markerOptions.icon(BitmapDescriptorFactory.fromResource(markerIcon(placeName)));
what you want to do is,
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(markerIcon(placeName)));
markerOptions.icon(icon);
Hope it helps.
U have function in separate class try this
MarkerIcons.markerIcon(placeName))
or update me if ur problem is cleared.
After trying the answers that were given and attempting to debug my code to find what was wrong, I found the error.
For anyone else that may have the same issue of the marker icons not showing, through trial and error I had found that you cannot use vector images that are in xml format as your markers. Once I switched them all over to png files, every icon showed without flaw.
Hope this answer helps someone else in the future. Thank you everyone for your contributions.
I'm having a hard time dealing with info window of google maps.
Everything goes fine until I try to add info in a loop! I'm just not able to add info in a Loop and display it in the Info Window. This is a custom info window which I inflate from a layout xml file. I have successfully managed to add multiple markers in the loop(I receive jsonarray with information and add markers in the loop with received longitude and latitude). the problem is that Google maps takes only 2 kinds of strings which are the Title and the Snippet, but I have 5 pieces of information blogs to put in the info window,so how can I do it? By default I cant add image to infowindow thats the purpose for me to create my custom info window. (I'll post code of a loop and of an info window)
public void addpaqs(){
try {
JSONArray array = new JSONArray(paqsresponse);
for (int i = 0; i < array.length(); i++) {
JSONObject row = array.getJSONObject(i);
tolongitude = row.getString("to_longitude");
tolatitude = row.getString("to_latitude");
creatorfirstname = row.getString("creator_first_name");
creatorlastname = row.getString("creator_last_name");
paqtype = row.getString("paq_type");
startdate = row.getString("start_date");
enddate=row.getString("end_date");
fromplace = row.getString("from_country");
toplace = row.getString("to_country");
fromcity =row.getString("from_city");
tocity = row.getString("to_city");
String price = row.getString("price");
double tolongdouble = Double.parseDouble(tolongitude);
double tolatdouble = Double.parseDouble(tolatitude);
MarkerOptions options = new MarkerOptions();
options.position(new LatLng(tolatdouble, tolongdouble));
options.Price(price);
options.icon(BitmapDescriptorFactory.fromResource(R.drawable.paqqyinactive));
options.snippet(creatorfirstname+creatorlastname);
map2.addMarker(options);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
inside the loop with method of addpaqs()
and now my custom infowindow
addpaqs();
map2.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
// Setting up the infoWindow with current's marker info
//infoSnippet.setText(marker.getSnippet());
infoButtonListener.setMarker(marker);
firstnamelastname.setText(marker.getPrice());
Log.d("firstnamelastname",marker.getPrice().toString());
// We must call this to set the current marker and infoWindow references
// to the MapWrapperLayout
mapWrapperLayout.setMarkerWithInfoWindow(marker, infoWindow);
return infoWindow;
}
});
enter code here
enter code here
here i call addpaqs,and later i just dont know what to do with it!:(
EDIT:
my custom info window(how do i set up it)
private ViewGroup infoWindow;
this.infoWindow = (ViewGroup) getLayoutInflater().inflate(R.layout.infowindow, null);
this.firstnamelastname = (TextView) infoWindow.findViewById(R.id.firstnamelastname);
this.infoButton = (Button) infoWindow.findViewById(R.id.button);
Ok, I got a simple example working. The overall idea here is to use a wrapper class to store the data for each Marker, and then keep the data stored in a HashMap with the Marker ID as the key so that you can obtain it in the InfoWindowAdapter.
First, create a holder class for the info corresponding to each Marker (you can expand on this to include more info as needed):
public class MarkerHolder {
public String startdate;
public String enddate;
public String fromplace;
public String toplace;
public MarkerHolder(String sd, String ed, String fp, String tp) {
startdate = sd;
enddate = ed;
fromplace = fp;
toplace = tp;
}
}
Then create a HashMap<String, MarkerHolder> that will map each Marker ID to the info for each Marker, and make it an instance variable:
HashMap<String, MarkerHolder> markerHolderMap = new HashMap<String, MarkerHolder>();
Here is a simplified example of just adding one Marker, note where the info is added to the HashMap with the Marker ID as the key:
public void addpaqs() {
//Simple example with just one Marker:
String creatorfirstname = "creator_first_name";
String creatorlastname = "creator_last_name";
String paqtype = "paq_type";
String startdate = "start_date";
String enddate = "end_date";
String fromplace = "from_country";
String toplace = "to_country";
String fromcity = "from_city";
String tocity = "to_city";
//String price = row.getString("price");
double tolongdouble = -122.417506;
double tolatdouble = 37.77657;
MarkerOptions options = new MarkerOptions();
options.position(new LatLng(tolatdouble, tolongdouble));
//options.Price(price);
//options.icon(BitmapDescriptorFactory.fromResource(R.drawable.paqqyinactive));
options.title(paqtype);
options.snippet(creatorfirstname + " " + creatorlastname);
Marker marker = mGoogleMap.addMarker(options);
MarkerHolder mHolder = new MarkerHolder(startdate, enddate, fromplace, toplace);
markerHolderMap.put(marker.getId(), mHolder); //Add info to HashMap
}
Here is the custom layout xml for the InfoWindow, you can expand on this as needed:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:orientation="vertical"
android:background="#d3d3d3">
<TextView
android:id="#+id/paq"
android:textColor="#D3649F"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/names"
android:textColor="#D3649F"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/dates"
android:textColor="#D3649F"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/places"
android:textColor="#D3649F"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Then, put it all together, here is the InfoWindowAdapter. Note that I used the Title and the Snippet stored in the Marker, but also used info obtained from the MarkerHolder which was obtained from the HashMap:
mGoogleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker arg0) {
View v = getLayoutInflater().inflate(R.layout.customlayout2, null);
TextView tLocation = (TextView) v.findViewById(R.id.paq);
TextView tSnippet = (TextView) v.findViewById(R.id.names);
TextView tDates = (TextView) v.findViewById(R.id.dates);
TextView tPlaces = (TextView) v.findViewById(R.id.places);
//These are standard, just uses the Title and Snippet
tLocation.setText(arg0.getTitle());
tSnippet.setText(arg0.getSnippet());
//Now get the extra info you need from the HashMap
//Store it in a MarkerHolder Object
MarkerHolder mHolder = markerHolderMap.get(arg0.getId()); //use the ID to get the info
tDates.setText(mHolder.startdate + " " + mHolder.enddate);
tPlaces.setText(mHolder.fromplace + " " + mHolder.toplace);
return v;
}
});
Result:
I was looking for a solution to my problem, i found some info here but i couldn't make it work with my code.
So, i have a google map with markers. The markers are created with JSON information. What i want is to attach a custom value to each marker, so each time a user touches the infowindow, a new activity will open with passed parameters attached to the specific marker.
Here is the JSON parsing and marker creation:
try{
JSONArray jArray = new JSONArray(result);
for(int i=0; i < jArray.length(); i++) {
JSONObject jObject = jArray.getJSONObject(i);
String image = jObject.getString("image");
String title = jObject.getString("title");
String snipet = jObject.getString("snipet");
double lat=jObject.getDouble("lat");
double lng=jObject.getDouble("lng");
addMarkers(lat, lng,image,title,snipet);
} // End Loop
} catch (JSONException e) {
Log.e("JSONException", "Error: " + e.toString());
} // catch (JSONException e)
private void addMarkers( double jLat, double jLng, final String image, final String jTitle,final String jDescription)
{
LatLng jLocation = new LatLng(jLat, jLng);
alertMarkers = theMap.addMarker(new MarkerOptions()
.position(jLocation)
.title(jTitle)
.snippet(jDescription)
.icon(BitmapDescriptorFactory.fromResource(icon)));
theMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker arg0) {
Toast.makeText(MainActivity.this, arg0.getId(), 1000).show();
}}
}
How can assign that extra parameter, i.e image,to the marker so when a user touches the marker, the corresponding image will be used for further processing.
Thanks.
EDIT:
Here what i added to the code above,but something is not right:
Declared at start
HashMap<String, HashMap> extraMarkerInfo = new HashMap<String, HashMap>();
then added a new HashMap:
*alertMarkers = theMap.addMarker(new MarkerOptions()
.position(jLocation)
.title(jTitle)
.snippet(jDescription)
.icon(BitmapDescriptorFactory.fromResource(icon)));*
HashMap<String, Integer> data = new HashMap<String, Integer>();
data.put("id",alertID);
extraMarkerInfo.put(alertMarkers.getId(),data);
public void onInfoWindowClick(Marker arg0) {
HashMap<String, String> marker_data = extraMarkerInfo.get(arg0.getId());
Log.i("test",marker_data.get("id"));
(…)
But i am getting an error :
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at line:
HashMap<String, String> marker_data = extraMarkerInfo.get(arg0.getId());
I am bit confused with HashMaps.
You can maintain your own HashMap<>, mapping the ID value of the Marker (generated by the system, immutable) to its corresponding extra data. Then, on a marker tap, you look up the extra data. You can see this in action in this sample project.
Or, you can shove the string representation of the data (JSON) into the snippet of the Marker, and retrieve it again later on as needed. This will be more overhead, I suspect.
Marker, however, is final and cannot be extended.
I'm creating a view that displays data that is parsed from a plist (XML) file. My parsing routine stores the data as an Object in a hashmap that I later retrieve with a key. My textview does display the data, but it does not process the \n into line breaks. Instead, the \n displays along with the text. Here is the code I use to retrieve my data from the hashmap:
String contactData = dict.get("Data").toString();
I have tried variations without success:
Object obj = dict.get("Data");
String contactData = obj.toString();
and
contactData = (String)dict.get("Data");
My text is lengthy with \n imbedded to force line breaks. I set my text as follows:
TextView data = (TextView) getActivity().findViewById(R.id.data);
data.setText(contactData);
Here is my layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/light_grey"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/midnight_blue"
android:gravity="center"
android:text="Contacts"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/white"
android:textStyle="bold" />
<TextView
android:id="#+id/country"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:gravity="center"
android:textColor="#color/midnight_blue"
android:textSize="16dp" />
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="#color/white"
android:gravity="center"
android:textColor="#color/midnight_blue"
android:textSize="16dp" />
<TextView
android:id="#+id/data"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:gravity="center"
android:singleLine="false"
android:textColor="#color/black"
android:textSize="12dp"
android:text="Line one\nLine two\nLine3"/>
\n works fine if I hard code the text to my variable (contactData) or I use the default text in the layout XML file. It does not work when I convert my object data toString??
Please do not suggest converting to \r\n. \n is the line separator. I've gone down that line in a previous question and it wasn't the resolution. The following code returns \n:
System.getProperty("line.separator");
My problem is related to how I'm retrieving my text from the hashmap and converting it to String. Any thoughts or suggestions would be appreciated!!!
* Update
Here is my parse routine for the plist file:
public void parse(InputStream inputStream) throws XmlPullParserException, IOException {
final XmlPullParserFactory xppf = XmlPullParserFactory.newInstance();
final XmlPullParser parser = xppf.newPullParser();
parser.setInput(inputStream, null);
final Stack<List<Map<String, Object>>> arrayStack = new Stack<List<Map<String, Object>>>();
final Stack<Map<String, Object>> dictStack = new Stack<Map<String, Object>>();
final Stack<String> keyStack = new Stack<String>();
int eventType = parser.getEventType();
boolean done = false;
while (!done) {
final String name = parser.getName();
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
if ("array".equalsIgnoreCase(name)) {
final List<Map<String, Object>> array = new ArrayList<Map<String,Object>>();
arrayStack.push(array);
} else if ("dict".equalsIgnoreCase(name)) {
final Map<String, Object> dict = new HashMap<String, Object>();
dictStack.push(dict);
} else if ("key".equalsIgnoreCase(name)){
keyStack.push(parser.nextText()); // assign current key
} else if ("string".equalsIgnoreCase(name)) {
final Map<String, Object> dict = dictStack.peek();
final String string = parser.nextText();
final String key = keyStack.pop();
dict.put(key, string);
} else if ("integer".equalsIgnoreCase(name)) {
final Map<String, Object> dict = dictStack.peek();
final String integerStr = parser.nextText();
final Integer integer = new Integer(integerStr);
final String key = keyStack.pop();
dict.put(key, integer);
} else if ("false".equalsIgnoreCase(name)) {
final Map<String, Object> dict = dictStack.peek();
final Boolean booleanValue = new Boolean(false);
final String key = keyStack.pop();
dict.put(key, booleanValue);
} else if ("true".equalsIgnoreCase(name)) {
final Map<String, Object> dict = dictStack.peek();
final Boolean booleanValue = new Boolean(true);
final String key = keyStack.pop();
dict.put(key, booleanValue);
}
break;
case XmlPullParser.END_TAG:
if ("array".equalsIgnoreCase(name)) {
final List<Map<String, Object>> array = arrayStack.pop();
if (arrayStack.isEmpty()) {
// return array;
mPlistHashMap.put("array",array);
break;
}
// If not end of array, means it's an array within a dict
final String key = keyStack.pop();
dictStack.peek().put(key, array);
} else if ("dict".equalsIgnoreCase(name)) {
final Map<String, Object> dict = dictStack.pop();
if (!arrayStack.empty())
arrayStack.peek().add(dict);
else
mPlistHashMap = dict;
}
break;
case XmlPullParser.END_DOCUMENT:
done = true;
break;
}
eventType = parser.next();
}
}
My plist consists of an Array of Dictionary items with three strings. Here is a snippet of my plist XML file:
<array>
<dict>
<key>Country</key>
<string>Mexico</string>
<key>Name</key>
<string>Mexico City</string>
<key>Data</key>
<string>Line one\nLine two\nLine three</string>
</dict>
Wrap your text in and use actual newlines. Then the parser should give you the data exactly as written. Something like:
<array>
<dict>
<key>Country</key>
<string>Mexico</string>
<key>Name</key>
<string>Mexico City</string>
<key>Data</key>
<string>
<![CDATA[
Line one
Line two
Line three
]]>
</string>
</dict>
</array>
Thanks to Nikolay's suggestions, I discovered that my text was somehow embedding and extra backslash to my line break character. So my text had "\n" instead of "\n". I had tried using .replaceAll("\n","\n"), but for some reason that was not working. Here is the code that worked for me:
contactData = dict.get("Data").toString().replace("\\n", "\n");