@@ -39,40 +39,44 @@ public class YandexMapImpl implements MapInterface {
private boolean ownVesselClickListenerSet = false ;
private Map < String , Boolean > aisVesselClickListenersSet = new HashMap < > ( ) ;
// Флаги для предотвращения повторного добавления обработчиков
private Map < String , Boolean > aisVesselClickListenersAdded = new HashMap < > ( ) ;
// Слушатель поворота карты
private com . yandex . mapkit . map . InputListener inputListener ;
private float lastMapAzimuth = 0 . 0f ;
// Отслеживание двойного клика для AIS судов
private Map < String , Long > lastClickTime = new HashMap < > ( ) ;
private static final long DOUBLE_CLICK_DELAY = 300 ; // 300мс для двойного клика
public YandexMapImpl ( Context context , MapView mapView ) {
this . context = context ;
this . mapView = mapView ;
this . aisMarkers = new HashMap < > ( ) ;
this . aisVessels = new HashMap < > ( ) ;
android . util . Log . d ( " YandexMapImpl " , " Конструктор YandexMapImpl вызван " ) ;
android . util . Log . d ( " YandexMapImpl " , " Context: " + ( context ! = null ? " установлен " : " null " ) ) ;
android . util . Log . d ( " YandexMapImpl " , " MapView: " + ( mapView ! = null ? " установлен " : " null " ) ) ;
// Получение коллекции объектов карты
try {
this . mapObjects = mapView . getMap ( ) . getMapObjects ( ) . addCollection ( ) ;
android . util . Log . d ( " YandexMapImpl " , " Коллекция объектов карты создана: " + ( mapObjects ! = null ? " успешно " : " null " ) ) ;
} catch ( Exception e ) {
android . util . Log . e ( " YandexMapImpl " , " Ошибка создания коллекции объектов карты: " + e . getMessage ( ) , e ) ;
// Ошибка создания коллекции объектов карты
}
}
@Override
public void initialize ( ) {
android . util . Log . d ( " YandexMapImpl " , " initialize() вызван " ) ;
android . util . Log . d ( " YandexMapImpl " , " mapObjects: " + ( mapObjects ! = null ? " установлен " : " null " ) ) ;
android . util . Log . d ( " YandexMapImpl " , " mapView: " + ( mapView ! = null ? " установлен " : " null " ) ) ;
android . util . Log . d ( " YandexMapImpl " , " context: " + ( context ! = null ? " установлен " : " null " ) ) ;
// Карта уже инициализирована в конструкторе
if ( mapObjects ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Коллекция объектов карты готова к использованию " ) ;
}
// Инициализируем слушатель поворота карты
setupCameraListener ( ) ;
}
@Override
public void cleanup ( ) {
// Удаляем слушатель ввода
if ( inputListener ! = null & & mapView ! = null ) {
mapView . getMap ( ) . removeInputListener ( inputListener ) ;
}
if ( mapObjects ! = null ) {
mapView . getMap ( ) . getMapObjects ( ) . remove ( mapObjects ) ;
}
@@ -83,151 +87,123 @@ public class YandexMapImpl implements MapInterface {
@Override
public void addOwnVesselMarker ( Vessel vessel ) {
android . util . Log . d ( " YandexMapImpl " , " addOwnVesselMarker вызван: lat= " + vessel . getLatitude ( ) + " , lon= " + vessel . getLongitude ( ) + " , course= " + vessel . getCourse ( ) + " ° " ) ;
// Сохраняем ссылку на судно
this . ownVessel = vessel ;
// Проверяем координаты
if ( vessel . getLatitude ( ) = = 0 . 0 & & vessel . getLongitude ( ) = = 0 . 0 ) {
android . util . Log . w ( " YandexMapImpl " , " Координаты равны 0,0 - маркер не будет создан " ) ;
// Проверяем валидность координат (исключаем только невалидные значения)
if ( Double . isNaN ( vessel . getLatitude ( ) ) | | Double . isNaN ( vessel . getLongitude ( ) ) | |
Double . isInfinite ( vessel . getLatitude ( ) ) | | Double . isInfinite ( vessel . getLongitude ( ) ) ) {
return ;
}
if ( ownVesselMarker ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Удаляем существующий маркер " ) ;
mapObjects . remove ( ownVesselMarker ) ;
}
Point point = new Point ( vessel . getLatitude ( ) , vessel . getLongitude ( ) ) ;
android . util . Log . d ( " YandexMapImpl " , " Создаем Point: " + point ) ;
ownVesselMarker = mapObjects . addPlacemark ( point ) ;
android . util . Log . d ( " YandexMapImpl " , " Placemark создан: " + ( ownVesselMarker ! = null ? " успешно " : " null " ) ) ;
if ( ownVesselMarker = = null ) {
android . util . Log . e ( " YandexMapImpl " , " Не удалось создать Placemark! " ) ;
return ;
}
// Используем готовую иконку стрелки с учетом курса
android . util . Log . d ( " YandexMapImpl " , " Устанавливаем иконку стрелки с курсом: " + vessel . getCourse ( ) + " ° " ) ;
setMarkerIcon ( ownVesselMarker , " arrowship " , vessel . getCourse ( ) ) ;
// Используем готовую иконку стрелки с учетом курса (синий цвет для нашего судна)
setMarkerIcon ( ownVesselMarker , " target " , vessel . getCourse ( ) , android . graphics . Color . BLUE ) ;
// Устанавливаем размер иконки
android . util . Log . d ( " YandexMapImpl " , " Устанавливаем IconStyle... " ) ;
com . yandex . mapkit . map . IconStyle iconStyle = new com . yandex . mapkit . map . IconStyle ( ) ;
iconStyle . setScale ( 1 . 5f ) ; // У величиваем размер иконки
iconStyle . setScale ( 1 . 0f ) ; // У меньшаем масштаб иконки
ownVesselMarker . setIconStyle ( iconStyle ) ;
// Устанавливаем обработчик кликов только если он еще не установлен
if ( ! ownVesselClickListenerSet ) {
android . util . Log . d ( " YandexMapImpl " , " Устанавливаем обработчик клика для маркера... " ) ;
ownVesselMarker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по маркеру нашего судна! " ) ;
if ( markerClickListener ! = null & & ownVessel ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onOwnVesselClick " ) ;
markerClickListener . onOwnVesselClick ( ownVessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null или ownVessel == null! " ) ;
android . util . Log . d ( " YandexMapImpl " , " markerClickListener = " + ( markerClickListener ! = null ? " установлен " : " null " ) ) ;
android . util . Log . d ( " YandexMapImpl " , " ownVessel = " + ( ownVessel ! = null ? " установлен " : " null " ) ) ;
}
return true ;
} ) ;
ownVesselClickListenerSet = true ;
}
android . util . Log . d ( " YandexMapImpl " , " Маркер нашего судна создан и настроен, markerClickListener = " + ( markerClickListener ! = null ? " установлен " : " null " ) ) ;
// Проверяем, что маркер действительно добавлен в коллекцию
android . util . Log . d ( " YandexMapImpl " , " Маркер добавлен в коллекцию объектов карты " ) ;
}
@Override
public void updateOwnVesselPosition ( Vessel vessel ) {
android . util . Log . d ( " YandexMapImpl " , " updateOwnVesselPosition вызван: lat= " + vessel . getLatitude ( ) + " , lon= " + vessel . getLongitude ( ) + " , course= " + vessel . getCourse ( ) + " ° " ) ;
// Обновляем ссылку на судно
this . ownVessel = vessel ;
// Проверяем координаты
if ( vessel . getLatitude ( ) = = 0 . 0 & & vessel . getLongitude ( ) = = 0 . 0 ) {
android . util . Log . w ( " YandexMapImpl " , " Координаты равны 0,0 - обновление пропущено " ) ;
// Проверяем валидность координат (исключаем только невалидные значения)
if ( Double . isNaN ( vessel . getLatitude ( ) ) | | Double . isNaN ( vessel . getLongitude ( ) ) | |
Double . isInfinite ( vessel . getLatitude ( ) ) | | Double . isInfinite ( vessel . getLongitude ( ) ) ) {
return ;
}
if ( ownVesselMarker = = null ) {
// Создаем маркер нашего судна, если его еще нет
android . util . Log . d ( " YandexMapImpl " , " Создаем новый маркер нашего судна " ) ;
addOwnVesselMarker ( vessel ) ;
} else {
// Проверяем, нужно ли обновить курс
boolean needCourseUpdate = Math . abs ( vessel . getCourse ( ) ) > 0 . 1 ; // Если курс больше 0.1 градуса
if ( needCourseUpdate ) {
android . util . Log . d ( " YandexMapImpl " , " Обновляем курс маркера на " + vessel . getCourse ( ) + " ° " ) ;
// Обновляем только иконку с новым курсом
setMarkerIcon ( ownVesselMarker , " arrowship " , vessel . getCourse ( ) ) ;
}
// Всегда обновляем иконку с текущим курсом
// Обновляем иконку с новым курсом (синий цвет для нашего судна)
setMarkerIcon ( ownVesselMarker , " target " , vessel . getCourse ( ) , android . graphics . Color . BLUE ) ;
// Обновляем позицию маркера
Point newPoint = new Point ( vessel . getLatitude ( ) , vessel . getLongitude ( ) ) ;
ownVesselMarker . setGeometry ( newPoint ) ;
android . util . Log . d ( " YandexMapImpl " , " Позиция маркера обновлена на: " + newPoint ) ;
// Переустанавливаем обработчик клика после обновления маркера
if ( markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Переустанавливаем обработчик клика после обновления маркера " ) ;
// В Яндекс.Картах нет метода setTapListener(null), поэтому просто добавляем новый обработчик
ownVesselMarker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по маркеру нашего судна! " ) ;
if ( markerClickListener ! = null & & ownVessel ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onOwnVesselClick " ) ;
markerClickListener . onOwnVesselClick ( ownVessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null или ownVessel == null! " ) ;
}
return true ;
} ) ;
// Обработчик клика уже установлен при создании маркера, не добавляем повторно
}
}
android . util . Log . d ( " YandexMapImpl " , " Маркер нашего судна обновлен, ownVesselMarker = " + ( ownVesselMarker ! = null ? " создан " : " null " ) + " , markerClickListener = " + ( markerClickListener ! = null ? " установлен " : " null " ) ) ;
}
@Override
public void addAISVesselMarker ( AISVessel vessel ) {
android . util . Log . d ( " YandexMapImpl " , " addAISVesselMarker вызван: lat= " + vessel . getLatitude ( ) + " , lon= " + vessel . getLongitude ( ) + " , course= " + vessel . getCourse ( ) + " ° " ) ;
// Проверяем валидность координат (исключаем только невалидные значения)
if ( Double . isNaN ( vessel . getLatitude ( ) ) | | Double . isNaN ( vessel . getLongitude ( ) ) | |
Double . isInfinite ( vessel . getLatitude ( ) ) | | Double . isInfinite ( vessel . getLongitude ( ) ) ) {
return ;
}
Point point = new Point ( vessel . getLatitude ( ) , vessel . getLongitude ( ) ) ;
com . yandex . mapkit . map . PlacemarkMapObject marker = mapObjects . addPlacemark ( point ) ;
if ( marker = = null ) {
return ;
}
// Сохраняем ссылку на судно
aisVessels . put ( vessel . getMmsi ( ) , vessel ) ;
// Используем готовую иконку стрелки для AIS судов с учетом курса
setMarkerIcon ( marker , " arrowship " , vessel . getCourse ( ) ) ;
// Используем готовую иконку стрелки для AIS судов с учетом курса и цвета
int vesselColor = getVesselColor ( vessel ) ;
setMarkerIcon ( marker , " target " , vessel . getCourse ( ) , vesselColor , vessel . isSelected ( ) ) ;
// Устанавливаем размер иконки
com . yandex . mapkit . map . IconStyle iconStyle = new com . yandex . mapkit . map . IconStyle ( ) ;
iconStyle . setScale ( 1 . 5f ) ; // У величиваем размер иконки
iconStyle . setScale ( 1 . 0f ) ; // У меньшаем масштаб иконки
marker . setIconStyle ( iconStyle ) ;
// Установка обработчика кликов только если он еще не установлен
String mmsi = vessel . getMmsi ( ) ;
if ( ! aisVesselClickListenersSet . containsKey ( mmsi ) | | ! aisVesselClickListenersSet . get ( mmsi ) ) {
if ( ! aisVesselClickListenersAdded . containsKey ( mmsi ) | | ! aisVesselClickListenersAdded . get ( mmsi ) ) {
marker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по AIS маркеру: " + mmsi ) ;
if ( markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onAISVesselClick " ) ;
markerClickListener . onAISVesselClick ( vessel ) ;
// Проверяем двойной клик
long currentTime = System . currentTimeMillis ( ) ;
Long lastTime = lastClickTime . get ( mmsi ) ;
if ( lastTime ! = null & & ( currentTime - lastTime ) < DOUBLE_CLICK_DELAY ) {
// Двойной клик - вызываем BottomSheet
if ( markerClickListener ! = null ) {
markerClickListener . onAISVesselClick ( vessel ) ;
}
lastClickTime . remove ( mmsi ) ; // Сбрасываем для следующего двойного клика
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null! " ) ;
android . util . Log . d ( " YandexMapImpl " , " markerClickListener = " + ( markerClickListener ! = null ? " установлен " : " null " ) ) ;
// Одиночный клик - выделяем/снимаем выделение
toggleVesselSelection ( vessel ) ;
lastClickTime . put ( mmsi , currentTime ) ;
}
return true ;
} ) ;
aisVesselClickListenersSet . put ( mmsi , true ) ;
aisVesselClickListenersAdded . put ( mmsi , true ) ;
}
aisMarkers . put ( vessel . getMmsi ( ) , marker ) ;
@@ -243,27 +219,11 @@ public class YandexMapImpl implements MapInterface {
Point newPoint = new Point ( vessel . getLatitude ( ) , vessel . getLongitude ( ) ) ;
marker . setGeometry ( newPoint ) ;
// О бновляем курс маркера, если он изменился
if ( Math . abs ( vessel . getCourse ( ) ) > 0 . 1 ) {
android . util . Log . d ( " YandexMapImpl " , " Обновляем курс AIS маркера " + vessel . getMmsi ( ) + " на " + vessel . getCourse ( ) + " ° " ) ;
setMarkerIcon ( marker , " arrowship " , vessel . getCourse ( ) ) ;
}
// Всегда о бновляем курс маркера
int vesselColor = getVesselColor ( vessel ) ;
setMarkerIcon ( marker , " target " , vessel . getCourse ( ) , vesselColor , vessel . isSelected ( ) ) ;
// Переустанавливаем обработчик клика после обновления маркера
if ( markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Переустанавливаем обработчик клика для AIS маркера: " + vessel . getMmsi ( ) ) ;
// В Яндекс.Картах нет метода setTapListener(null), поэтому просто добавляем новый обработчик
marker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по AIS маркеру: " + vessel . getMmsi ( ) ) ;
if ( markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onAISVesselClick " ) ;
markerClickListener . onAISVesselClick ( vessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null! " ) ;
}
return true ;
} ) ;
}
// Обработчик клика уже установлен при создании маркера, не добавляем повторно
}
}
@@ -275,8 +235,9 @@ public class YandexMapImpl implements MapInterface {
}
// Удаляем ссылку на судно
aisVessels . remove ( mmsi ) ;
// Удаляем флаг обработчика кликов
// Удаляем флаги обработчиков кликов
aisVesselClickListenersSet . remove ( mmsi ) ;
aisVesselClickListenersAdded . remove ( mmsi ) ;
}
@Override
@@ -287,6 +248,7 @@ public class YandexMapImpl implements MapInterface {
aisMarkers . clear ( ) ;
aisVessels . clear ( ) ;
aisVesselClickListenersSet . clear ( ) ;
aisVesselClickListenersAdded . clear ( ) ;
}
@Override
@@ -322,7 +284,6 @@ public class YandexMapImpl implements MapInterface {
@Override
public void setMarkerClickListener ( MarkerClickListener listener ) {
android . util . Log . d ( " YandexMapImpl " , " setMarkerClickListener вызван: " + ( listener ! = null ? " listener установлен " : " listener == null " ) ) ;
this . markerClickListener = listener ;
// Переустанавливаем обработчики кликов для всех существующих маркеров
@@ -334,46 +295,108 @@ public class YandexMapImpl implements MapInterface {
* Этот метод переустанавливает обработчики для всех маркеров
*/
private void updateAllMarkerClickListeners ( ) {
android . util . Log . d ( " YandexMapImpl " , " updateAllMarkerClickListeners вызван - пере устана вливаем обработчики " ) ;
// Обработчик для маркера нашего судна уже устано влен при создании, не добавляем повторно
// Переустанавливаем о бработчик для маркера нашего судна
if ( ownVesselMarker ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Переустанавливаем обработчик для маркера нашего судна " ) ;
// В Яндекс.Картах нет метода setTapListener(null), поэтому просто добавляем новый обработчик
ownVesselMarker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по маркеру нашего судна! " ) ;
if ( markerClickListener ! = null & & ownVessel ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onOwnVesselClick " ) ;
markerClickListener . onOwnVesselClick ( ownVessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null или ownVessel == null! " ) ;
}
return true ;
} ) ;
ownVesselClickListenerSet = true ;
}
// Переустанавливаем обработчики для AIS маркеров
for ( Map . Entry < String , com . yandex . mapkit . map . PlacemarkMapObject > entry : aisMarkers . entrySet ( ) ) {
String mmsi = entry . getKey ( ) ;
com . yandex . mapkit . map . PlacemarkMapObject marker = entry . getValue ( ) ;
AISVessel vessel = aisVessels . get ( mmsi ) ;
if ( marker ! = null & & vessel ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Переустанавливаем обработчик для AIS маркера: " + mmsi ) ;
// В Яндекс.Картах нет метода setTapListener(null), поэтому просто добавляем новый обработчик
marker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по AIS маркеру: " + mmsi ) ;
if ( markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onAISVesselClick " ) ;
markerClickListener . onAISVesselClick ( vessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null! " ) ;
}
return true ;
} ) ;
aisVesselClickListenersSet . put ( mmsi , true ) ;
// О бработчики для AIS маркеров уже установлены при создании, не добавляем повторно
}
/**
* Создание повернутой цветной иконки из ресурса
*/
private Bitmap createRotatedIconFromResource ( int resourceId , double course , int color ) {
return createRotatedIconFromResource ( resourceId , course , color , false ) ;
}
/**
* Создание повернутой цветной иконки из ресурса с поддержкой выделения
*/
private Bitmap createRotatedIconFromResource ( int resourceId , double course , int color , boolean isSelected ) {
try {
// Получаем drawable из ресурса
Drawable drawable = context . getResources ( ) . getDrawable ( resourceId , null ) ;
if ( drawable = = null ) {
return null ;
}
// Применяем цвет к drawable
if ( color ! = 0 ) {
drawable . setColorFilter ( color , android . graphics . PorterDuff . Mode . SRC_IN ) ;
}
// Получаем оригинальные размеры drawable
int originalWidth = drawable . getIntrinsicWidth ( ) ;
int originalHeight = drawable . getIntrinsicHeight ( ) ;
// Если размеры не определены, используем стандартные
if ( originalWidth < = 0 ) originalWidth = 32 ;
if ( originalHeight < = 0 ) originalHeight = 48 ;
// Масштабируем размеры (уменьшаем еще больше)
float scale = 0 . 3f ; // Уменьшаем в 3.3 раза
int width = ( int ) ( originalWidth * scale ) ;
int height = ( int ) ( originalHeight * scale ) ;
// Получаем азимут карты (поворот карты)
float mapAzimuth = 0 . 0f ;
try {
CameraPosition cameraPosition = mapView . getMap ( ) . getCameraPosition ( ) ;
mapAzimuth = cameraPosition . getAzimuth ( ) ;
} catch ( Exception e ) {
// Не удалось получить азимут карты
}
// Создаем bitmap минимального размера для уменьшения хитбокса
int bitmapSize = Math . max ( width , height ) + 8 ; // Добавляем только небольшой отступ
Bitmap bitmap = Bitmap . createBitmap ( bitmapSize , bitmapSize , Bitmap . Config . ARGB_8888 ) ;
Canvas canvas = new Canvas ( bitmap ) ;
// Поворачиваем маркер на курс судна с учетом поворота карты
// Курс судна - это направление относительно севера
// Азимут карты - это поворот карты относительно севера
// Итоговый поворот = курс судна - азимут карты (чтобы маркер оставался относительно севера)
float rotationAngle = ( float ) ( course - mapAzimuth ) ;
// Центрируем drawable в bitmap
int centerX = bitmapSize / 2 ;
int centerY = bitmapSize / 2 ;
int left = centerX - width / 2 ;
int top = centerY - height / 2 ;
// Устанавливаем границы для drawable
drawable . setBounds ( left , top , left + width , top + height ) ;
// Поворачиваем canvas на курс
canvas . save ( ) ;
canvas . rotate ( rotationAngle , centerX , centerY ) ;
// Рисуем drawable
drawable . draw ( canvas ) ;
canvas . restore ( ) ;
// Если судно выделено, добавляем рамку выделения
if ( isSelected ) {
// Получаем drawable для рамки выделения
Drawable selectionDrawable = context . getResources ( ) . getDrawable (
context . getResources ( ) . getIdentifier ( " chosentarget " , " drawable " , context . getPackageName ( ) ) , null ) ;
if ( selectionDrawable ! = null ) {
// Масштабируем рамку выделения
int selectionSize = Math . max ( width , height ) + 16 ; // Рамка немного больше
int selectionLeft = centerX - selectionSize / 2 ;
int selectionTop = centerY - selectionSize / 2 ;
selectionDrawable . setBounds ( selectionLeft , selectionTop ,
selectionLeft + selectionSize , selectionTop + selectionSize ) ;
// Рисуем рамку выделения
selectionDrawable . draw ( canvas ) ;
}
}
return bitmap ;
} catch ( Exception e ) {
return null ;
}
}
@@ -410,10 +433,8 @@ public class YandexMapImpl implements MapInterface {
canvas . drawPath ( path , paint ) ;
canvas . restore ( ) ;
android . util . Log . d ( " YandexMapImpl " , " Программная иконка с курсом " + course + " ° создана успешно, размер: " + size + " x " + size ) ;
return bitmap ;
} catch ( Exception e ) {
android . util . Log . e ( " YandexMapImpl " , " Ошибка создания программной иконки: " + e . getMessage ( ) , e ) ;
return null ;
}
}
@@ -429,7 +450,6 @@ public class YandexMapImpl implements MapInterface {
* Принудительно пересоздает маркер нашего судна с иконкой
*/
public void recreateOwnVesselMarker ( Vessel vessel ) {
android . util . Log . d ( " YandexMapImpl " , " Принудительно пересоздаем маркер нашего судна " ) ;
if ( ownVesselMarker ! = null ) {
mapObjects . remove ( ownVesselMarker ) ;
ownVesselMarker = null ;
@@ -442,7 +462,6 @@ public class YandexMapImpl implements MapInterface {
* Вызывается после закрытия BottomSheet для восстановления функциональности
*/
public void refreshMarkerClickListeners ( ) {
android . util . Log . d ( " YandexMapImpl " , " refreshMarkerClickListeners вызван - переустанавливаем все обработчики " ) ;
updateAllMarkerClickListeners ( ) ;
}
@@ -450,84 +469,143 @@ public class YandexMapImpl implements MapInterface {
* Устанавливает иконку для маркера с fallback
*/
private void setMarkerIcon ( com . yandex . mapkit . map . PlacemarkMapObject marker , String iconName , double course ) {
setMarkerIcon ( marker , iconName , course , 0 ) ; // По умолчанию без цвета
}
/**
* Устанавливает цветную иконку для маркера с fallback
*/
private void setMarkerIcon ( com . yandex . mapkit . map . PlacemarkMapObject marker , String iconName , double course , int color ) {
setMarkerIcon ( marker , iconName , course , color , false ) ;
}
/**
* Устанавливает цветную иконку для маркера с поддержкой выделения
*/
private void setMarkerIcon ( com . yandex . mapkit . map . PlacemarkMapObject marker , String iconName , double course , int color , boolean isSelected ) {
try {
android . util . Log . d ( " YandexMapImpl " , " Пытаемся устан ови ть иконку: " + iconName + " с курсом: " + course + " ° " ) ;
android . util . Log . d ( " YandexMapImpl " , " Package name: " + context . getPackageName ( ) ) ;
// Сначала пробуем создать программную иконку с учетом курса
android . util . Log . d ( " YandexMapImpl " , " Создаем программную иконку стрелки с курсом " + course + " °... " ) ;
Bitmap iconBitmap = createVesselIcon ( android . graphics . Color . BLUE , course ) ;
if ( iconBitmap ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Программная иконка с курсом " + course + " ° создана, устанавливаем... " ) ;
marker . setIcon ( ImageProvider . fromBitmap ( iconBitmap ) ) ;
android . util . Log . d ( " YandexMapImpl " , " Программная иконка с курсом " + course + " ° установлена успешно " ) ;
return ;
}
// Если программная иконка не создалась, пробуем ресурс
// Сначала пробуем использ ова ть ресурс с поворотом
int iconResId = context . getResources ( ) . getIdentifier ( iconName , " drawable " , context . getPackageName ( ) ) ;
android . util . Log . d ( " YandexMapImpl " , " ID ресурса " + iconName + " : " + iconResId ) ;
if ( iconResId ! = 0 ) {
android . util . Log . d ( " YandexMapImpl " , " Устанавливаем иконку из ресурса... " ) ;
marker . setIcon ( ImageProvider . fromResource ( context , iconResId ) ) ;
android . util . Log . d ( " YandexMapImpl " , " Иконка " + iconName + " установлена успешно " ) ;
Bitmap rotatedBitmap = createRotatedIconFromResource ( iconResId , course , color , isSelected ) ;
if ( rotatedBitmap ! = null ) {
marker . setIcon ( ImageProvider . fromBitmap ( rotatedBitmap ) ) ;
return ;
} else {
marker . setIcon ( ImageProvider . fromResource ( context , iconResId ) ) ;
return ;
}
}
// Если ресурс не найден, создаем программную иконку с учетом курса
Bitmap iconBitmap = createVesselIcon ( android . graphics . Color . BLUE , course ) ;
if ( iconBitmap ! = null ) {
marker . setIcon ( ImageProvider . fromBitmap ( iconBitmap ) ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " Не удалось найти ресурс " + iconName ) ;
android . util . Log . d ( " YandexMapImpl " , " Используем fallback иконку... " ) ;
// Создаем простую иконку как fallback
marker . setIcon ( ImageProvider . fromResource ( context , android . R . drawable . ic_menu_compass ) ) ;
android . util . Log . d ( " YandexMapImpl " , " Fallback иконка установлена " ) ;
}
} catch ( Exception e ) {
android . util . Log . e ( " YandexMapImpl " , " Ошибка установки иконки " + iconName + " : " + e . getMessage ( ) , e ) ;
android . util . Log . d ( " YandexMapImpl " , " Используем fallback иконку после ошибки... " ) ;
// Создаем простую иконку как fallback
marker . setIcon ( ImageProvider . fromResource ( context , android . R . drawable . ic_menu_compass ) ) ;
android . util . Log . d ( " YandexMapImpl " , " Fallback иконка установлена после ошибки " ) ;
}
// После установки иконки проверяем, что обработчик клика все еще работает
// Это может помочь с проблемами, когда установка иконки нарушает обработчики
android . util . Log . d ( " YandexMapImpl " , " Иконка установлена, проверяем обработчик клика... " ) ;
// Дополнительная проверка: если это маркер нашего судна, пере устана вливаем обработчик клика
if ( marker = = ownVesselMarker & & markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Переустанавливаем о бработчик клика для маркера нашего судна после установки иконки " ) ;
// В Яндекс.Картах нет метода setTapListener(null), поэтому просто добавляем новый обработчик
marker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по маркеру нашего судна! " ) ;
if ( markerClickListener ! = null & & ownVessel ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onOwnVesselClick " ) ;
markerClickListener . onOwnVesselClick ( ownVessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null или ownVessel == null! " ) ;
// Обработчик клика для нашего судна уже устано влен при создании маркера, не добавляем повторно
// О бработчики кликов уже установлены при создании маркеров, не добавляем повторно
}
/**
* Настройка слушателя поворота карты
*/
private void setupCameraListener ( ) {
try {
inputListener = new com . yandex . mapkit . map . InputListener ( ) {
@Override
public void onMapTap ( com . yandex . mapkit . map . Map map , com . yandex . mapkit . geometry . Point point ) {
// Не обрабатываем клики по карте
}
return true ;
} ) ;
@Override
public void onMapLongTap ( com . yandex . mapkit . map . Map map , com . yandex . mapkit . geometry . Point point ) {
// Не обрабатываем долгие клики по карте
}
} ;
// Добавляем слушатель к карте
mapView . getMap ( ) . addInputListener ( inputListener ) ;
// Включаем жесты поворота карты
mapView . getMap ( ) . setRotateGesturesEnabled ( true ) ;
} catch ( Exception e ) {
// Ошибка установки слушателя
}
}
/**
* Перерисовывает все маркеры с учетом текущего азимута карты
* Вызывается при повороте карты
*/
public void refreshAllMarkers ( ) {
// Перерисовываем маркер нашего судна (синий цвет)
if ( ownVesselMarker ! = null & & ownVessel ! = null ) {
setMarkerIcon ( ownVesselMarker , " target " , ownVessel . getCourse ( ) , android . graphics . Color . BLUE ) ;
}
// Дополнительная проверка: если это AIS маркер, переустанавливаем обработчик клика
// Перерисовываем все AIS маркеры с их цветами
for ( Map . Entry < String , com . yandex . mapkit . map . PlacemarkMapObject > entry : aisMarkers . entrySet ( ) ) {
if ( entry . getValue ( ) = = marker & & markerClickListener ! = null ) {
String mmsi = entry . getKey ( ) ;
AISVessel vessel = aisVessels . get ( mmsi ) ;
if ( vessel ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Переустанавливаем обработчик клика для AIS маркера " + mmsi + " после установки иконки " ) ;
// В Яндекс.Картах нет метода setTapListener(null), поэтому просто добавляем новый обработчик
marker . addTapListener ( ( mapObject , point1 ) - > {
android . util . Log . d ( " YandexMapImpl " , " Клик по AIS маркеру: " + mmsi ) ;
if ( markerClickListener ! = null ) {
android . util . Log . d ( " YandexMapImpl " , " Вызываем callback onAISVesselClick " ) ;
markerClickListener . onAISVesselClick ( vessel ) ;
} else {
android . util . Log . e ( " YandexMapImpl " , " markerClickListener == null! " ) ;
}
return true ;
} ) ;
}
break ;
String mmsi = entry . getKey ( ) ;
com . yandex . mapkit . map . PlacemarkMapObject marker = entry . getValue ( ) ;
AISVessel vessel = aisVessels . get ( mmsi ) ;
if ( marker ! = null & & vessel ! = null ) {
int vesselColor = getVesselColor ( vessel ) ;
setMarkerIcon ( marker , " target " , vessel . getCourse ( ) , vesselColor , vessel . isSelected ( ) ) ;
}
}
}
/**
* Переключает выделение AIS судна
*/
private void toggleVesselSelection ( AISVessel vessel ) {
vessel . setSelected ( ! vessel . isSelected ( ) ) ;
// Обновляем иконку маркера с учетом состояния выделения
com . yandex . mapkit . map . PlacemarkMapObject marker = aisMarkers . get ( vessel . getMmsi ( ) ) ;
if ( marker ! = null ) {
int vesselColor = getVesselColor ( vessel ) ;
setMarkerIcon ( marker , " target " , vessel . getCourse ( ) , vesselColor , vessel . isSelected ( ) ) ;
}
}
/**
* Получает цвет для AIS судна в зависимости от его статуса
*/
private int getVesselColor ( AISVessel vessel ) {
// Можно настроить цвета в зависимости от параметров судна
// Используем navigation status из AIS данных
String navStatus = vessel . getNavigationalStatus ( ) ;
if ( navStatus ! = null ) {
switch ( navStatus . toLowerCase ( ) ) {
case " under way using engine " :
case " under way " :
return android . graphics . Color . GREEN ;
case " at anchor " :
return android . graphics . Color . YELLOW ;
case " moored " :
return android . graphics . Color . BLUE ;
case " not under command " :
case " restricted manoeuvrability " :
return android . graphics . Color . RED ;
default :
return android . graphics . Color . WHITE ;
}
}
return android . graphics . Color . WHITE ; // По умолчанию белый
}
}