Как стать автором
Обновить

Написание MarkerInfoWindow для osmdroid

Время на прочтение 7 мин
Количество просмотров 5.9K
Статья предназначена для тех, у кого трудности с подключением infoWindow в osmdroid и работой с AsyncTask и просто для тех, кто раньше не делал ничего подобного. Здесь я писал о том, как я создавал окошко для получения данных об автомобиле в сервисе мониторинга транспорта.
Суть в том, что при нажатии на маркер, некоторые данные берутся из объекта, другие данные подгружаются из API, записываются в БД приложения, после чего отображаются в объекте InfoWindow.

Начинаем с создания xml файла с описанием infoWindow, добавляем поля с заголовками критериев транспорта.

image
MarkerInfoWindow позволяет записывать в Title, Description, Subdescription, я использовал только Descripton для всех нужных записей. Будем впоследствии передавать туда данные в виде строки с переносами.

Разметка выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@drawable/balloon_overlay_white" >
    <ImageView android:id="@+id/bubble_image"
        android:layout_width="65dp"
        android:layout_height="65dp"
        android:visibility="gone" />
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:orientation="vertical" >
            <TextView android:id="@+id/bubble_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#000000"
                android:maxEms="17"
                android:layout_gravity="left"
                android:layout_weight="1"
                android:text="Title"
                android:textSize="18dp"
                android:textIsSelectable="false" />
            <Button android:id="@+id/bubble_moreinfo"
                android:background="@drawable/btn_moreinfo"
                android:visibility="gone"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:layout_weight="0" />
        <TextView android:id="@+id/bubble_description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14dp"
            android:maxEms="17"
            android:text="Description"
            android:layout_toRightOf="@+id/model"
            android:layout_below="@+id/bubble_title"
            android:lineSpacingExtra="3dp"
            android:layout_marginLeft="3dp" />
        <TextView android:id="@+id/model"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff6c6c6c"
            android:textSize="14dp"
            android:maxEms="17"
            android:text="@string/model"
            android:layout_below="@+id/bubble_title"
            android:layout_alignRight="@+id/organization" />
        <TextView android:id="@+id/group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff6c6c6c"
            android:textSize="14dp"
            android:maxEms="17"
            android:text="@string/group"
            android:layout_below="@+id/model"
            android:layout_alignRight="@+id/organization" />
        <TextView android:id="@+id/organization"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff6c6c6c"
            android:textSize="14dp"
            android:maxEms="17"
            android:text="@string/organization"
            android:layout_below="@+id/group" />
        <TextView android:id="@+id/speed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff6c6c6c"
            android:textSize="14dp"
            android:maxEms="17"
            android:text="@string/speed"
            android:layout_below="@+id/organization"
            android:layout_alignRight="@+id/organization" />
        <TextView android:id="@+id/update"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ff6c6c6c"
            android:textSize="14dp"
            android:maxEms="17"
            android:text="@string/update"
            android:layout_below="@+id/speed"
            android:layout_alignRight="@+id/organization" />
        <TextView android:id="@+id/bubble_subdescription"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:textSize="10dp"
            android:maxEms="17"
            android:text="Address"
            android:layout_below="@+id/update" />
    </RelativeLayout>
</LinearLayout>



Далее, для отображения нужных данных, пишем свой класс CarInfoWindow:
public class CarInfoWindow extends MarkerInfoWindow {

    Car mCar;
    Marker mMarker;
    CarInfoTask carInfoTask;
    Boolean stopped = false;
    Drawable icon;
    String active;

    public CarInfoWindow(int layoutResId, MapView mapView) {
        super(layoutResId, mapView);
    }
    //при открытии запускаем asyncTask
    @Override
    public void onOpen(final Object item) {
        if (!stopped) {
            carInfoTask = new CarInfoTask();
            carInfoTask.execute(item);
        }
        super.onOpen(item);
    }
    //при закрытии можем поменять иконку маркера
    @Override
    public void onClose() {
        stopped = false;
        super.onClose();

        if (!(mCar.getLastUpdate() == null)) {
            if (((System.currentTimeMillis() - Long.parseLong(mCar.getLastUpdate())) / 3600000) > 1) {
                active = "0"; //car is not active
            }
            else {
                active = "1";
            }
        }
        String fileName = Environment.getExternalStorageDirectory()+"/automap/cars/icons/"+mCar.getIconIndex()+"/"+active+"/icon.png";
        icon = Utils.loadIcon(fileName, Float.parseFloat(mCar.getDirection()), mCar.getIconType());
        mMarker.setIcon(icon);
    }

	
    class CarInfoTask extends AsyncTask<Object, String, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

		
        @Override
        //операции по обработке данных производятся в этом методе
        protected Void doInBackground(Object... params) {
            try {
		//задаем нужный маркер, к которому привязан объект Car с нужными данными
                mMarker = (Marker)params[0];
                mCar = (Car) mMarker.getRelatedObject();
		//Данные, которые нужно передать в infoWindow
                String markName;
                String carModelName;
                String groupName;
                String carLastUpdate;
                Context context = getView().getContext();

                //берем token, и данные из объекта
                Token token = Prefs.getToken(getView().getContext());
                String markId = mCar.getMarkId();
                String modelId = mCar.getModelId();
                String orgId = mCar.getOrganizationId();
                String groupId = mCar.getGroupId();
                carLastUpdate = mCar.getLastUpdate();

		//что-нибудь делаем
                String formattedDate = "";
                if (!(carLastUpdate == null)) {
                    long unixSeconds = Long.parseLong(carLastUpdate);
                    Date date = new Date(unixSeconds);
                    SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy  HH:mm:ss ");
                    formattedDate = sdf.format(date);
                }

                String organizationName = DbHelper.getInstance(context).getOrganizationStatById(orgId).getName();
                List<Mark> marksList = null;
                List<CarModel> carModelsList = null;
                List<Group> groupsList = null;
				
                //делаем запрос в API, берем mark и model по id
                try {
                    //используем retrofit
                    carModelsList = Api.getService(context).getModels(token.getValue(), markId); 
                    int size = carModelsList.size();
                    for (int i=0; i<size; i++) {
                        //используем cupboard для сохранения данных в БД
                        DbHelper.getInstance(context).insertCarModels(carModelsList.get(i)); 
                    }

                    groupsList = Api.getService(context).getGroups(token.getValue(), orgId);
                    size = groupsList.size();
                    for (int i=0; i<size; i++) {
                        DbHelper.getInstance(context).insertGroups(groupsList.get(i));
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
                markName = DbHelper.getInstance(context).getMarkById(markId).getName();
                carModelName = DbHelper.getInstance(context).getCarModelById(modelId).getName();
                groupName = DbHelper.getInstance(context).getGroupById(groupId).getName();
				
                //записываем нужные данные сюда для передачи в UI. 
                publishProgress(organizationName, markName, carModelName, groupName, formattedDate); 
				//values[0] = organizationName, values[1] = markName и т.д.

            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            //отображаем данные в textView, которые были переданые методом publishProgress()
            mMarker.hideInfoWindow();
            mMarker.setTitle(mCar.getCarNo() + " (" + values[1] + ")");
            mMarker.setSnippet(
                    values[2] + "\n" +
                    values[3] + "\n" +
                    values[0] + "\n" +
                    mCar.getSpeed() + "\n" +
                    values[4]
            );
            mMarker.setSubDescription("");

            //можем поменять иконку маркера
            String fileName = Environment.getExternalStorageDirectory()+"/automap/cars/icons/"+mCar.getIconIndex()+"/2/icon.png";
            icon = Utils.loadIcon(fileName, Float.parseFloat(mCar.getDirection()), mCar.getIconType());
            mMarker.setIcon(icon);
        }
        //метод, в котором мы останавливаем asyncTask
        @Override
        protected void onPostExecute(Void result) {
            stopped = true;
            mMarker.showInfoWindow();
            super.onPostExecute(result);
        }
    }
}



Теперь при создании маркера остается всего лишь к маркеру привязать нужное окно

marker.setInfoWindow(infoWindow);


В результате проделанных манипуляций получаем нечто вроде:

image

P.S. Несмотря на то, что маркер — иконка грузовика, а в описании это Alfa Romeo, всё работает верно.
Теги:
Хабы:
-3
Комментарии 6
Комментарии Комментарии 6

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн