Wednesday 13 July 2011

How to search a list of places by keyword and display them with custom icons

What I need: let the user search for a place by name and display the search results obtained on a Map.

I won't go into the details of the layout and focus on the map aspect. The interface looks like this:


The user enters the place he is looking for and the application pulls available location matching the name, displays them in a list and on the map. To link the list and the icons items, numbers are used.
There are two challenges here:
1) get the list of places matching the name
2) render the icons on the map with a number

Getting the list of places is achieved thanks to GeoCoder with this simple snippet of code:

Geocoder geoCoder = new Geocoder(this, Locale.getDefault());
        try {
            List<Address> places = geoCoder.getFromLocationName(locationName, 10);
        } catch (IOException e) {                
            e.printStackTrace();
            Utils.alert(this, "Could not retrieve locations, do you have an Internet connection running?");
        }   


We need to add some code to fill the list and add the icons to the Map.

Geocoder geoCoder = new Geocoder(this, Locale.getDefault());
        try {
            List<Address> places = geoCoder.getFromLocationName(locationName, 10);
            placesList.setAdapter(new AddressesAdapter(this, places));
            // add places to the map
         // clear previous overlays
            List<Overlay> listOfOverlays = mapView.getOverlays();
            if(listOfOverlays != null) {
                listOfOverlays.clear();
                mapView.invalidate();
            }
            // add place markers
            ArrayList<GeoPoint> points = new ArrayList<GeoPoint>();
            int index = 0;
            for(Address address : places) {
                Marker marker = new Marker(this, address, index++);
                listOfOverlays.add(marker);
            }
        } catch (IOException e) {                
            e.printStackTrace();
            Utils.alert(this, "Could not retrieve locations, do you have an Internet connection running?");
        }   

We create our own adapter to display the places in the list. Essentially this adapter builds the name of the place and appends a number to it. To build the place name, use the following:

int length = addresses.get(position).getMaxAddressLineIndex();
     String add = position + ") ";
            for (int i = 0; i < length; i++) {
             String line = addresses.get(position).getAddressLine(i);
             if(line != null) {
                 add += line;
                 if(i != length - 1) {
                  add += ", ";
                 }
             }
            }
The markers are displayed by using our own Marker class that extends the Overlay class. The draw method is overriden to use our own bitmap and draw the index number in the middle of the canvas.
@Override
    public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) 
    {
        super.draw(canvas, mapView, shadow);                   

        //---translate the GeoPoint to screen pixels---
        Point screenPts = new Point();
        mapView.getProjection().toPixels(this.geoPoint, screenPts);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(bitmap.getHeight() / 2);
        paint.setColor(Color.DKGRAY);
        paint.setTextAlign(Align.CENTER);
        //---add the marker---
        canvas.drawBitmap(bitmap, screenPts.x - bitmap.getWidth() / 2, screenPts.y - bitmap.getHeight(), null);         
        canvas.drawText(index + "", screenPts.x, screenPts.y - bitmap.getHeight() / 2, paint);
        return true;
    }


One last word on testing. Just a small tip on how to test the location with the android avd. In Eclipse go to windows->open perspective->other->ddms. Go to the emulator control panel on the right and scroll down for location controls! Otherwise you can telnet your avd (while running) by using telnet localhost 5554, once logged in send the command geo fix 'yourlat' 'yourlong'.

This concludes the series on Compastic! Remember the full code is available @ http://code.google.com/p/compastic/ and the app is on the Android Market @ https://market.android.com/details?id=com.metaaps.mobile.compastic&feature=search_result

No comments:

Post a Comment