Files
AndroidAisMap/app/src/main/res/layout/activity_settings.xml
T
Grigo b5aee265bc feat: новая архитектура UI и расширенная визуализация AIS
Архитектурные улучшения:
- Внедрен UIRenderingCoordinator с централизованным throttling
- Решены проблемы зависания UI через батчинг операций карты
- Добавлен VesselPathController для отслеживания маршрутов
- Реализован MapLibreMapImpl как альтернатива Яндекс.Картам

Визуализация AIS:
- Добавлены векторные иконки для всех типов судов
- Разделение Class A/B судов с соответствующими иконками
- Иконки навигационных статусов (anchor, moored, engine, sail)
- Улучшенный CursorOverlay с информацией о судах

Производительность:
- Throttling UI обновлений (vessel: 500ms, AIS: 1s, paths: 2s)
- Устранение утечек Handler объектов
- Оптимизация GeoJSON операций в MapLibre
2025-10-02 09:15:33 +03:00

628 lines
29 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Заголовок -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="⚙️ Настройки AIS Map"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:gravity="center"
android:layout_marginBottom="24dp" />
<!-- UDP Настройки -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="📡 UDP Настройки"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="UDP Порт"
app:helperText="Порт для прослушивания AIS данных">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_udp_port"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="10110" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_udp_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Включить UDP слушатель"
android:textSize="16sp"
android:checked="true" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Треки и предсказание -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="🧭 Путь и предсказание"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Максимум точек на судно"
app:helperText="Ограничение размера истории пути">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_path_max_points"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="300" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Толщина линии пути (px)">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_path_width"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="3.0" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Цвет пути (#RRGGBB)">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_path_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:text="#00FFFF" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Толщина линии предсказания (px)">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_prediction_width"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="2.0" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Цвет предсказания (#RRGGBB)">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_prediction_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:text="#FFFF00" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Горизонт предсказания (сек)">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_prediction_horizon_sec"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="60" />
</com.google.android.material.textfield.TextInputLayout>
<!-- Кнопка очистки трекера пути -->
<Button
android:id="@+id/btn_clear_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="🗑️ Очистить трекер пути"
android:textSize="16sp"
android:layout_marginTop="8dp"
style="@style/Widget.Material3.Button.OutlinedButton" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Удаляет все сохраненные точки пути собственного судна"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Приоритеты данных -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="📊 Приоритеты данных"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Выберите источники данных для получения координат и навигационной информации:"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_android_nmea_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Android NMEA (GPS API)"
android:textSize="16sp"
android:checked="true"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Использовать встроенный GPS Android для получения координат"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp"
android:layout_marginStart="16dp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_udp_nmea_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="UDP NMEA"
android:textSize="16sp"
android:checked="true"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Получать NMEA данные через UDP (курс, скорость, спутники)"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp"
android:layout_marginStart="16dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Режим работы:"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="8dp" />
<RadioGroup
android:id="@+id/radio_group_data_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/radio_hybrid_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Гибридный режим (рекомендуется)"
android:textSize="14sp"
android:checked="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Координаты от Android GPS, остальное от NMEA"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
<RadioButton
android:id="@+id/radio_nmea_only"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Только NMEA"
android:textSize="14sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Все данные только из NMEA сообщений"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
<RadioButton
android:id="@+id/radio_android_only"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Только Android GPS"
android:textSize="14sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Только встроенный GPS Android"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
</RadioGroup>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Настройки устаревания данных -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="⏰ Устаревание данных AIS"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Настройте время, через которое данные о судах считаются устаревшими:"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Время предупреждения (минуты)"
app:helperText="Судна старше этого времени будут помечены как устаревшие">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_stale_warning_minutes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="5" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Время удаления (минуты)"
app:helperText="Судна старше этого времени будут удалены с карты">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_stale_remove_minutes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="7" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="💡 Совет: Устаревшие суда отображаются с иконкой losingtarget.xml"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginTop="8dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Настройки экрана -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="📱 Управление экраном"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Настройте поведение экрана во время навигации:"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_keep_screen_on"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Не давать экрану засыпать"
android:textSize="16sp"
android:checked="true"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Экран будет оставаться включенным во время навигации (рекомендуется для навигатора)"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Настройки уведомлений -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="🔔 Уведомления о новых целях AIS"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Настройте уведомления при обнаружении новых судов:"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_vibration_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Вибрация"
android:textSize="16sp"
android:checked="true"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Вибрация устройства при обнаружении нового судна"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp"
android:layout_marginStart="16dp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_sound_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Звуковое уведомление"
android:textSize="16sp"
android:checked="true"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Звуковой сигнал при обнаружении нового судна"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Настройки курсора -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="🎯 Курсор на карте"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:layout_marginBottom="12dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Настройте отображение курсора с координатами центра экрана:"
android:textSize="14sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="16dp" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_cursor_enabled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Показать курсор"
android:textSize="16sp"
android:checked="false"
android:layout_marginBottom="8dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Отображать крест в центре экрана с координатами и информацией о расстоянии"
android:textSize="12sp"
android:textColor="@android:color/darker_gray"
android:layout_marginBottom="8dp"
android:layout_marginStart="16dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- Кнопки -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<Button
android:id="@+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Отмена"
android:layout_marginEnd="8dp"
style="@style/Widget.Material3.Button.OutlinedButton" />
<Button
android:id="@+id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Сохранить"
style="@style/Widget.Material3.Button" />
</LinearLayout>
</LinearLayout>
</ScrollView>