diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java
index c350204b52..9b61aec963 100644
--- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java
+++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java
@@ -10,8 +10,6 @@ import net.osmand.router.GeneralRouter.RouteDataObjectAttribute;
public class TransportRoutingConfiguration {
- public static final String KEY = "public_transport";
-
public int ZOOM_TO_LOAD_TILES = 15;
public int walkRadius = 1500; // ? 3000
diff --git a/OsmAnd-telegram/res/values-sv/strings.xml b/OsmAnd-telegram/res/values-sv/strings.xml
index cbf274305e..7dac55e059 100644
--- a/OsmAnd-telegram/res/values-sv/strings.xml
+++ b/OsmAnd-telegram/res/values-sv/strings.xml
@@ -13,7 +13,7 @@
Kilomter/meter
Miles/yard
Miles/fot
- Distansminuter per timme (knop)
+ Sjömil per timme (knop)
Minuter per mile
Minuter per kilometer
Meter per sekund
diff --git a/OsmAnd/res/layout/route_line_appearance.xml b/OsmAnd/res/layout/route_line_appearance.xml
new file mode 100644
index 0000000000..ca822afb37
--- /dev/null
+++ b/OsmAnd/res/layout/route_line_appearance.xml
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/route_line_color_card.xml b/OsmAnd/res/layout/route_line_color_card.xml
new file mode 100644
index 0000000000..c25332de88
--- /dev/null
+++ b/OsmAnd/res/layout/route_line_color_card.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/route_line_width_card.xml b/OsmAnd/res/layout/route_line_width_card.xml
new file mode 100644
index 0000000000..9d0702b1dd
--- /dev/null
+++ b/OsmAnd/res/layout/route_line_width_card.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml
index 9583371a8e..178af35973 100644
--- a/OsmAnd/res/values-eo/strings.xml
+++ b/OsmAnd/res/values-eo/strings.xml
@@ -4045,4 +4045,7 @@
Intertempo
Kaŝi limojn de naturaj rezervejoj, protektataj areoj kaj naciaj parkoj
Limoj de rezervejoj
+ Agordita periodo de intertempo de registrado, dum kiu OsmAnd petos la nunajn poziciajn datumojn.
+ Ĉiuj nekonservitaj datumoj perdiĝos.
+ Konservi kaj daŭrigi
\ No newline at end of file
diff --git a/OsmAnd/res/values-et/strings.xml b/OsmAnd/res/values-et/strings.xml
index f78e97a163..e4c91a241f 100644
--- a/OsmAnd/res/values-et/strings.xml
+++ b/OsmAnd/res/values-et/strings.xml
@@ -4052,4 +4052,6 @@
Kaugus toksamise järgi
Peida (loodus)kaitsealade ja rahvusparkide piirid
Looduse piirid
+ Salvesta ja jätka
+ Kõik salvestamata andmed lähevad kaotsi.
\ No newline at end of file
diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml
index ff02ab8a68..2d0bce8623 100644
--- a/OsmAnd/res/values-fa/strings.xml
+++ b/OsmAnd/res/values-fa/strings.xml
@@ -492,7 +492,7 @@
اجرای برنامه در حالت ایمن (بهجای کد native از کد Android که کُندتر است استفاده میکند).
برنامه در حالت ایمن اجرا شده است (از طریق تنظیمات آن را غیرفعال کنید).
سرویس پسزمینهٔ OsmAnd هنوز در حال اجراست. آن را هم متوقف میکنید؟
- بستن بستهٔ تغییرات
+ بستن بستهٔ تغییر
برنامهٔ اسکنر بارکد ZXing نصب نشده است. در گوگلپلی جستوجو میکنید؟
یکی از رنگبندیهای راه را انتخاب کنید:
رنگبندی راه
@@ -787,8 +787,8 @@
در حال تبدیل اسامی محلی/انگلیسی…
ناموفق
اجازهٔ دسترسی احراز نشد
- بستن بستهٔ تغییرات…
- بازکردن بستهٔ تغییرات…
+ بستن بستهٔ تغییر…
+ بازکردن بستهٔ تغییر…
دریافت لیست مناطق از https://osmand.net ناموفق بود.
در حال دانلود لیست مناطق موجود…
دادهٔ آفلاینِ {0} از قبل وجود دارد ({1}). آن را روزآمد میکنید ({2})؟
@@ -1478,7 +1478,7 @@
برنامهٔ OsmAnd نقشهگردی و ناوبری آفلاین را برایتان به ارمغان میآورد.
خوش آمدید
مسیر فعلی
- تغییرات OSM به بستهٔ تغییرات محلی اضافه شد
+ تغییرات OSM به بستهٔ تغییر محلی اضافه شد
برای حذفکردن علامت بزنید
از آپلود این %1$d تغییر در OSM مطمئن هستید؟
سوابق را پاک میکنید؟
@@ -2589,7 +2589,7 @@
نشانههایی که بهعنوان گذرانده مشخص شود در این صفحه نشان داده میشود.
بیشتر
در حال جستوجوی ردهای دارای راهنشان
- اشیای OSM را بسازید یا ویرایش کنید
+ مکانهای OSM را ایجاد یا ویرایش کنید
POIها را اضافه یا ویرایش کنید، یادداشتهای OSMای اضافه کنید یا روی آنها نظر بدهید و فایلهای GPX ضبطشده را آپلود کنید.
حذفشده(ها)
ویرایش شد
@@ -3479,7 +3479,7 @@
در حال درونبرد
درونبرد کامل شد
همهٔ داده از %1$s درونبرد شد. با استفاده از دکمههای زیر میتوانید بخش موردنیاز برنامه را برای مدیریت آن باز کنید.
- انواع POI
+ گونههای POI
%1$s که در زیر آمده، هماکنون در OsmAnd وجود دارد.
OsmAnd در حال بررسی %1$s برای چیزهای تکراری موجود در برنامه است.
\n
@@ -4068,5 +4068,5 @@
مکث کرده
دکمهای برای آشکار یا پنهان کردن ابزارک مختصات روی نقشه.
بازه
- فاصله با لمس دوانگشتی
+ مسافت با لمس
\ No newline at end of file
diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml
index 18cf09a780..702b8f37e1 100644
--- a/OsmAnd/res/values-fr/strings.xml
+++ b/OsmAnd/res/values-fr/strings.xml
@@ -1192,11 +1192,11 @@
Fichier GPX vide
Traces
Favoris
- Mes lieux favoris
+ Lieux favoris
\n\nAppui long pour afficher sur la carte
Démarrer la navigation pas à pas automatiquement
sélectionné(s)
- Intervalle de division
+ Intervalle de fractionnement
\n\nAppui long pour afficher les options
Sections : %1$s
Points de passage : %1$s
@@ -4035,4 +4035,7 @@
Appuyer pour afficher ou cacher le widget Coordonnées sur la carte.
L’icône de localisation va se déplacer sur le trajet en cours.
Veuillez sélectionner un autre type de colorisation.
+ L\'intervalle d’enregistrement définit la fréquence à laquelle OsmAnd récupérera les données de localisation.
+ Enregistrer et continuer
+ Toutes les données non enregistrées seront perdues.
\ No newline at end of file
diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml
index 2f81cd1464..f42791d9aa 100644
--- a/OsmAnd/res/values-hu/strings.xml
+++ b/OsmAnd/res/values-hu/strings.xml
@@ -4039,4 +4039,7 @@
Az alkalmazás hetente ellenőrzi a térképfrissítéseket. Következő ellenőrzés: %1$s (ennyi idő múlva: %2$s).
Az alkalmazás naponta ellenőrzi a térképfrissítéseket. Következő ellenőrzés: %1$s (ennyi idő múlva: %2$s).
Az alkalmazás óránként ellenőrzi a térképfrissítéseket. Következő ellenőrzés: %1$s (ennyi idő múlva: %2$s).
+ A naplózási intervallum az az időköz, amelyben az OsmAnd lekéri az aktuális helyadatokat.
+ Mentés és folytatás
+ Minden nem mentett adat törlődni fog.
\ No newline at end of file
diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml
index c5949f404d..76006696f9 100644
--- a/OsmAnd/res/values-iw/strings.xml
+++ b/OsmAnd/res/values-iw/strings.xml
@@ -9,7 +9,7 @@
הצגת הכיוון ליעד
יש להפעיל את תוסף „מעקב הטיול” כדי להשתמש בשירותי רישום מיקום (מעקב חי, רישום GPX)
יש לחשב מסלול בלתי יעיל למרחקים ארוכים
- נא להפעיל את רכיב האיכון (GPS) בהגדרות
+ נא להפעיל את ה־GPS בהגדרות
שירותי רישום
אין מסלול
הסרת יעד
@@ -1881,7 +1881,7 @@
מטרים לשנייה
דקות לקילומטר
דקות למייל
- מיל ימי לשעה (קשר)
+ מייל ימי לשעה (קשר)
קשר
מ/שנ׳
הקלטת טיול
@@ -4047,4 +4047,8 @@
קיים עדכון ל־OpenStreetMap:
להסתיר גבולות של שמורות טבע, אזורים מוגנים ופארקים ציבוריים
גבולות טבעיים
+ למחוק את כל העדכונים החיים של %s\?
+ הגדרת הפרש קבוע בין הבקשות של OsmAnd לקבלת נתוני המיקום הנוכחיים.
+ לשמור ולהמשיך
+ כל הנתונים שלא נשמרו יאבדו.
\ No newline at end of file
diff --git a/OsmAnd/res/values-ja/strings.xml b/OsmAnd/res/values-ja/strings.xml
index 206586cfd1..cc3465ea61 100644
--- a/OsmAnd/res/values-ja/strings.xml
+++ b/OsmAnd/res/values-ja/strings.xml
@@ -3950,4 +3950,7 @@ POIの更新は利用できません
経路には標高データは含まれていません。
経路には速度データは含まれていません。
別タイプのカラーを選択してください。
+ ログ記録間隔は、OsmAndが現在の位置データを要求する期間を設定します。
+ 保存して続行
+ 保存されていないデータはすべて失われます。
\ No newline at end of file
diff --git a/OsmAnd/res/values-nb/strings.xml b/OsmAnd/res/values-nb/strings.xml
index 38107b6cc1..c902064e98 100644
--- a/OsmAnd/res/values-nb/strings.xml
+++ b/OsmAnd/res/values-nb/strings.xml
@@ -3939,4 +3939,6 @@
Optimalisert kortere rute (energisparende)
Aktuelle posisjonsikon vil bli festet til gjeldende navigeringsrute
Ruting kan unngå kraftige oppoverbakker.
+ Lagre og fortsett
+ All ulagret data vil gå tapt.
\ No newline at end of file
diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml
index 5cb9de5bb1..1914ba1d48 100644
--- a/OsmAnd/res/values-pt-rBR/strings.xml
+++ b/OsmAnd/res/values-pt-rBR/strings.xml
@@ -4040,4 +4040,6 @@
Selecione outro tipo de colorização.
Limites naturais
Segmento %1$d
+ Salvar e continuar
+ Todos os dados não salvos serão perdidos.
\ No newline at end of file
diff --git a/OsmAnd/res/values-sv/strings.xml b/OsmAnd/res/values-sv/strings.xml
index 0dd3173583..c84d961139 100644
--- a/OsmAnd/res/values-sv/strings.xml
+++ b/OsmAnd/res/values-sv/strings.xml
@@ -84,7 +84,8 @@
Välj animerad ruttacceleration
Allokerat minne %1$s MB (Android-gräns %2$s MB, Dalvik %3$s MB).
Allokerat minne
- Totalt inbyggt minne allokerat av appen %1$s MB (Dalvik %2$s MB, övrigt %3$s MB). Proportionellt minne %4$s MB (Android-gräns %5$s MB, Dalvik %6$s MB).
+ Totalt inbyggt minne allokerat av appen %1$s MB (Dalvik %2$s MB, övrigt %3$s MB).
+\nProportionellt minne %4$s MB (Android-gräns %5$s MB, Dalvik %6$s MB).
Totalt inbyggt minne
Startpunkten ligger för långt från närmaste väg.
Delad plats
@@ -165,9 +166,8 @@
em
fm
Parkeringsplats
- Modulen Parkeringsplats hjälper dig att hålla reda på var din bil är parkerad och vid behov hur mycket parkeringstid det är kvar.
-
-Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på kartskärmen. Du kan lägga till ett larm i kalendern som en påminnelse.
+ Låter dig spara var din bil är parkerad, inklusive hur mycket parkeringstid som finns kvar.
+\nBåde plats och tid är synliga både på instrumentpanelen och i en kartwidget. En larmpåminnelse kan läggas till i Android-kalendern.
Parkeringsplats
Markera som parkeringsplats
Ta bort P-markering
@@ -192,11 +192,11 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
Online-kartor och kartrutor
Använd online-kartor (hämta och cacha kartbitar på SD-kortet).
Konfigurera online- eller cachade källor för kartbitar.
- "Med denna modul får man tillgång till många typer av online-kartor, från fördefinierade Openstreetmap-rutor (som Mapnik) till satellitbilder och speciella lager såsom väderkartor, klimatkartor, geologiska kartor, reliefkartor o.s.v.
+ Med denna modul får man tillgång till många typer av online-kartor, från fördefinierade Openstreetmap-rutor (som Mapnik) till satellitbilder och speciella lager såsom väderkartor, klimatkartor, geologiska kartor, reliefkartor o.s.v.
\n
-\nDessa kartor kan användas antingen som huvudkarta (baskarta) och visas på kartskärmen i OsmAnd eller som ett över- eller underlägg till en annan baskarta (som OsmAnds vanliga offline-kartor). För att göra en underliggande karta tydligare kan vissa element i OsmAnds vektorkartor lätt döljas via menyn \'Konfigurera karta\'.
+\nDessa kartor kan användas antingen som huvudkarta (baskarta) och visas på kartskärmen i OsmAnd eller som ett över- eller underlägg till en annan baskarta (som OsmAnds vanliga offline-kartor). För att göra en underliggande karta tydligare kan vissa element i OsmAnds vektorkartor lätt döljas via menyn \'Konfigurera karta\'.
\n
-\nKartbitar (tile maps) kan hämtas direkt på nätet eller förberedas för användning frånkopplad (och kopieras manuellt till OsmAnds datamapp) som en SQLite-databas som kan skapas med olika tredjepartsverktyg. "
+\nKartbitar (tile maps) kan hämtas direkt på nätet eller förberedas för användning frånkopplad (och kopieras manuellt till OsmAnds datamapp) som en SQLite-databas som kan skapas med olika tredjepartsverktyg.
Visa inställningarna för att aktivera spårning och navigering i bakgrundsläge (skärm av) genom att periodvis väcka GPS-enheten.
Denna modul visar inställningarna för utvecklings- och felsökningsfunktioner som rutt-testning och -simulering eller visning av renderingsprestanda eller röststyrning. Dessa inställningar är avsedda för utvecklare och behövs inte för den vanliga användaren.
Hantera insticksmoduler
@@ -208,19 +208,33 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
Din parkerade bils plats. %1$s
Insticksmoduler aktiverar avancerade inställningar samt ger ytterligare funktionalitet.
Insticksmoduler
- "Med denna modul kan OsmAnd användas för att göra bidrag till OSM såsom skapa eller modifiera OSM POI-objekt, öppna eller kommentera OSM-anteckningar, och bidra med inspelade GPX-filer. OSM är ett globalt kartprojekt inom public domain, För mer info, se https://openstreetmap.org. Aktivt deltagande uppskattas och bidrag kan göras direkt från OsmAnd om du anger dina autentiseringsuppgifter till OSM i appen."
+ Ge OSM-bidrag som att skapa eller modifiera OSM POI-objekt, öppna eller kommentera OSM-anteckningar och bidra med inspelade GPX-filer i OsmAnd genom att ange ditt användarnamn och lösenord. OpenStreetMap.org är ett community-driven, globalt kartläggningsprojekt för allmän domän.
Vektorkartor ritas sannolikt upp snabbare. Fungerar kanske inte så bra på vissa enheter.
Spela upp kommandon med vald röst
Test av röstmeddelanden
Det finns ingen offline vektorkarta för den här platsen. Du kan hämta en i Inställningar (Hantera kartfiler) eller byta till online-kartor (aktivera modulen för online-kartor för detta).
- "OsmAnd (Open Street Maps Automated Navigation Directions)
-\n
-\nOsmAnd är ett öppen källkodsprogram med tillgång till ett brett utbud av global OpenStreetMap-data. Alla kartdata (vektor- eller rasterkartor) kan lagras i telefonens minneskort för offlineanvändning. OsmAnd erbjuder även navigering offline och online, inklusive röstguidning. Några av de viktigaste funktionerna: - Komplett offline-funktionalitet (lagra nedladdade vektorkartor eller kartbitar på enheten) - Kompakta offline-vektorkartor för hela världen finns tillgängliga - Nedladdning av land- eller regionkartor direkt från appen - Överlägg av flera kartlager möjligt, som GPX- eller navigationsspår, sevärdheter, favoriter, höjddata, offentliga hållplatser, extra kartor med anpassningsbara transparens - Sökning offline efter adresser och platser (POIs) - Offline-dirigering för medellånga sträckor (experimentell) - Bil-, cykel- och fotgängarlägen med: - Tillval automatisk växling mellan dag- och nattvisning - Tillval hastighetsberoende zoomning - Valfri inställningen enligt kompass eller färdriktningen - Frivillig körfältsvägledning, visning av hastighetsgräns, inspelade röster samt TTS-röster
-\n
-\nBegränsningar i denna gratisversion av OsmAnd: - Antalet hämtningar av kartor är begränsat - Ingen tillgång till Wikipedia offline POIs
-\n
-\nOsmAnd utvecklas aktivt och vårt projekt och dess fortsatta framsteg bygger på ekonomiska bidrag för att finansiera utveckling och testning av ny funktionalitet. Vänligen överväg att köpa OsmAnd+, finansiera specifika nya funktioner eller göra en allmän donation på osmand.net.
-\n "
+ OsmAnd (OSM Automated Navigation Directions)
+\n
+\nOsmAnd är en programvara för öppen källkodsnavigering med tillgång till ett stort antal globala OSM-data. Alla kartdata (vektor- eller brickor) kan lagras på telefonens minneskort för offline-användning. Offline- och online-dirigeringsfunktioner erbjuds också, inklusive röstvägledning för sväng.
+\n
+\nNågra av kärnfunktionerna:
+\n- Komplett offline-funktionalitet (lagra nedladdad vektor eller kakelkartor i enhetens lagring)
+\n- Kompakta offlinevektorkartor för hela världen
+\n- Ladda ner land- eller regionkartor direkt från appen
+\n- Överlagring av flera kartlager möjliga, som GPX eller navigationsspår, intressanta platser, favoriter, konturlinjer, kollektivtrafikstopp, ytterligare kartor med anpassningsbar transparens
+\n- Offline sökning efter adresser och platser (POI)
+\n- Offline-dirigering för medelstora avstånd
+\n- Lägen för bil, cykel och fotgängare med tillval:
+\n- Automatisk växling mellan dag och natt
+\n- Hastighetsberoende kartzoomning
+\n- Kartinriktning enligt kompass eller rörelseriktning
+\n- Fältvägledning, hastighetsgränsvisning, inspelade och text-till-tal-röster
+\n
+\nBegränsningar av denna gratisversion av OsmAnd:
+\n- Antalet nedladdningar av kartor begränsat
+\n- Ingen offlineåtkomst till Wikipedia-intressepunkter
+\n
+\nOsmAnd utvecklas aktivt och vårt projekt och dess fortsatta framsteg är beroende av ekonomiska bidrag för utveckling och testning av ny funktionalitet. Överväg att köpa OsmAnd +, eller finansiera specifika nya funktioner eller göra en allmän donation på https://osmand.net.
Inbyggd rendering
Support
Ge stöd till nya funktioner
@@ -297,9 +311,8 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
Bakgrundsläge
OsmAnd körs i bakgrunden medan skärmen är avstängd.
Det finns inte tillräckligt med ledigt utrymme för att hämta %1$s MB (ledigt: %2$s).
- Hämta {0} fil(er)?
-Nyttjat utrymme är {1} MB.
-(Tillgängligt utrymme är {2} MB.)
+ Hämta {0} fil(er)\?
+\n{1} MB (av {2} MB) kommer att användas.
Genomskinligt tema
Inbyggt bibliotek stöds inte på den här enheten.
Initierar inbyggt bibliotek …
@@ -382,7 +395,7 @@ Nyttjat utrymme är {1} MB.
Packar upp nya data …
En online-navigeringstjänst är vald men ingen internetanslutning är tillgänglig.
Språket stöds inte
- Det valda språket stöds inte av den installerade Android TTS (text-till-tal)-motorn. Vill du söka efter en annan TTS-motor på Market? Annars kommer det förinställda TTS-språket att användas.
+ Det valda språket stöds inte av Android TTS (text-till-tal) -motorn installerad, dess förinställda TTS-språk används istället. Leta efter en annan TTS-motor i butiken\?
Data saknas
Inga data för det valda språket är installerade. Vill du besöka Google Play för att installera?
Omvänd GPX-riktning
@@ -701,7 +714,7 @@ Nyttjat utrymme är {1} MB.
Sök efter fler byar/postnummer
Välj när du vill visa kartor som endast har vägar:
Kartor med enbart vägar
- "Vägar "
+ Bara vägar
Standardkartor
Karta med enbart vägar
Kör appen i felsäkert läge (för långsammare Android istället för intern kod).
@@ -783,9 +796,9 @@ Nyttjat utrymme är {1} MB.
Inställningar för ljud och video
Ett fel uppstod under inspelningen
Ingen kamera tillgänglig
- "Denna modul erbjuder överlägg med höjdkurvor som kan visas i kombination med OsmAnds standardkartor. Denna funktion kommer att uppskattas av idrottsmän, vandrare och alla som är intresserade av höjdskillnader i landskapet.
-\n
-\nDessa globala data (mellan 70 grader norr och 70 grader syd) baseras på mätningar av SRTM (Shuttle Radar Topography Mission) och ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), ett bildinstrument ombord Terra, flaggskeppet i NASA:s Earth Observing System. ASTER är ett samprojekt mellan NASA, Japans Ministry of Economy, Trade and Industry (METI), and Japan Space Systems (J-spacesystems). "
+ Denna modul erbjuder överlägg med höjdkurvor som kan visas i kombination med OsmAnds standardkartor. Denna funktion kommer att uppskattas av idrottsmän, vandrare och alla som är intresserade av höjdskillnader i landskapet.
+\n
+\nDessa globala data (mellan 70 grader norr och 70 grader syd) baseras på mätningar av SRTM (Shuttle Radar Topography Mission) och ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), ett bildinstrument ombord Terra, flaggskeppet i NASA:s Earth Observing System. ASTER är ett samprojekt mellan NASA, Japans Ministry of Economy, Trade and Industry (METI), and Japan Space Systems (J-spacesystems).
Ta bort destination
Mellanliggande destination %1$s
Online Nominatim
@@ -874,11 +887,11 @@ Nyttjat utrymme är {1} MB.
Föredra motorvägar.
markerad
ej markerad
- Välj vid användning
+ På förfrågan\?
Aktivera Trippinspelningspluginen för att använda positionsloggningstjänster (GPX-loggning, online-spårning)
- "Denna modul erbjuder både ett överlägg med konturlinjer och ett höjdkurvslager som kan visas ovanpå OsmAnds offline-kartor. Denna funktion kommer att uppskattas av idrottsmän, vandrare och alla som är intresserade av höjdskillnader i landskapet.
+ Denna modul erbjuder både ett överlägg med konturlinjer och ett höjdkurvslager som kan visas ovanpå OsmAnds offline-kartor. Denna funktion kommer att uppskattas av idrottsmän, vandrare och alla som är intresserade av höjdskillnader i landskapet.
\n
-\nDessa globala data (mellan 70 grader norr och 70 grader syd) är baserade på SRTM (Shuttle Radar Topography Mission) och ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), ett bildinstrument på Terra, NASA:s Earth Observing Systems satellit. ASTER är ett samarbete mellan NASA, Japans finansdepartement, Trade and Industry (METI) och Japan Space Systems (J-spacesystems). "
+\nDessa globala data (mellan 70 grader norr och 70 grader syd) är baserade på SRTM (Shuttle Radar Topography Mission) och ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), ett bildinstrument på Terra, NASA:s Earth Observing Systems satellit. ASTER är ett samarbete mellan NASA, Japans finansdepartement, Trade and Industry (METI) och Japan Space Systems (J-spacesystems).
Ankomsttid
OpenMaps EU
Skuggad relief-lager
@@ -892,7 +905,7 @@ Nyttjat utrymme är {1} MB.
%1$d filer kvar
Du har %1$d filer kvar att hämta
Fullversion
- Avbryt rutten
+ Avbryt rutten\?
Avbryt navigeringen
Ta bort destinationen
Wi-Fi är för tillfället inte anslutet. Vill du hämta med din nuvarande anslutning till Internet?
@@ -1218,9 +1231,9 @@ Nyttjat utrymme är {1} MB.
Närbelägna intresssepunkter
Rundturer
Alla
- "Denna modul aktiverar funktionen att antingen spela in och spara dina spår genom att du trycker på widgeten GPX-loggning på kartskärmen eller att alla dina rutter sparas automatiskt i en GPX-fil.
+ Denna modul aktiverar funktionen att antingen spela in och spara dina spår genom att du trycker på widgeten GPX-loggning på kartskärmen eller att alla dina rutter sparas automatiskt i en GPX-fil.
\n
-\nInspelade spår kan delas ut till vänner eller användas som bidrag till OSM. Idrottsmän kan använda inspelade spår för att följa sin träning. Viss grundläggande spåranalys kan göras direkt i OsmAnd, såsom varvtider, genomsnittshastighet o.s.v. och spår kan givetvis också analyseras i efterhand i speciella analysverktyg från tredje part. "
+\nInspelade spår kan delas ut till vänner eller användas som bidrag till OSM. Idrottsmän kan använda inspelade spår för att följa sin träning. Viss grundläggande spåranalys kan göras direkt i OsmAnd, såsom varvtider, genomsnittshastighet o.s.v. och spår kan givetvis också analyseras i efterhand i speciella analysverktyg från tredje part.
Inspelning av resa
h
Längd
@@ -1279,7 +1292,7 @@ Nyttjat utrymme är {1} MB.
Alla filer är uppdaterade
Använd OpenGL-rendering
Använd hårdvaruaccelererad OpenGL-rendering (fungerar kanske inte på vissa enheter).
- Kan inte hämta; kontrollera din internetsanslutning.
+ Kan inte hämta, kontrollera din internetsanslutning.
Vägtyp
Standard
Brandgul
@@ -1349,13 +1362,20 @@ Nyttjat utrymme är {1} MB.
\nEn kartfil som innehåller alla nautiska symboler globalt finns tillgänglig som en enda nedladdning med namnet \'World seamarks\'.
\n
\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor.
- "Om du aktiverar denna vy ändras kartstilen till Vinter och skidor, och visar landskapet i vinterskrud.
-\n\nEn global karta med alla pister och längdskidspår i denna vy finns tillgänglig under Alla kartor som \'World ski map\'.
-\n\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor. "
- "Om du aktiverar denna vy ändras kartan till \'Vägkartsvy\', som är en speciell vy med mycket detaljer för resenärer och yrkesförare.
-\n\nDenna vy ger, vid varje zoomnivå, maximalt antal detaljer som är tillgängliga i kartdatat (speciellt vägar, stigar och orienteringsmärken).\n\nDen visar också alla vägtyper på ett mycket tydligt sätt via färgkoder något som är användbart t.ex vid framförande av stora fordon.
-\n\nOch den erbjuder också speciella alternativ såsom visning av cykelrutter eller rutter i Alperna.\n\nIngen speciell hämtning av någon karta krävs; denna vy skapas med våra standardkartor.
-\n\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor. "
+ Detta plugin för OsmAnd ger dig detaljer om globala utförsåkning, längdskidspår, alpina skidvägar, linbanor och skidliftar. Rutter och pister visas färgkodade av svårigheter och avbildas i en speciell \"vinter\" -stil som liknar ett snöfärgat vinterlandskap.
+\n
+\nOm du aktiverar den här vyn ändras kartstilen till \"Vinter och skidor\" och visar alla landskapsfunktioner under vinterförhållanden. Denna vy kan återställas genom att antingen avaktivera den igen här, eller genom att ändra \'Kartstil\' under \'Konfigurera karta\' efter önskemål.
+ Om du aktiverar denna vy ändras kartan till \'Vägkartsvy\', som är en speciell vy med mycket detaljer för resenärer och yrkesförare.
+\n
+\nDenna vy ger, vid varje zoomnivå, maximalt antal detaljer som är tillgängliga i kartdatat (speciellt vägar, stigar och orienteringsmärken).
+\n
+\nDen visar också alla vägtyper på ett mycket tydligt sätt via färgkoder något som är användbart t.ex vid framförande av stora fordon.
+\n
+\nOch den erbjuder också speciella alternativ såsom visning av cykelrutter eller rutter i Alperna.
+\n
+\nIngen speciell hämtning av någon karta krävs; denna vy skapas med våra standardkartor.
+\n
+\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor.
Plats:\n Lat %1$s\n Lon %2$s
Vägkartsvy
dagar efter
@@ -1423,7 +1443,7 @@ Nyttjat utrymme är {1} MB.
Simulera din plats
Platt lista
Lat %1$s
-Long %2$s
+\nLong %2$s
Frågor och svar, nyliga förändringar och annat.
Navigeringsinställningar
Allmänna inställningar
@@ -1495,7 +1515,7 @@ Long %2$s
Du håller på att ta bort %1$d anteckningar. Är du säker?
Wikipedia
Importera till OsmAnd
- Platstjänsten är inte aktiverad. Vill du slå på den?
+ Platstjänsten är av. Vill du slå på den\?
Du har gamla och inkompatibla data från Wikipedia. Vill du arkivera dem?
Hämta ytterligare data från Wikipedia (%1$s MB)?
Volapük
@@ -1611,7 +1631,7 @@ Long %2$s
Meter per sekund
Minuter per kilometer
Minuter per mile
- Sjömil i timmen (knop)
+ Sjömil per timme (knop)
Inspelning av resa
Navigering
Körs i bakgrunden
@@ -1619,7 +1639,7 @@ Long %2$s
Välj kategori
Antal rader
di
- nmi/h
+ M
min/mi
min/km
m/s
@@ -1746,7 +1766,7 @@ Long %2$s
Avstånd:
Tid:
Appen har inte tillåtelse att använda SD-kortet
- Appen har inte tillräckliga behörigheter för att komma åt platsdata.
+ Appen saknar behörigheter för att komma åt platsdata.
Appen har inte tillräckliga behörigheter för att komma åt kameran.
Appen har inte tillräckliga behörigheter för att komma åt mikrofonen.
Välj röstvägledning
@@ -1807,9 +1827,10 @@ Long %2$s
Verktygsfält
Widgetar
Inte tillräckligt med utrymme!
-Detta skulle kräva {3} MB temporärt och {1} MB permanent.
-Tillgängligt utrymme är blott {2} MB.
- Hämta {0} fil(er)? Nyttjat utrymme är {3} MB temporärt och {1} MB permanent. (Tillgängligt utrymme är {2} MB.)
+\n{3} MB temporärt och {1} MB permanent.
+\n(Bara {2} MB tillgängligt.)
+ Hämta {0} fil(er)\?
+\n{3} MB används temporärt och {1} MB permanent. (Av{2} MB.)
Ladda upp OSM-anteckning
Ladda upp anonymt
Välj kartmarkör
@@ -1879,8 +1900,8 @@ Tillgängligt utrymme är blott {2} MB.
Nu har appen tillåtelse att skriva till extern lagringsplats. En manuell omstart av appen krävs.
Stödregion
Denna prenumeration aktiverar uppdateringar varje timme av kartor runt omkring i världen.
-En del av inkomsterna går tillbaka till OSM-gemenskapen och betalas ut för varje OSM-bidrag.
-Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt sätt att göra det på.
+\nEn del av inkomsterna går tillbaka till OSM-gemenskapen och betalas ut för varje OSM-bidrag.
+\nOm du tycker om OsmAnd och OSM och vill stödja och stödjas av dem så är detta ett utmärkt sätt att göra det på.
Destinationen är inte fastställd
Magnetisk bäring
Klipplängd
@@ -1936,7 +1957,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
Ta bort filter
Nytt filter
Ange ett namn på det nya filtret. Det kommer att läggas till på fliken ’Kategorier’.
- "Transkribera om %1$s namn saknas"
+ Transkribera om %1$s namn saknas
Hoppa över nerladdning av kartor
Välj en annan region
Obegränsade nedladdningar av kartor, uppdateringar och Wikipedia-plugin.
@@ -1960,7 +1981,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
Donation till OpenStreetMap-gemenskapen
Skaffa det
Skaffa för %1$s
- "Du har inte några offline-kartor installerade. Du kan välja en karta från listan eller hämta kartor senare via \'Meny - %1$s\'."
+ Du har inte några offline-kartor installerade. Du kan välja en karta från listan eller hämta kartor senare via \'Meny - %1$s\'.
Söker efter kartor …
Erhåll vägbeskrivningar och upptäck nya platser utan Internetuppkoppling
Sök efter min plats
@@ -2047,7 +2068,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
Ogiltig OLC
\n
Kort OLC
-Vänligen tillhandahåll fullständig kod
+\nVänligen tillhandahåll fullständig kod
Filen kan inte flyttas.
Flytta
Spår
@@ -2090,7 +2111,7 @@ Vänligen tillhandahåll fullständig kod
Åtgärdsnamn
Kartöverlägg
Lägg till överlägg
- "Kartöverlägget har ändrats till \"%s\"."
+ Kartöverlägget har ändrats till \"%s\".
Tryck länge och dra knappen för att ändra dess position på skärmen.
Använd höjddata
Visa djupkonturer och punkter.
@@ -2420,7 +2441,9 @@ Vänligen tillhandahåll fullständig kod
Max/Min
Min/Max
Denna väg kan vara för lång tid att beräkna. Lägg till mellanliggande destinationer om inget resultat finns inom 10 minuter.
- "OsmAnd (OSM Automated Navigation Directions) är en kartnavigationsapp med tillgång till gratis, världsomfattande OpenStreetMap (OSM)-data av hög kvalitet. Njut av röstnavigation eller visuell navigation, visning av POI (points of interest - nyttoplatser), att skapa och hantera GPX-spår, visa höjdkurvor och höjdinfo (via plugin), val mellan bil-, cykel-, fotgängar-lägen, OSM-redigering och mycket mer."
+ OsmAnd (OSM Automated Navigation Directions) är en kartnavigationsapp med tillgång till gratis, världsomfattande OpenStreetMap (OSM)-data av hög kvalitet.
+\n
+\nNjut av röstnavigation eller visuell navigation, visning av POI (points of interest - nyttoplatser), att skapa och hantera GPX-spår, visa höjdkurvor och höjdinfo (via plugin), val mellan bil-, cykel-, fotgängar-lägen, OSM-redigering och mycket mer.
GPS-navigering
\n• Välj mellan offline- (inga roaming-avgifter när du är utomlands) eller online-läge a(snabbare)
\n• Steg-för-steg röstguidning leder dig längs vägen (inspelade och genererade röster)
@@ -2442,8 +2465,14 @@ Vänligen tillhandahåll fullständig kod
\n • Låter dig välja hur du vill visa namn på kartan: på svenska, lokala, eller fonetisk stavning
\n • Visar specialiserade online-rutor, satellitvy (från Bing), olika överlägg som tour/navigering GPX-spår och ytterligare lager med anpassningsbar transparens
\n
- Skidåkning OsmAnd skidkartor plugin gör att du kan se skidspår svårighetsgrad och en del kompletterande information, som plats för liftar och andra faciliteter.
- Cykling • Du kan hitta cykelstigar på kartan • GPS-navigering i cykelläge skapar din rutt med hjälp av cykelvägar • Du kan se din hastighet och höjd • Med GPX-inspelningsalternativet kan du spela in din resa och dela den • Via ytterligare plugin kan du aktivera visning av höjdkurvor och höjdrelief
+ Skidåkning
+\nOsmAnd skidkartor plugin gör att du kan se skidspår svårighetsgrad och en del kompletterande information, som plats för liftar och andra faciliteter.
+ Cykling
+\n• Hitta cykelvägar på kartan
+\n• GPS-navigering i cykelläge bygger din rutt med cykelvägar
+\n• Se din hastighet och höjd
+\n• Med GPX-inspelningsalternativ kan du spela in din resa och dela den
+\n• Via ett extra plugin kan du aktivera konturlinjer och backskuggning
Promenader, vandring, stadsrundtur
\n • Kartan visar promenad- och vandringsleder
\n • Wikipedia på ditt föredragna språk kan berätta en hel del under en stadsrundtur
@@ -2458,23 +2487,58 @@ Vänligen tillhandahåll fullständig kod
\n
Rensa alla mellanliggande punkter
Strömsporter
- OsmAnd är open-source och är utvecklas aktivt. Alla kan bidra till appen genom att rapportera buggar, förbättra översättningar eller programmera nya funktioner. Projektet är i ett dynamiskt tillstånd av kontinuerlig förbättring av alla dessa former genom utvecklare och interaktion med användare. Projektet är också beroende av ekonomiska bidrag för att finansiera kodning och testning av nya funktioner. Ungefärlig karttäckning och kvalitet: • Västeuropa: **** • Östeuropa: *** • Ryssland: *** • Nordamerika: *** • Sydamerika: ** • Asien: ** • Japan & Korea: *** • Mellanöstern: ** • Afrika: ** • Antarktis: * De flesta länder runt om i världen finns tillgängliga för hämtning! Få en tillförlitlig navigator i ditt land - det kan vara Tyskland, Frankrike, Mexiko, Storbritannien, Spanien, Nederländerna, USA, Ryssland, Brasilien eller något annat.
- OsmAnd+ (OSM Automated Navigation Directions)
+ OsmAnd är aktivt utvecklad programvara med öppen källkod. Alla kan bidra till appen genom att rapportera fel, förbättra översättningar eller koda nya funktioner. Dessutom bygger projektet på ekonomiska bidrag för att finansiera kodning och testning av nya funktioner.
+\nUngefärlig karttäckning och kvalitet:
+\n• Västeuropa: ****
+\n• Östeuropa: ***
+\n• Ryssland: ***
+\n• Nordamerika: ***
+\n• Sydamerika: **
+\n• Asien: **
+\n• Japan och Korea: ***
+\n• Mellanöstern: **
+\n• Afrika: **
+\n• Antarktis: *
+\nDe flesta länder runt om i världen är tillgängliga för nedladdning!
+\nFå en pålitlig navigatör i ditt land - vare sig det är Frankrike, Tyskland, Mexiko, Storbritannien, Spanien, Nederländerna, USA, Ryssland, Brasilien eller något annat.
+ OsmAnd + (OSM Automated Navigation Directions)
\n
-\nOsmAnd+ är ett open source-navigationsapp med tillgång till ett brett utbud av global OpenStreetMap(OSM)-data. Alla kartdata (vektor- eller rasterkartor) kan sparas på telefonens minneskort för användning offline. OsmAnd erbjuder även offline och online-ruttunktioner, inklusive turn-by-turn röstguidning.
+\nOsmAnd + är en programvara för programvara med öppen källkod för navigering med tillgång till ett stort antal globala OSM-data. Alla kartdata (vektor- eller brickor) kan lagras på telefonens minneskort för offline-användning. Offline- och online-dirigeringsfunktioner erbjuds också, inklusive röstvägledning för sväng.
\n
-\nOsmAnd+ är den betalversionenen av appeb, genom att köpa det stödjer du projektet, finansierar utveckling av nya funktioner, och får de senaste uppdateringarna.
+\nOsmAnd + är den betalda appversionen, genom att köpa den stöder du projektet, finansierar utvecklingen av nya funktioner och får de senaste uppdateringarna.
\n
-\nNågra av de centrala funktionerna: - Komplett offline-funktionalitet (spara vektor- eller rasterkartor i enhetens lagring) - Kompakta offline vektorkartor för hela världen finns tillgängliga - Obegränsad hämtning av land- eller regionkartor direkt från appen - Offline Wikipedia-artiklar (hämta Wikipedia-POI), utmärkt för sightseeing
+\nNågra av kärnfunktionerna:
+\n- Komplett offline-funktionalitet (lagra nedladdad vektor eller kakelkartor i enhetens lagring)
+\n- Kompakta offlinevektorkartor för hela världen
+\n- Obegränsad nedladdning av land- eller regionkartor direkt från appen
+\n- Offline Wikipedia-funktion (ladda ner Wikipedia POI), perfekt för sightseeing
+\n- Överlagring av flera kartlager möjliga, som GPX eller navigationsspår, intressanta platser, favoriter, konturlinjer, kollektivtrafikstopp, ytterligare kartor med anpassningsbar transparens
\n
-\n - Överlagring av flera kartskikt är möjligt, som GPX eller navigeringsspår, Punkter av Intresse, favoriter, höjdkurvor, hållplatser för kollektivtrafiken, fler kartor med anpassningsbar genomskinlighet- Offlinesökning efter adresser och intressepunkter (POI) - Offline routing för mediumdistansavstånd - Bil-, cykel- och fotgängarelägen med: - tillval automatiskt byte av dag/nattläge -
-\n
-\n - Valfri hastighetsbunden kartzoom - valfri kartjustering enligt kompass eller riktning - som tillval körfältsguide, hastighetsgräns visas, inspelade- och TTS-röster
+\n- Offline sökning efter adresser och platser (POI)
+\n- Offline-dirigering för medelstora avstånd
+\n- Lägen för bil, cykel och fotgängare med tillval:
+\n- Automatisk växling mellan dag och natt
+\n- Hastighetsberoende kartzoomning
+\n- Kartinriktning enligt kompass eller rörelseriktning
+\n- Fältvägledning, hastighetsgränsvisning, inspelade och text-till-tal-röster
+\n
Kunde inte hitta något inom:
Lägg till alla spårens vägpunkter, eller välj separata kategorier.
Totalt
- OsmAnd+ (OSM Automated Navigation Directions) är en kartnavigationsapp med tillgång till gratis världsomfattande och högkvalitativa OpenStreetMap (OSM)-data. Njut av röst- och visuell navigation, visning av POI (points of interest - intressepunkter), att skapa och hantera GPX-spår, se höjdkurvor och höjdinfo, välja mellan bil-cykel- och fotgängarlägen, OSM-redigering och mycket mer. OsmAnd+ är en betalversion av appen. Genom att köpa den, stödjer du projektet, finansierar utveckling av nya funktioner, och får de senaste uppdateringarna. Några av de viktigaste funktionerna:
- Navigering • Fungerar på nätet (snabb) eller offline (inga roaming-avgifter när du är utomlands) • Sväng-för-sväng-röstguidning (inspelade och syntetiska röster) • Valfri körfältsguide, gatunamn visas, och beräknad ankomsttid • Stödjer mellanliggande punkter på din resplan • Automatisk omdirigering när du avviker från rutten • Sök platser efter adress eller typ (t ex: restaurang, hotell, bensinstation, museum), eller med geografiska koordinater
+ OsmAnd+ (OSM Automated Navigation Directions) är en kartnavigationsapp med tillgång till gratis världsomfattande och högkvalitativa OSM-data.
+\nNjut av röst- och visuell navigation, visning av POI (points of interest - intressepunkter), att skapa och hantera GPX-spår, se höjdkurvor och höjdinfo, välja mellan bil-cykel- och fotgängarlägen, OSM-redigering och mycket mer.
+\n
+\nOsmAnd+ är en betalversion av appen. Genom att köpa den, stödjer du projektet, finansierar utveckling av nya funktioner, och får de senaste uppdateringarna.
+\n
+\nNågra av de viktigaste funktionerna:
+ Navigering
+\n• Fungerar online (snabbt) eller offline (inga roamingavgifter när du är utomlands)
+\n• Röstvägledning för sväng (inspelade och syntetiserade röster)
+\n• Valfri körvägledning, visning av gatunamn och beräknad ankomsttid
+\n• Stöder mellanliggande poäng på din resplan
+\n• Automatisk omdirigering när du avviker från rutten
+\n• Sök efter platser efter adress, efter typ (t.ex. restaurang, hotell, bensinstation, museum) eller efter geografiska koordinater
+\n
Kartvisning
\n • Visa din position och orientering
\n • Eventuellt justera bilden i förhållande till kompass eller din riktning
@@ -2490,8 +2554,7 @@ Vänligen tillhandahåll fullständig kod
Namnet innehåller för många versaler. Vill du fortsätta?
Knackning på åtgärdsknappen kommer att lägga till en GPX-punkt vid skärmens mitt.
Knackning på åtgärdsknappen kommer att lägga en ljudanteckning vid skärmens mitt.
- Att trycka på denna åtgärdsknapp lägger
-\ntill en videoanteckning mitt på skärmen.
+ Att trycka på denna åtgärdsknapp lägger till en videoanteckning mitt på skärmen.
Knackning på åtgärdsknappen kommer att lägga till en fotoanteckning vid skärmens mitt.
Knackning på åtgärdsknappen kommer att lägga till en OSM-anteckning vid skärmens mitt.
Knackning på åtgärdsknappen kommer att lägga till en Intressepunkt vid skärmens mitt.
@@ -2600,7 +2663,13 @@ Vänligen tillhandahåll fullständig kod
\n• Valfri hastighetsbaserad zoomning
\n• Dela din position så att dina vänner kan hitta dig
\n
- Funktioner för cykel och gående • Se vägar för gående och cyklande samt vandringsstigar, utmärkta för utomhusaktiviteter • Speciella ruttval och visningsläge för cykel och gående • Valfria kollektivtrafiksplatser (buss, spårvagn, tåg) inklusive linjenamn • Valfri reseinspelning till lokal GPX-fil eller onlinetjänst • Valfri visning av hastighet och höjd • Visa konturlinjer och höjdreliefer (via separat plugin)
+ Funktioner för cykel och gående
+\n• Se vägar för gående och cyklande samt vandringsstigar, utmärkta för utomhusaktiviteter
+\n• Speciella ruttval och visningsläge för cykel och gående
+\n• Valfria kollektivtrafiksplatser (buss, spårvagn, tåg) inklusive linjenamn
+\n• Valfri reseinspelning till lokal GPX-fil eller onlinetjänst
+\n• Valfri visning av hastighet och höjd
+\n• Visa konturlinjer och höjdreliefer (via separat plugin)
Bidra direkt till OSM
\n• Rapportera databuggar
\n• Ladda upp GPX-spår till OSM direkt från appen
@@ -3267,4 +3336,9 @@ Vänligen tillhandahåll fullständig kod
Spåret innehåller inte höjddata.
Spåret innehåller inte hastighetsdata.
Välj en annan typ av färgning.
+ Spara riktning till varje spårningspunkt under inspelning.
+ Go-cart
+ Loggningsintervall ställde in den tidsperiod under vilken OsmAnd kommer att be om aktuell positionspositionsdata.
+ Spara och fortsätt
+ All osparad data kommer att försvinna.
\ No newline at end of file
diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml
index 054c932cc6..262ec98674 100644
--- a/OsmAnd/res/values-uk/strings.xml
+++ b/OsmAnd/res/values-uk/strings.xml
@@ -4044,4 +4044,7 @@
Виберіть інший тип забарвлення.
Сховати природні заповідники, заповідні території та межі національних парків
Межі природи
+ Інтервал журналювання встановлює проміжок часу, впродовж якого OsmAnd запитуватиме дані про поточне розташування.
+ Зберегти й продовжити
+ Усі незбережені дані буде втрачено.
\ No newline at end of file
diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml
index 4ffbbadc5c..4bef29c778 100644
--- a/OsmAnd/res/values-zh-rTW/strings.xml
+++ b/OsmAnd/res/values-zh-rTW/strings.xml
@@ -4038,4 +4038,7 @@
請選擇另一種顏色。
隱藏自然保留區、保護區與國家公園界線
自然界線
+ 紀錄間隔設定的時段,OsmAnd 將會要求目前位置的位置資料。
+ 儲存並繼續
+ 所有未儲存的資料都將會遺失。
\ No newline at end of file
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index 5a52b1bf96..bfb443020a 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -11,6 +11,17 @@
Thx - Hardy
-->
+
+
+ • OsmAnd Live updates moved to \"Downloads > Updates\"\n\n
+ • Tracks now could be colorizing by altitude, speed, or slope.\n\n
+ • Added option to change the appearance of the navigation route line\n\n
+ • Updated \"Trip recording\" dialog\n\n
+
+ Specify color for map mode: %1$s.
+ Route line would be use %1$s specified on selected map style: %2$s.
+ Route line
+ Customize route line
If disabled, recording will start right after tap on the widget or menu item, skipping the confirmation dialog.
Show start dialog
All unsaved data will be lost.
diff --git a/OsmAnd/res/xml/profile_appearance.xml b/OsmAnd/res/xml/profile_appearance.xml
index 87ec511b69..b037591e16 100644
--- a/OsmAnd/res/xml/profile_appearance.xml
+++ b/OsmAnd/res/xml/profile_appearance.xml
@@ -76,4 +76,11 @@
android:title="@string/select_navigation_icon"
android:selectable="false"/>
+
+
\ No newline at end of file
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
index 487f4d902f..953691b272 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
@@ -125,6 +125,7 @@ import net.osmand.plus.settings.datastorage.DataStorageFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.plus.settings.fragments.ConfigureProfileFragment;
+import net.osmand.plus.settings.fragments.RouteLineAppearanceFragment;
import net.osmand.plus.track.TrackAppearanceFragment;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
@@ -2265,6 +2266,10 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
return getFragment(TrackMenuFragment.TAG);
}
+ public RouteLineAppearanceFragment getRouteLineAppearanceFragment() {
+ return getFragment(RouteLineAppearanceFragment.TAG);
+ }
+
public void backToConfigureProfileFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
int backStackEntryCount = fragmentManager.getBackStackEntryCount();
diff --git a/OsmAnd/src/net/osmand/plus/dialogs/SelectMapStyleBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/SelectMapStyleBottomSheetDialogFragment.java
index f5515f11bd..96c84bfd01 100644
--- a/OsmAnd/src/net/osmand/plus/dialogs/SelectMapStyleBottomSheetDialogFragment.java
+++ b/OsmAnd/src/net/osmand/plus/dialogs/SelectMapStyleBottomSheetDialogFragment.java
@@ -193,10 +193,7 @@ public class SelectMapStyleBottomSheetDialogFragment extends MenuBottomSheetDial
List names = new ArrayList<>(renderers.keySet());
for (String name : names) {
- String translation = RendererRegistry.getTranslatedRendererName(context, name);
- if (translation == null) {
- translation = name.replace('_', ' ').replace('-', ' ');
- }
+ String translation = RendererRegistry.getRendererName(context, name);
res.put(translation, name);
}
diff --git a/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java
index 6225bea95d..6b7640bf1b 100644
--- a/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java
+++ b/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java
@@ -30,7 +30,7 @@ public class WhatsNewDialogFragment extends DialogFragment {
final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication();
final String appVersion = Version.getAppVersion(osmandApplication);
builder.setTitle(getString(R.string.whats_new) + " " + appVersion)
- .setMessage(getString(R.string.release_3_9))
+ .setMessage(getString(R.string.release_4_0_beta))
.setNegativeButton(R.string.shared_string_close, null);
if (AppInitializer.LATEST_CHANGES_URL != null) {
builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() {
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
index 9e88c5689f..49815c05dd 100644
--- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
@@ -106,6 +106,7 @@ import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCo
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.AFTER;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.ALL;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.BEFORE;
+import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener,
@@ -906,7 +907,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
case SnapTrackWarningFragment.CONTINUE_RESULT_CODE:
if (mapActivity != null) {
ApplicationMode mode = editingCtx.getAppMode();
- if (mode == ApplicationMode.DEFAULT || "public_transport".equals(mode.getRoutingProfile())) {
+ if (mode == ApplicationMode.DEFAULT || PUBLIC_TRANSPORT_KEY.equals(mode.getRoutingProfile())) {
mode = null;
}
List> pointsSegments = editingCtx.getPointsSegments(true, false);
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/ProfileCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/ProfileCard.java
index 179ad54645..8b6d615d9c 100644
--- a/OsmAnd/src/net/osmand/plus/measurementtool/ProfileCard.java
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/ProfileCard.java
@@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
+
public class ProfileCard extends BaseCard {
private ApplicationMode selectedMode;
@@ -42,7 +44,7 @@ public class ProfileCard extends BaseCard {
Iterator iterator = modes.iterator();
while (iterator.hasNext()) {
ApplicationMode mode = iterator.next();
- if ("public_transport".equals(mode.getRoutingProfile())) {
+ if (PUBLIC_TRANSPORT_KEY.equals(mode.getRoutingProfile())) {
iterator.remove();
}
}
diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java
index 12eff78327..fec2f6379d 100644
--- a/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java
+++ b/OsmAnd/src/net/osmand/plus/measurementtool/RouteBetweenPointsBottomSheetDialogFragment.java
@@ -35,6 +35,7 @@ import static net.osmand.plus.UiUtilities.CustomRadioButtonType.END;
import static net.osmand.plus.UiUtilities.CustomRadioButtonType.START;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.DEFAULT_APP_MODE;
import static net.osmand.plus.measurementtool.SelectFileBottomSheet.BOTTOM_SHEET_HEIGHT_DP;
+import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBehaviourDialogFragment {
@@ -116,7 +117,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBeha
for (int i = 0; i < modes.size(); i++) {
ApplicationMode mode = modes.get(i);
- if (!"public_transport".equals(mode.getRoutingProfile())) {
+ if (!PUBLIC_TRANSPORT_KEY.equals(mode.getRoutingProfile())) {
icon = app.getUIUtilities().getPaintedIcon(mode.getIconRes(), mode.getProfileColor(nightMode));
addProfileView(navigationType, onClickListener, i, icon, mode.toHumanString(), mode.equals(appMode));
}
diff --git a/OsmAnd/src/net/osmand/plus/quickaction/actions/MapStyleAction.java b/OsmAnd/src/net/osmand/plus/quickaction/actions/MapStyleAction.java
index a526954365..1bcac88a36 100644
--- a/OsmAnd/src/net/osmand/plus/quickaction/actions/MapStyleAction.java
+++ b/OsmAnd/src/net/osmand/plus/quickaction/actions/MapStyleAction.java
@@ -102,9 +102,7 @@ public class MapStyleAction extends SwitchableAction {
@Override
public String getTranslatedItemName(Context context, String item) {
- String translation = RendererRegistry.getTranslatedRendererName(context, item);
- return translation != null ? translation
- : item.replace('_', ' ').replace('-', ' ');
+ return RendererRegistry.getRendererName(context, item);
}
public List getFilteredStyles() {
@@ -175,9 +173,8 @@ public class MapStyleAction extends SwitchableAction {
List visibleNamesList = new ArrayList<>();
final List items = new ArrayList<>(renderers.keySet());
for (String item : items) {
- String translation = RendererRegistry.getTranslatedRendererName(activity, item);
- visibleNamesList.add(translation != null ? translation
- : item.replace('_', ' ').replace('-', ' '));
+ String name = RendererRegistry.getRendererName(activity, item);
+ visibleNamesList.add(name);
}
final ArrayAdapter arrayAdapter = new ArrayAdapter<>(themedContext, R.layout.dialog_text_item);
diff --git a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java
index 1b070e38a1..f015e790e0 100644
--- a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java
+++ b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java
@@ -289,6 +289,20 @@ public class RendererRegistry {
return renderers;
}
+ public String getSelectedRendererName() {
+ RenderingRulesStorage storage = getCurrentSelectedRenderer();
+ if (storage == null) {
+ return "";
+ }
+ return RendererRegistry.getRendererName(app, storage.getName());
+ }
+
+ public static String getRendererName(@NonNull Context ctx, @NonNull String name) {
+ String translation = getTranslatedRendererName(ctx, name);
+ return translation != null ? translation :
+ name.replace('_', ' ').replace('-', ' ');
+ }
+
@Nullable
public static String getTranslatedRendererName(@NonNull Context ctx, @NonNull String key) {
switch (key) {
diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java b/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java
new file mode 100644
index 0000000000..92cb926fa1
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/routing/RouteLineDrawInfo.java
@@ -0,0 +1,156 @@
+package net.osmand.plus.routing;
+
+import android.os.Bundle;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import net.osmand.util.Algorithms;
+
+public class RouteLineDrawInfo {
+
+ private static final String LINE_COLOR = "line_color";
+ private static final String LINE_WIDTH = "line_width";
+ private static final String NAVIGATION_ICON_ID = "navigation_icon_id";
+ private static final String NAVIGATION_ICON_COLOR = "navigation_icon_color";
+ private static final String CENTER_X = "center_x";
+ private static final String CENTER_Y = "center_y";
+ private static final String SCREEN_HEIGHT = "screen_height";
+
+ // parameters to save
+ @ColorInt
+ private Integer color;
+ private String width;
+
+ // temporally parameters to show in preview
+ @ColorInt
+ private int iconColor;
+ private int iconId;
+ private int centerX;
+ private int centerY;
+ private int screenHeight;
+
+ public RouteLineDrawInfo(@Nullable @ColorInt Integer color,
+ @Nullable String width) {
+ this.color = color;
+ this.width = width;
+ }
+
+ public RouteLineDrawInfo(@NonNull Bundle bundle) {
+ readBundle(bundle);
+ }
+
+ public RouteLineDrawInfo(@NonNull RouteLineDrawInfo existed) {
+ this.color = existed.color;
+ this.width = existed.width;
+ this.iconId = existed.iconId;
+ this.iconColor = existed.iconColor;
+ this.centerX = existed.centerX;
+ this.centerY = existed.centerY;
+ this.screenHeight = existed.screenHeight;
+ }
+
+ public void setColor(@Nullable Integer color) {
+ this.color = color;
+ }
+
+ public void setWidth(@Nullable String width) {
+ this.width = width;
+ }
+
+ public void setIconId(int iconId) {
+ this.iconId = iconId;
+ }
+
+ public void setIconColor(int iconColor) {
+ this.iconColor = iconColor;
+ }
+
+ public void setCenterX(int centerX) {
+ this.centerX = centerX;
+ }
+
+ public void setCenterY(int centerY) {
+ this.centerY = centerY;
+ }
+
+ public void setScreenHeight(int screenHeight) {
+ this.screenHeight = screenHeight;
+ }
+
+ @Nullable
+ public Integer getColor() {
+ return color;
+ }
+
+ @Nullable
+ public String getWidth() {
+ return width;
+ }
+
+ public int getIconId() {
+ return iconId;
+ }
+
+ @ColorInt
+ public int getIconColor() {
+ return iconColor;
+ }
+
+ public int getCenterX() {
+ return centerX;
+ }
+
+ public int getCenterY() {
+ return centerY;
+ }
+
+ public int getScreenHeight() {
+ return screenHeight;
+ }
+
+ private void readBundle(@NonNull Bundle bundle) {
+ if (bundle.containsKey(LINE_COLOR)) {
+ color = bundle.getInt(LINE_COLOR);
+ }
+ width = bundle.getString(LINE_WIDTH);
+ iconId = bundle.getInt(NAVIGATION_ICON_ID);
+ iconColor = bundle.getInt(NAVIGATION_ICON_COLOR);
+ centerX = bundle.getInt(CENTER_X);
+ centerY = bundle.getInt(CENTER_Y);
+ screenHeight = bundle.getInt(SCREEN_HEIGHT);
+ }
+
+ public void saveToBundle(@NonNull Bundle bundle) {
+ if (color != null) {
+ bundle.putInt(LINE_COLOR, color);
+ }
+ if (width != null) {
+ bundle.putString(LINE_WIDTH, width);
+ }
+ bundle.putInt(NAVIGATION_ICON_ID, iconId);
+ bundle.putInt(NAVIGATION_ICON_COLOR, iconColor);
+ bundle.putInt(CENTER_X, centerX);
+ bundle.putInt(CENTER_Y, centerY);
+ bundle.putInt(SCREEN_HEIGHT, screenHeight);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RouteLineDrawInfo)) return false;
+
+ RouteLineDrawInfo that = (RouteLineDrawInfo) o;
+
+ if (!Algorithms.objectEquals(getColor(), that.getColor())) return false;
+ return Algorithms.objectEquals(getWidth(), that.getWidth());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = color != null ? color.hashCode() : 0;
+ result = 31 * result + (width != null ? width.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java
index 637e3078e7..9f56f6d633 100644
--- a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java
+++ b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java
@@ -55,6 +55,8 @@ public class TransportRoutingHelper {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(TransportRoutingHelper.class);
+ public static final String PUBLIC_TRANSPORT_KEY = "public_transport";
+
private List> listeners = new LinkedList<>();
private final OsmandApplication app;
diff --git a/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java b/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java
new file mode 100644
index 0000000000..3eabe283e3
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineColorCard.java
@@ -0,0 +1,332 @@
+package net.osmand.plus.routing.cards;
+
+import android.content.Context;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.content.res.AppCompatResources;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.R;
+import net.osmand.plus.UiUtilities;
+import net.osmand.plus.activities.MapActivity;
+import net.osmand.plus.helpers.ColorDialogs;
+import net.osmand.plus.helpers.enums.DayNightMode;
+import net.osmand.plus.render.RendererRegistry;
+import net.osmand.plus.routepreparationmenu.cards.BaseCard;
+import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
+import net.osmand.plus.routing.RouteLineDrawInfo;
+import net.osmand.plus.settings.backend.ListStringPreference;
+import net.osmand.plus.track.AppearanceViewHolder;
+import net.osmand.plus.track.ColorsCard;
+import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
+import net.osmand.plus.widgets.MultiStateToggleButton;
+import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
+import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+public class RouteLineColorCard extends BaseCard implements CardListener, ColorPickerListener {
+
+ private static final int DAY_TITLE_ID = R.string.day;
+ private static final int NIGHT_TITLE_ID = R.string.night;
+
+ private final Fragment targetFragment;
+
+ private ColorsCard colorsCard;
+ private ColorTypeAdapter colorAdapter;
+ private RecyclerView groupRecyclerView;
+ private TextView tvColorName;
+ private TextView tvDescription;
+ private View themeToggleContainer;
+ private ViewGroup cardsContainer;
+
+ private ColorMode selectedMode;
+ private RouteLineDrawInfo routeLineDrawInfo;
+ private DayNightMode initMapTheme;
+ private DayNightMode selectedMapTheme;
+
+ private enum ColorMode {
+ DEFAULT(R.string.map_widget_renderer, R.drawable.ic_action_map_style),
+ CUSTOM(R.string.shared_string_custom, R.drawable.ic_action_settings);
+
+ ColorMode(int titleId, int iconId) {
+ this.titleId = titleId;
+ this.iconId = iconId;
+ }
+
+ int titleId;
+ int iconId;
+ }
+
+ public RouteLineColorCard(@NonNull MapActivity mapActivity,
+ @NonNull Fragment targetFragment,
+ @NonNull RouteLineDrawInfo routeLineDrawInfo,
+ @NonNull DayNightMode initMapTheme,
+ @NonNull DayNightMode selectedMapTheme) {
+ super(mapActivity);
+ this.targetFragment = targetFragment;
+ this.routeLineDrawInfo = routeLineDrawInfo;
+ this.initMapTheme = initMapTheme;
+ this.selectedMapTheme = selectedMapTheme;
+ }
+
+ @Override
+ public int getCardLayoutId() {
+ return R.layout.route_line_color_card;
+ }
+
+ @Override
+ protected void updateContent() {
+ tvColorName = view.findViewById(R.id.color_name);
+ tvDescription = view.findViewById(R.id.description);
+
+ colorAdapter = new ColorTypeAdapter();
+ groupRecyclerView = view.findViewById(R.id.recycler_view);
+ groupRecyclerView.setAdapter(colorAdapter);
+ groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
+
+ themeToggleContainer = view.findViewById(R.id.theme_toggle_container);
+ LinearLayout radioGroup = (LinearLayout) view.findViewById(R.id.custom_radio_buttons);
+ setupRadioGroup(radioGroup);
+
+ cardsContainer = (ViewGroup) view.findViewById(R.id.colors_card_container);
+ createColorSelector(cardsContainer);
+
+ initSelectedMode();
+ }
+
+ private void initSelectedMode() {
+ selectedMode = routeLineDrawInfo.getColor() == null ? ColorMode.DEFAULT : ColorMode.CUSTOM;
+ modeChanged();
+ }
+
+ private void modeChanged() {
+ if (selectedMode == ColorMode.DEFAULT) {
+ themeToggleContainer.setVisibility(View.GONE);
+ cardsContainer.setVisibility(View.GONE);
+ changeMapTheme(initMapTheme);
+ } else {
+ themeToggleContainer.setVisibility(View.VISIBLE);
+ cardsContainer.setVisibility(View.VISIBLE);
+ changeMapTheme(isNightMap() ? DayNightMode.NIGHT : DayNightMode.DAY);
+ }
+ updateSelectedColor();
+ updateDescription();
+ }
+
+ private void setupRadioGroup(LinearLayout buttonsContainer) {
+ RadioItem day = createMapThemeButton(false);
+ RadioItem night = createMapThemeButton(true);
+
+ MultiStateToggleButton radioGroup = new MultiStateToggleButton(app, buttonsContainer, nightMode);
+ radioGroup.setItems(day, night);
+
+ radioGroup.setSelectedItem(!isNightMap() ? day : night);
+ }
+
+ private RadioItem createMapThemeButton(final boolean isNight) {
+ RadioItem item = new RadioItem(app.getString(!isNight ? DAY_TITLE_ID : NIGHT_TITLE_ID));
+ item.setOnClickListener(new OnRadioItemClickListener() {
+ @Override
+ public boolean onRadioItemClick(RadioItem radioItem, View view) {
+ selectedMapTheme = isNight ? DayNightMode.NIGHT : DayNightMode.DAY;
+ changeMapTheme(selectedMapTheme);
+ updateDescription();
+ return true;
+ }
+ });
+ return item;
+ }
+
+ private void changeMapTheme(DayNightMode mapTheme) {
+ if (targetFragment instanceof OnMapThemeUpdateListener) {
+ ((OnMapThemeUpdateListener) targetFragment).onMapThemeUpdated(mapTheme);
+ }
+ }
+
+ private void createColorSelector(ViewGroup container) {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ List colors = new ArrayList<>();
+ for (int color : ColorDialogs.pallette) {
+ colors.add(color);
+ }
+ Integer selectedColor = routeLineDrawInfo.getColor();
+ if (selectedColor != null) {
+ if (!ColorDialogs.isPaletteColor(selectedColor)) {
+ colors.add(selectedColor);
+ }
+ } else {
+ selectedColor = colors.get(0);
+ }
+ ListStringPreference preference = app.getSettings().CUSTOM_ROUTE_LINE_COLORS;
+ colorsCard = new ColorsCard(mapActivity, selectedColor, targetFragment, colors, preference, null);
+ colorsCard.setListener(this);
+ container.addView(colorsCard.build(mapActivity));
+ }
+ }
+
+ @Override
+ public void onColorSelected(Integer prevColor, int newColor) {
+ colorsCard.onColorSelected(prevColor, newColor);
+ updateSelectedColor();
+ }
+
+ private void updateSelectedColor() {
+ Integer color = selectedMode == ColorMode.CUSTOM ? colorsCard.getSelectedColor() : null;
+ routeLineDrawInfo.setColor(color);
+ updateColorName();
+ if (targetFragment instanceof OnSelectedColorChangeListener) {
+ ((OnSelectedColorChangeListener) targetFragment).onSelectedColorChanged();
+ }
+ }
+
+ private void updateColorName() {
+ if (selectedMode == ColorMode.DEFAULT) {
+ tvColorName.setText(app.getString(R.string.map_widget_renderer));
+ } else if (routeLineDrawInfo.getColor() != null) {
+ int colorNameId = ColorDialogs.getColorName(routeLineDrawInfo.getColor());
+ tvColorName.setText(app.getString(colorNameId));
+ }
+ }
+
+ private void updateDescription() {
+ String description;
+ if (selectedMode == ColorMode.DEFAULT) {
+ String pattern = app.getString(R.string.route_line_use_map_style_appearance);
+ String color = app.getString(R.string.shared_string_color).toLowerCase();
+ description = String.format(pattern, color, app.getRendererRegistry().getSelectedRendererName());
+ } else {
+ String pattern = app.getString(R.string.specify_color_for_map_mode);
+ String mapModeTitle = app.getString(isNightMap() ? NIGHT_TITLE_ID : DAY_TITLE_ID);
+ description = String.format(pattern, mapModeTitle.toLowerCase());
+ }
+ tvDescription.setText(description);
+ }
+
+ private boolean isNightMap() {
+ return selectedMapTheme.isNight();
+ }
+
+ @Override
+ public void onCardLayoutNeeded(@NonNull BaseCard card) {
+
+ }
+
+ @Override
+ public void onCardPressed(@NonNull BaseCard card) {
+ if (card instanceof ColorsCard) {
+ updateSelectedColor();
+ }
+ }
+
+ @Override
+ public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) {
+
+ }
+
+ private class ColorTypeAdapter extends RecyclerView.Adapter {
+
+ private List items = Arrays.asList(ColorMode.values());
+
+ @NonNull
+ @Override
+ public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
+ View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
+ view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
+ view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
+
+ AppearanceViewHolder holder = new AppearanceViewHolder(view);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
+ R.drawable.ripple_solid_dark_6dp);
+ }
+ return holder;
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
+ ColorMode item = items.get(position);
+ holder.title.setText(app.getString(item.titleId));
+
+ updateButtonBg(holder, item);
+ updateTextAndIconColor(holder, item);
+
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ selectedMode = items.get(holder.getAdapterPosition());
+ notifyItemRangeChanged(0, getItemCount());
+
+ modeChanged();
+
+ CardListener listener = getListener();
+ if (listener != null) {
+ listener.onCardPressed(RouteLineColorCard.this);
+ }
+ }
+ });
+ }
+
+ private void updateButtonBg(AppearanceViewHolder holder, ColorMode item) {
+ GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
+ if (rectContourDrawable != null) {
+ if (selectedMode == item) {
+ int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
+ rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
+ } else {
+ int strokeColor = ContextCompat.getColor(app, nightMode ?
+ R.color.stroked_buttons_and_links_outline_dark :
+ R.color.stroked_buttons_and_links_outline_light);
+ rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
+ }
+ holder.button.setImageDrawable(rectContourDrawable);
+ }
+ }
+
+ private void updateTextAndIconColor(AppearanceViewHolder holder, ColorMode item) {
+ Context ctx = holder.itemView.getContext();
+ int iconColorId;
+ int textColorId;
+
+ if (selectedMode == item) {
+ iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.default_icon_color);
+ textColorId = AndroidUtils.getColorFromAttr(ctx, android.R.attr.textColor);
+ } else {
+ iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary);
+ textColorId = iconColorId;
+ }
+
+ holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.iconId, iconColorId));
+ holder.title.setTextColor(textColorId);
+ }
+
+ @Override
+ public int getItemCount() {
+ return items.size();
+ }
+ }
+
+ public interface OnSelectedColorChangeListener {
+ void onSelectedColorChanged();
+ }
+
+ public interface OnMapThemeUpdateListener {
+ void onMapThemeUpdated(@NonNull DayNightMode mapTheme);
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineWidthCard.java b/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineWidthCard.java
new file mode 100644
index 0000000000..95c20783a4
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/routing/cards/RouteLineWidthCard.java
@@ -0,0 +1,305 @@
+package net.osmand.plus.routing.cards;
+
+import android.content.Context;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.content.res.AppCompatResources;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.github.ksoichiro.android.observablescrollview.ScrollUtils;
+import com.google.android.material.slider.Slider;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.R;
+import net.osmand.plus.UiUtilities;
+import net.osmand.plus.activities.MapActivity;
+import net.osmand.plus.helpers.AndroidUiHelper;
+import net.osmand.plus.render.RendererRegistry;
+import net.osmand.plus.routepreparationmenu.cards.BaseCard;
+import net.osmand.plus.routing.RouteLineDrawInfo;
+import net.osmand.plus.track.AppearanceViewHolder;
+import net.osmand.plus.track.TrackAppearanceFragment.OnNeedScrollListener;
+import net.osmand.util.Algorithms;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class RouteLineWidthCard extends BaseCard {
+
+ private final static int CUSTOM_WIDTH_MIN = 1;
+ private final static int CUSTOM_WIDTH_MAX = 24;
+
+ private RouteLineDrawInfo routeLineDrawInfo;
+ private OnNeedScrollListener onNeedScrollListener;
+
+ private WidthMode selectedMode;
+
+ private WidthAdapter widthAdapter;
+ private View sliderContainer;
+ private RecyclerView groupRecyclerView;
+ private TextView tvModeType;
+ private TextView tvDescription;
+
+ private enum WidthMode {
+ DEFAULT(R.string.map_widget_renderer, R.drawable.ic_action_map_style, null),
+ THIN(R.string.rendering_value_thin_name, R.drawable.ic_action_track_line_thin_color, "thin"),
+ MEDIUM(R.string.rendering_value_medium_name, R.drawable.ic_action_track_line_medium_color, "medium"),
+ THICK(R.string.rendering_value_bold_name, R.drawable.ic_action_track_line_bold_color, "bold"),
+ CUSTOM(R.string.shared_string_custom, R.drawable.ic_action_settings, null);
+
+ WidthMode(int titleId, int iconId, String widthKey) {
+ this.titleId = titleId;
+ this.iconId = iconId;
+ this.widthKey = widthKey;
+ }
+
+ int titleId;
+ int iconId;
+ String widthKey;
+ }
+
+ public RouteLineWidthCard(@NonNull MapActivity mapActivity,
+ @NonNull RouteLineDrawInfo routeLineDrawInfo,
+ @NonNull OnNeedScrollListener onNeedScrollListener) {
+ super(mapActivity);
+ this.routeLineDrawInfo = routeLineDrawInfo;
+ this.onNeedScrollListener = onNeedScrollListener;
+ }
+
+ @Override
+ public int getCardLayoutId() {
+ return R.layout.route_line_width_card;
+ }
+
+ @Override
+ protected void updateContent() {
+ widthAdapter = new WidthAdapter();
+ groupRecyclerView = view.findViewById(R.id.recycler_view);
+ groupRecyclerView.setAdapter(widthAdapter);
+ groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
+
+ tvModeType = view.findViewById(R.id.width_type);
+ tvDescription = view.findViewById(R.id.description);
+ sliderContainer = view.findViewById(R.id.slider_container);
+ AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider());
+
+ initSelectedMode();
+ }
+
+ private void initSelectedMode() {
+ selectedMode = findAppropriateMode(getRouteLineWidth());
+ modeChanged();
+ }
+
+ private void modeChanged() {
+ updateHeader();
+ updateDescription();
+ updateCustomWidthSlider();
+ scrollMenuToSelectedItem();
+ }
+
+ public void updateItems() {
+ if (widthAdapter != null) {
+ widthAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void setRouteLineWidth(String widthKey) {
+ routeLineDrawInfo.setWidth(widthKey);
+ mapActivity.refreshMap();
+ }
+
+ private String getRouteLineWidth() {
+ return routeLineDrawInfo.getWidth();
+ }
+
+ private void updateHeader() {
+ tvModeType.setText(app.getString(selectedMode.titleId));
+ }
+
+ private void updateDescription() {
+ if (selectedMode == WidthMode.DEFAULT) {
+ String pattern = app.getString(R.string.route_line_use_map_style_appearance);
+ String width = app.getString(R.string.shared_string_color).toLowerCase();
+ String description = String.format(pattern, width, app.getRendererRegistry().getSelectedRendererName());
+ tvDescription.setText(description);
+ tvDescription.setVisibility(View.VISIBLE);
+ } else {
+ tvDescription.setVisibility(View.GONE);
+ }
+ }
+
+ private void updateCustomWidthSlider() {
+ if (selectedMode == WidthMode.CUSTOM) {
+ Slider slider = view.findViewById(R.id.width_slider);
+ final TextView tvCustomWidth = view.findViewById(R.id.width_value_tv);
+
+ slider.setValueTo(CUSTOM_WIDTH_MAX);
+ slider.setValueFrom(CUSTOM_WIDTH_MIN);
+
+ ((TextView) view.findViewById(R.id.width_value_min)).setText(String.valueOf(CUSTOM_WIDTH_MIN));
+ ((TextView) view.findViewById(R.id.width_value_max)).setText(String.valueOf(CUSTOM_WIDTH_MAX));
+
+ String widthKey = getRouteLineWidth();
+ int width = Algorithms.parseIntSilently(widthKey, 1);
+ widthKey = String.valueOf(width);
+ setRouteLineWidth(widthKey);
+ tvCustomWidth.setText(widthKey);
+ slider.setValue(width);
+
+ slider.addOnChangeListener(new Slider.OnChangeListener() {
+ @Override
+ public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
+ if (fromUser) {
+ String newWidth = String.valueOf((int) value);
+ setRouteLineWidth(newWidth);
+ tvCustomWidth.setText(newWidth);
+ }
+ }
+ });
+ UiUtilities.setupSlider(slider, nightMode, null, true);
+ ScrollUtils.addOnGlobalLayoutListener(sliderContainer, new Runnable() {
+ @Override
+ public void run() {
+ if (sliderContainer.getVisibility() == View.VISIBLE) {
+ onNeedScrollListener.onVerticalScrollNeeded(sliderContainer.getBottom());
+ }
+ }
+ });
+ AndroidUiHelper.updateVisibility(sliderContainer, true);
+ } else {
+ AndroidUiHelper.updateVisibility(sliderContainer, false);
+ }
+ }
+
+ private void scrollMenuToSelectedItem() {
+ int position = widthAdapter.getItemPosition(selectedMode);
+ if (position != -1) {
+ groupRecyclerView.scrollToPosition(position);
+ }
+ }
+
+ private static WidthMode findAppropriateMode(@Nullable String widthKey) {
+ if (widthKey != null) {
+ for (WidthMode mode : WidthMode.values()) {
+ if (mode.widthKey != null && mode.widthKey.equals(widthKey)) {
+ return mode;
+ }
+ }
+ return WidthMode.CUSTOM;
+ }
+ return WidthMode.DEFAULT;
+ }
+
+ private class WidthAdapter extends RecyclerView.Adapter {
+
+ private final List items = Arrays.asList(WidthMode.values());
+
+ @NonNull
+ @Override
+ public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
+ View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
+ view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
+ view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
+
+ AppearanceViewHolder holder = new AppearanceViewHolder(view);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
+ R.drawable.ripple_solid_dark_6dp);
+ }
+ return holder;
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
+ WidthMode item = items.get(position);
+ holder.title.setText(app.getString(item.titleId));
+
+ updateButtonBg(holder, item);
+ updateTextAndIconColor(holder, item);
+
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int prevSelectedPosition = getItemPosition(selectedMode);
+ selectedMode = items.get(holder.getAdapterPosition());
+ notifyItemChanged(holder.getAdapterPosition());
+ notifyItemChanged(prevSelectedPosition);
+
+ if (selectedMode != WidthMode.CUSTOM) {
+ setRouteLineWidth(selectedMode.widthKey);
+ }
+ modeChanged();
+
+ CardListener listener = getListener();
+ if (listener != null) {
+ listener.onCardPressed(RouteLineWidthCard.this);
+ }
+ }
+ });
+ }
+
+ private void updateTextAndIconColor(AppearanceViewHolder holder, WidthMode item) {
+ Context ctx = holder.itemView.getContext();
+ int iconColor;
+ int textColorId;
+
+ if (selectedMode == item) {
+ iconColor = getIconColor(item, AndroidUtils.getColorFromAttr(ctx, R.attr.default_icon_color));
+ textColorId = AndroidUtils.getColorFromAttr(ctx, android.R.attr.textColor);
+ } else {
+ iconColor = getIconColor(item, AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary));
+ textColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary);
+ }
+
+ holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.iconId, iconColor));
+ holder.title.setTextColor(textColorId);
+ }
+
+ private int getIconColor(@NonNull WidthMode mode, @ColorInt int defaultColor) {
+ return mode.widthKey != null ? getRouteLineColor() : defaultColor;
+ }
+
+ private int getRouteLineColor() {
+ Integer color = routeLineDrawInfo.getColor();
+ return color != null ? color :
+ mapActivity.getMapLayers().getRouteLayer().getRouteLineColor(nightMode);
+ }
+
+ private void updateButtonBg(AppearanceViewHolder holder, WidthMode item) {
+ GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
+ if (rectContourDrawable != null) {
+ if (selectedMode == item) {
+ int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
+ rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
+ } else {
+ int strokeColor = ContextCompat.getColor(app, nightMode ?
+ R.color.stroked_buttons_and_links_outline_dark
+ : R.color.stroked_buttons_and_links_outline_light);
+ rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
+ }
+ holder.button.setImageDrawable(rectContourDrawable);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return items.size();
+ }
+
+ int getItemPosition(WidthMode widthMode) {
+ return items.indexOf(widthMode);
+ }
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java
index 2d99edfc34..5fbc34e674 100644
--- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java
@@ -84,6 +84,7 @@ import java.util.StringTokenizer;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.CONFIGURE_MAP_ITEM_ID_SCHEME;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_ITEM_ID_SCHEME;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_ACTIONS;
+import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class OsmandSettings {
@@ -998,7 +999,7 @@ public class OsmandSettings {
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.CAR, "car");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.BICYCLE, "bicycle");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.PEDESTRIAN, "pedestrian");
- ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.PUBLIC_TRANSPORT, "public_transport");
+ ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.PUBLIC_TRANSPORT, PUBLIC_TRANSPORT_KEY);
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.BOAT, "boat");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.AIRCRAFT, "STRAIGHT_LINE_MODE");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.SKI, "ski");
@@ -2690,6 +2691,9 @@ public class OsmandSettings {
public final CommonPreference ROUTE_RECALCULATION_DISTANCE = new FloatPreference(this, "routing_recalc_distance", 0.f).makeProfile();
public final CommonPreference ROUTE_STRAIGHT_ANGLE = new FloatPreference(this, "routing_straight_angle", 30.f).makeProfile();
+ public final ListStringPreference CUSTOM_ROUTE_LINE_COLORS = (ListStringPreference) new ListStringPreference(this, "custom_route_line_colors", null, ",").makeShared().makeGlobal();
+ public final CommonPreference ROUTE_LINE_COLOR = new IntPreference(this, "route_line_color", 0).makeProfile();
+ public final CommonPreference ROUTE_LINE_WIDTH = new StringPreference(this, "route_line_width", null).makeProfile();
public final OsmandPreference USE_OSM_LIVE_FOR_ROUTING = new BooleanPreference(this, "enable_osmc_routing", true).makeProfile();
diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java
index 4c0af32894..6eeea74426 100644
--- a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java
+++ b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java
@@ -685,6 +685,11 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
ContextCompat.getColor(app, nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light);
}
+ @ColorRes
+ protected int getActiveColorRes() {
+ return isNightMode() ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
+ }
+
@ColorRes
protected int getBackgroundColorRes() {
return isNightMode() ? R.color.list_background_color_dark : R.color.list_background_color_light;
diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java
index b649ccf8cd..f4b38a32b8 100644
--- a/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java
+++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ProfileAppearanceFragment.java
@@ -54,10 +54,13 @@ import net.osmand.plus.profiles.SelectProfileBottomSheet.DialogMode;
import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
+import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteService;
import net.osmand.plus.settings.backend.ApplicationMode;
+import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper;
+import net.osmand.plus.settings.fragments.RouteLineAppearanceFragment.OnApplyRouteLineListener;
import net.osmand.plus.track.ColorsCard;
import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
import net.osmand.plus.widgets.FlowLayout;
@@ -74,8 +77,9 @@ import java.util.List;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID;
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILES_LIST_UPDATED_ARG;
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILE_KEY_ARG;
+import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
-public class ProfileAppearanceFragment extends BaseSettingsFragment implements OnSelectProfileCallback, CardListener, ColorPickerListener {
+public class ProfileAppearanceFragment extends BaseSettingsFragment implements OnSelectProfileCallback, CardListener, ColorPickerListener, OnApplyRouteLineListener {
private static final Log LOG = PlatformUtil.getLog(ProfileAppearanceFragment.class);
@@ -91,6 +95,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
private static final String LOCATION_ICON_ITEMS = "location_icon_items";
private static final String SELECT_NAV_ICON = "select_nav_icon";
private static final String NAV_ICON_ITEMS = "nav_icon_items";
+ private static final String CUSTOMIZE_ROUTE_LINE = "customize_route_line";
private static final String PROFILE_NAME_KEY = "profile_name_key";
private static final String PROFILE_STRINGKEY_KEY = "profile_stringkey_key";
@@ -159,6 +164,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
changedProfile.routeService = profile.routeService;
changedProfile.locationIcon = profile.locationIcon;
changedProfile.navigationIcon = profile.navigationIcon;
+ changedProfile.routeLineDrawInfo = profile.routeLineDrawInfo;
isNewProfile = ApplicationMode.valueOfStringKey(changedProfile.stringKey, null) == null;
}
requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@@ -179,6 +185,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
profile.routeService = baseModeForNewProfile.getRouteService();
profile.locationIcon = baseModeForNewProfile.getLocationIcon();
profile.navigationIcon = baseModeForNewProfile.getNavigationIcon();
+ profile.routeLineDrawInfo = createRouteLineDrawInfo(baseModeForNewProfile);
}
@Override
@@ -239,6 +246,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
findPreference(SELECT_ICON).setVisible(false);
findPreference(ICON_ITEMS).setVisible(false);
}
+ updateRouteLinePreference();
}
@SuppressLint("InlinedApi")
@@ -318,6 +326,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
outState.putBoolean(IS_BASE_PROFILE_IMPORTED, isBaseProfileImported);
outState.putSerializable(PROFILE_LOCATION_ICON_KEY, changedProfile.locationIcon);
outState.putSerializable(PROFILE_NAVIGATION_ICON_KEY, changedProfile.navigationIcon);
+ changedProfile.routeLineDrawInfo.saveToBundle(outState);
}
private void restoreState(Bundle savedInstanceState) {
@@ -331,6 +340,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
isBaseProfileImported = savedInstanceState.getBoolean(IS_BASE_PROFILE_IMPORTED);
changedProfile.locationIcon = (LocationIcon) savedInstanceState.getSerializable(PROFILE_LOCATION_ICON_KEY);
changedProfile.navigationIcon = (NavigationIcon) savedInstanceState.getSerializable(PROFILE_NAVIGATION_ICON_KEY);
+ changedProfile.routeLineDrawInfo = new RouteLineDrawInfo(savedInstanceState);
isNewProfile = savedInstanceState.getBoolean(IS_NEW_PROFILE_KEY);
}
@@ -709,6 +719,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
changedProfile.routingProfile = changedProfile.parent.getRoutingProfile();
changedProfile.routeService = changedProfile.parent.getRouteService();
this.isBaseProfileImported = isBaseProfileImported;
+ updateRouteLinePreference();
}
private void setupBaseProfileView(String stringKey) {
@@ -716,6 +727,14 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
baseProfileName.setText(Algorithms.capitalizeFirstLetter(mode.toHumanString()));
}
+ private void updateRouteLinePreference() {
+ Preference preference = findPreference(CUSTOMIZE_ROUTE_LINE);
+ boolean isDefaultProfile = getSelectedAppMode().equals(ApplicationMode.DEFAULT) && !isNewProfile;
+ boolean isPublicTransport = PUBLIC_TRANSPORT_KEY.equals(changedProfile.routingProfile);
+ preference.setVisible(!isDefaultProfile && !isPublicTransport);
+ preference.setIcon(getIcon(R.drawable.ic_action_route_distance, getActiveColorRes()));
+ }
+
private boolean checkProfileName() {
if (Algorithms.isBlank(changedProfile.name)) {
Activity activity = getActivity();
@@ -756,6 +775,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
mode.setCustomIconColor(changedProfile.customColor);
mode.setLocationIcon(changedProfile.locationIcon);
mode.setNavigationIcon(changedProfile.navigationIcon);
+ saveRouteLineAppearance(mode, changedProfile.routeLineDrawInfo);
FragmentActivity activity = getActivity();
if (activity != null) {
@@ -783,6 +803,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
if (!ApplicationMode.values(app).contains(mode)) {
ApplicationMode.changeProfileAvailability(mode, true, app);
}
+ saveRouteLineAppearance(mode, changedProfile.routeLineDrawInfo);
return mode;
}
@@ -967,6 +988,21 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
}
}
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ String prefId = preference.getKey();
+ if (CUSTOMIZE_ROUTE_LINE.equals(prefId)) {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ RouteLineDrawInfo drawInfo = changedProfile.routeLineDrawInfo;
+ drawInfo.setIconId(changedProfile.navigationIcon.getIconId());
+ drawInfo.setIconColor(changedProfile.getActualColor());
+ RouteLineAppearanceFragment.showInstance(mapActivity, drawInfo, this);
+ }
+ }
+ return super.onPreferenceClick(preference);
+ }
+
@Override
public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) {
}
@@ -977,6 +1013,29 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
this.onCardPressed(colorsCard);
}
+ @Override
+ public void applyRouteLineAppearance(@NonNull RouteLineDrawInfo routeLineDrawInfo) {
+ changedProfile.routeLineDrawInfo = routeLineDrawInfo;
+ }
+
+ private RouteLineDrawInfo createRouteLineDrawInfo(@NonNull ApplicationMode appMode) {
+ int storedValue = settings.ROUTE_LINE_COLOR.getModeValue(appMode);
+ Integer color = storedValue != 0 ? storedValue : null;
+ String widthKey = settings.ROUTE_LINE_WIDTH.getModeValue(appMode);
+ return new RouteLineDrawInfo(color, widthKey);
+ }
+
+ private void saveRouteLineAppearance(@NonNull ApplicationMode appMode,
+ @NonNull RouteLineDrawInfo drawInfo) {
+ Integer color = drawInfo.getColor();
+ if (color != null) {
+ settings.ROUTE_LINE_COLOR.setModeValue(appMode, color);
+ } else {
+ settings.ROUTE_LINE_COLOR.resetModeToDefault(appMode);
+ }
+ settings.ROUTE_LINE_WIDTH.setModeValue(appMode, drawInfo.getWidth());
+ }
+
public static boolean showInstance(FragmentActivity activity, SettingsScreenType screenType, @Nullable String appMode, boolean imported) {
try {
Fragment fragment = Fragment.instantiate(activity, screenType.fragmentName);
@@ -1008,6 +1067,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
RouteService routeService;
NavigationIcon navigationIcon;
LocationIcon locationIcon;
+ RouteLineDrawInfo routeLineDrawInfo;
@ColorInt
public int getActualColor() {
@@ -1044,6 +1104,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
return false;
if (routeService != that.routeService) return false;
if (navigationIcon != that.navigationIcon) return false;
+ if (routeLineDrawInfo != null ? !routeLineDrawInfo.equals(that.routeLineDrawInfo) : that.routeLineDrawInfo != null) return false;
return locationIcon == that.locationIcon;
}
@@ -1059,6 +1120,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
result = 31 * result + (routeService != null ? routeService.hashCode() : 0);
result = 31 * result + (navigationIcon != null ? navigationIcon.hashCode() : 0);
result = 31 * result + (locationIcon != null ? locationIcon.hashCode() : 0);
+ result = 31 * result + (routeLineDrawInfo != null ? routeLineDrawInfo.hashCode() : 0);
return result;
}
}
diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/RouteLineAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/RouteLineAppearanceFragment.java
new file mode 100644
index 0000000000..b0587eacde
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/settings/fragments/RouteLineAppearanceFragment.java
@@ -0,0 +1,431 @@
+package net.osmand.plus.settings.fragments;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+import androidx.activity.OnBackPressedCallback;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+
+import net.osmand.AndroidUtils;
+import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.R;
+import net.osmand.plus.UiUtilities;
+import net.osmand.plus.UiUtilities.DialogButtonType;
+import net.osmand.plus.activities.MapActivity;
+import net.osmand.plus.base.ContextMenuScrollFragment;
+import net.osmand.plus.helpers.AndroidUiHelper;
+import net.osmand.plus.helpers.enums.DayNightMode;
+import net.osmand.plus.routing.RouteLineDrawInfo;
+import net.osmand.plus.routing.cards.RouteLineColorCard;
+import net.osmand.plus.routing.cards.RouteLineColorCard.OnMapThemeUpdateListener;
+import net.osmand.plus.routing.cards.RouteLineColorCard.OnSelectedColorChangeListener;
+import net.osmand.plus.routing.cards.RouteLineWidthCard;
+import net.osmand.plus.settings.backend.ApplicationMode;
+import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
+import net.osmand.plus.track.TrackAppearanceFragment.OnNeedScrollListener;
+
+public class RouteLineAppearanceFragment extends ContextMenuScrollFragment implements ColorPickerListener, OnSelectedColorChangeListener, OnMapThemeUpdateListener {
+
+ public static final String TAG = RouteLineAppearanceFragment.class.getName();
+
+ private static final String INIT_MAP_THEME = "init_map_theme";
+ private static final String SELECTED_MAP_THEME = "selected_map_theme";
+
+ private RouteLineDrawInfo routeLineDrawInfo;
+
+ private int toolbarHeightPx;
+ private DayNightMode initMapTheme;
+ private DayNightMode selectedMapTheme;
+
+ private View buttonsShadow;
+ private View controlButtons;
+ private View toolbarContainer;
+
+ private RouteLineColorCard colorCard;
+ private RouteLineWidthCard widthCard;
+
+ @Override
+ public int getMainLayoutId() {
+ return R.layout.route_line_appearance;
+ }
+
+ @Override
+ public int getHeaderViewHeight() {
+ return 0;
+ }
+
+ @Override
+ public boolean isHeaderViewDetached() {
+ return false;
+ }
+
+ @Override
+ public int getToolbarHeight() {
+ return isPortrait() ? toolbarHeightPx : 0;
+ }
+
+ @Override
+ public float getMiddleStateKoef() {
+ return 0.5f;
+ }
+
+ @Override
+ public int getInitialMenuState() {
+ return MenuState.HALF_SCREEN;
+ }
+
+ @Override
+ public int getSupportedMenuStatesPortrait() {
+ return MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
+ }
+
+ @Override
+ public boolean shouldShowMapControls(int menuState) {
+ return menuState == MenuState.HALF_SCREEN;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar);
+
+ if (savedInstanceState != null) {
+ routeLineDrawInfo = new RouteLineDrawInfo(savedInstanceState);
+ initMapTheme = DayNightMode.valueOf(savedInstanceState.getString(INIT_MAP_THEME));
+ selectedMapTheme = DayNightMode.valueOf(savedInstanceState.getString(SELECTED_MAP_THEME));
+ } else {
+ initMapTheme = getMyApplication().getSettings().DAYNIGHT_MODE.get();
+ selectedMapTheme = initMapTheme;
+ }
+
+ requireMapActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
+ public void handleOnBackPressed() {
+ dismiss();
+ }
+ });
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+ if (view != null) {
+ toolbarContainer = view.findViewById(R.id.context_menu_toolbar_container);
+ buttonsShadow = view.findViewById(R.id.buttons_shadow);
+ controlButtons = view.findViewById(R.id.control_buttons);
+ if (isPortrait()) {
+ updateCardsLayout();
+ } else {
+ int widthNoShadow = getLandscapeNoShadowWidth();
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.gravity = Gravity.BOTTOM | Gravity.START;
+ controlButtons.setLayoutParams(params);
+ }
+ initContent(view);
+ }
+ return view;
+ }
+
+ private void initContent(@NonNull View view) {
+ setupCards();
+ setupToolbar();
+ setupButtons(view);
+ setupScrollShadow();
+ enterAppearanceMode();
+ openMenuHalfScreen();
+ calculateLayout();
+ }
+
+ private void calculateLayout() {
+ runLayoutListener(new Runnable() {
+ @Override
+ public void run() {
+ updateMapControlsPos(RouteLineAppearanceFragment.this, getViewY(), true);
+ initVisibleRect();
+ }
+ });
+ }
+
+ private void setupCards() {
+ MapActivity mapActivity = requireMapActivity();
+ ViewGroup cardsContainer = getCardsContainer();
+ cardsContainer.removeAllViews();
+
+ colorCard = new RouteLineColorCard(mapActivity, this, routeLineDrawInfo, initMapTheme, selectedMapTheme);
+ cardsContainer.addView(colorCard.build(mapActivity));
+
+ widthCard = new RouteLineWidthCard(mapActivity, routeLineDrawInfo, createScrollListener());
+ cardsContainer.addView(widthCard.build(mapActivity));
+ }
+
+ private OnNeedScrollListener createScrollListener() {
+ return new OnNeedScrollListener() {
+
+ @Override
+ public void onVerticalScrollNeeded(int y) {
+ View view = widthCard.getView();
+ if (view != null) {
+ int resultYPosition = view.getTop() + y;
+ int dialogHeight = getInnerScrollableHeight();
+ ScrollView scrollView = (ScrollView) getBottomScrollView();
+ if (resultYPosition > (scrollView.getScrollY() + dialogHeight)) {
+ scrollView.smoothScrollTo(0, resultYPosition - dialogHeight);
+ }
+ }
+ }
+
+ private int getInnerScrollableHeight() {
+ int totalScreenHeight = getViewHeight() - getMenuStatePosY(getCurrentMenuState());
+ int frameTotalHeight = controlButtons.getHeight() + buttonsShadow.getHeight();
+ return totalScreenHeight - frameTotalHeight;
+ }
+ };
+ }
+
+ private void setupToolbar() {
+ ImageView closeButton = toolbarContainer.findViewById(R.id.close_button);
+ closeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ }
+ });
+ closeButton.setImageResource(AndroidUtils.getNavigationIconResId(toolbarContainer.getContext()));
+ updateToolbarVisibility(toolbarContainer);
+ }
+
+ @Override
+ public int getStatusBarColorId() {
+ View view = getView();
+ if (Build.VERSION.SDK_INT >= 23 && !isNightMode() && view != null) {
+ view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ }
+ return isNightMode() ? R.color.divider_color_dark : R.color.divider_color_light;
+ }
+
+ @Override
+ public float getToolbarAlpha(int y) {
+ return isPortrait() ? 1f : 0f;
+ }
+
+ private void setupButtons(View view) {
+ View buttonsContainer = view.findViewById(R.id.buttons_container);
+ buttonsContainer.setBackgroundColor(AndroidUtils.getColorFromAttr(view.getContext(), R.attr.bg_color));
+ View saveButton = view.findViewById(R.id.right_bottom_button);
+ saveButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (getTargetFragment() instanceof OnApplyRouteLineListener) {
+ ((OnApplyRouteLineListener) getTargetFragment()).applyRouteLineAppearance(routeLineDrawInfo);
+ }
+ dismiss();
+ }
+ });
+
+ View cancelButton = view.findViewById(R.id.dismiss_button);
+ cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ FragmentActivity activity = getActivity();
+ if (activity != null) {
+ activity.onBackPressed();
+ }
+ }
+ });
+
+ UiUtilities.setupDialogButton(isNightMode(), cancelButton, DialogButtonType.SECONDARY, R.string.shared_string_cancel);
+ UiUtilities.setupDialogButton(isNightMode(), saveButton, DialogButtonType.PRIMARY, R.string.shared_string_apply);
+
+ AndroidUiHelper.updateVisibility(saveButton, true);
+ AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true);
+ }
+
+ private void setupScrollShadow() {
+ final View scrollView = getBottomScrollView();
+ scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
+ @Override
+ public void onScrollChanged() {
+ boolean scrollToBottomAvailable = scrollView.canScrollVertically(1);
+ if (scrollToBottomAvailable) {
+ showShadowButton();
+ } else {
+ hideShadowButton();
+ }
+ }
+ });
+ }
+
+ private void showShadowButton() {
+ buttonsShadow.setVisibility(View.VISIBLE);
+ buttonsShadow.animate()
+ .alpha(0.8f)
+ .setDuration(200)
+ .setListener(null);
+ }
+
+ private void hideShadowButton() {
+ buttonsShadow.animate()
+ .alpha(0f)
+ .setDuration(200);
+ }
+
+ private void initVisibleRect() {
+ MapActivity ctx = getMapActivity();
+ int screenHeight = AndroidUtils.getScreenHeight(ctx);
+ int screenWidth = AndroidUtils.getScreenWidth(ctx);
+ int statusBarHeight = AndroidUtils.getStatusBarHeight(ctx);
+ int centerX;
+ int centerY;
+ if (isPortrait()) {
+ centerX = screenWidth / 2;
+ centerY = (getViewY() + toolbarContainer.getHeight() + statusBarHeight) / 2;
+ } else {
+ boolean isRtl = AndroidUtils.isLayoutRtl(ctx);
+ int dialogWidth = getLandscapeNoShadowWidth();
+ int left = isRtl ? 0 : dialogWidth;
+ int right = isRtl ? screenWidth - dialogWidth : screenWidth;
+ centerX = (left + right) / 2;
+ centerY = (screenHeight + statusBarHeight) / 2 ;
+ }
+ routeLineDrawInfo.setCenterX(centerX);
+ routeLineDrawInfo.setCenterY(centerY);
+ routeLineDrawInfo.setScreenHeight(screenHeight);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ setDrawInfoOnRouteLayer(routeLineDrawInfo);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ setDrawInfoOnRouteLayer(null);
+ }
+
+ private void setDrawInfoOnRouteLayer(@Nullable RouteLineDrawInfo drawInfo) {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ mapActivity.getMapLayers().getRouteLayer().setRouteLineDrawInfo(drawInfo);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(INIT_MAP_THEME, initMapTheme.name());
+ outState.putString(SELECTED_MAP_THEME, selectedMapTheme.name());
+ routeLineDrawInfo.saveToBundle(outState);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ exitAppearanceMode();
+ }
+
+ private void enterAppearanceMode() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
+ AndroidUiHelper.setVisibility(mapActivity, portrait ? View.INVISIBLE : View.GONE,
+ R.id.map_left_widgets_panel,
+ R.id.map_right_widgets_panel,
+ R.id.map_center_info);
+ }
+ }
+
+ private void exitAppearanceMode() {
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
+ AndroidUiHelper.setVisibility(mapActivity, View.VISIBLE,
+ R.id.map_left_widgets_panel,
+ R.id.map_right_widgets_panel,
+ R.id.map_center_info,
+ R.id.map_search_button);
+ changeMapTheme(initMapTheme);
+ }
+ }
+
+ private void updateCardsLayout() {
+ View mainView = getMainView();
+ if (mainView != null) {
+ LinearLayout cardsContainer = getCardsContainer();
+ View topShadow = getTopShadow();
+ FrameLayout bottomContainer = getBottomContainer();
+ if (getCurrentMenuState() == MenuState.HEADER_ONLY) {
+ topShadow.setVisibility(View.INVISIBLE);
+ bottomContainer.setBackgroundDrawable(null);
+ AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.drawable.travel_card_bg_light, R.drawable.travel_card_bg_dark);
+ } else {
+ topShadow.setVisibility(View.VISIBLE);
+ AndroidUtils.setBackground(mainView.getContext(), bottomContainer, isNightMode(), R.color.list_background_color_light, R.color.list_background_color_dark);
+ AndroidUtils.setBackground(mainView.getContext(), cardsContainer, isNightMode(), R.color.list_background_color_light, R.color.list_background_color_dark);
+ }
+ }
+ }
+
+ @Override
+ public void onColorSelected(Integer prevColor, int newColor) {
+ colorCard.onColorSelected(prevColor, newColor);
+ }
+
+ @Override
+ public void onSelectedColorChanged() {
+ if (widthCard != null) {
+ widthCard.updateItems();
+ }
+ if (getMapActivity() != null) {
+ getMapActivity().refreshMap();
+ }
+ }
+
+ public static boolean showInstance(@NonNull MapActivity mapActivity,
+ @NonNull RouteLineDrawInfo drawInfo,
+ @NonNull Fragment target) {
+ try {
+ RouteLineAppearanceFragment fragment = new RouteLineAppearanceFragment();
+ fragment.setTargetFragment(target, 0);
+ fragment.routeLineDrawInfo = new RouteLineDrawInfo(drawInfo);
+
+ mapActivity.getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.fragmentContainer, fragment, TAG)
+ .addToBackStack(TAG)
+ .commitAllowingStateLoss();
+ return true;
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public void onMapThemeUpdated(@NonNull DayNightMode mapTheme) {
+ changeMapTheme(mapTheme);
+ }
+
+ private void changeMapTheme(@NonNull DayNightMode mapTheme) {
+ OsmandApplication app = getMyApplication();
+ if (app != null) {
+ app.getSettings().DAYNIGHT_MODE.set(mapTheme);
+ selectedMapTheme = mapTheme;
+ }
+ }
+
+ public interface OnApplyRouteLineListener {
+ void applyRouteLineAppearance(@NonNull RouteLineDrawInfo routeLineDrawInfo);
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceViewHolder.java b/OsmAnd/src/net/osmand/plus/track/AppearanceViewHolder.java
similarity index 64%
rename from OsmAnd/src/net/osmand/plus/track/TrackAppearanceViewHolder.java
rename to OsmAnd/src/net/osmand/plus/track/AppearanceViewHolder.java
index 1305f88f3d..bddb862593 100644
--- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceViewHolder.java
+++ b/OsmAnd/src/net/osmand/plus/track/AppearanceViewHolder.java
@@ -8,13 +8,13 @@ import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.R;
-public class TrackAppearanceViewHolder extends RecyclerView.ViewHolder {
+public class AppearanceViewHolder extends RecyclerView.ViewHolder {
- final TextView title;
- final ImageView icon;
- final ImageView button;
+ public final TextView title;
+ public final ImageView icon;
+ public final ImageView button;
- TrackAppearanceViewHolder(View itemView) {
+ public AppearanceViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.groupName);
icon = itemView.findViewById(R.id.groupIcon);
diff --git a/OsmAnd/src/net/osmand/plus/track/ColorsCard.java b/OsmAnd/src/net/osmand/plus/track/ColorsCard.java
index e6da7e736f..7651775f6c 100644
--- a/OsmAnd/src/net/osmand/plus/track/ColorsCard.java
+++ b/OsmAnd/src/net/osmand/plus/track/ColorsCard.java
@@ -6,7 +6,6 @@ import android.view.View;
import android.widget.ImageView;
import androidx.annotation.ColorInt;
-import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment;
@@ -28,12 +27,6 @@ import org.apache.commons.logging.Log;
import java.util.ArrayList;
import java.util.List;
-import androidx.annotation.ColorInt;
-import androidx.annotation.ColorRes;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.ColorUtils;
-import androidx.fragment.app.Fragment;
-
public class ColorsCard extends BaseCard implements ColorPickerListener {
public static final int MAX_CUSTOM_COLORS = 6;
@@ -58,7 +51,12 @@ public class ColorsCard extends BaseCard implements ColorPickerListener {
return R.layout.colors_card;
}
- public ColorsCard(MapActivity mapActivity, int selectedColor, Fragment targetFragment, List colors, ListStringPreference colorsListPreference, ApplicationMode appMode) {
+ public ColorsCard(MapActivity mapActivity,
+ int selectedColor,
+ Fragment targetFragment,
+ List colors,
+ ListStringPreference colorsListPreference,
+ ApplicationMode appMode) {
super(mapActivity);
this.targetFragment = targetFragment;
this.selectedColor = selectedColor;
diff --git a/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java b/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java
index 41e17ac37e..9e48ca0bbe 100644
--- a/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java
+++ b/OsmAnd/src/net/osmand/plus/track/TrackColoringCard.java
@@ -135,7 +135,7 @@ public class TrackColoringCard extends BaseCard {
updateHeader();
}
- private class TrackColoringAdapter extends RecyclerView.Adapter {
+ private class TrackColoringAdapter extends RecyclerView.Adapter {
private List items;
@@ -145,16 +145,16 @@ public class TrackColoringCard extends BaseCard {
@NonNull
@Override
- public TrackAppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
- return new TrackAppearanceViewHolder(view);
+ return new AppearanceViewHolder(view);
}
@Override
- public void onBindViewHolder(@NonNull final TrackAppearanceViewHolder holder, int position) {
+ public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
final TrackAppearanceItem item = items.get(position);
if (item.isActive() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -186,7 +186,7 @@ public class TrackColoringCard extends BaseCard {
});
}
- private void updateButtonBg(TrackAppearanceViewHolder holder, TrackAppearanceItem item) {
+ private void updateButtonBg(AppearanceViewHolder holder, TrackAppearanceItem item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
Context ctx = holder.itemView.getContext();
@@ -217,7 +217,7 @@ public class TrackColoringCard extends BaseCard {
}
}
- private void updateTextAndIconColor(TrackAppearanceViewHolder holder, TrackAppearanceItem item) {
+ private void updateTextAndIconColor(AppearanceViewHolder holder, TrackAppearanceItem item) {
Context ctx = holder.itemView.getContext();
boolean isSelected = item.getAttrName().equals(getSelectedAppearanceItem().getAttrName());
int iconColorId;
diff --git a/OsmAnd/src/net/osmand/plus/track/TrackWidthCard.java b/OsmAnd/src/net/osmand/plus/track/TrackWidthCard.java
index 9e98414d34..8c1385b43b 100644
--- a/OsmAnd/src/net/osmand/plus/track/TrackWidthCard.java
+++ b/OsmAnd/src/net/osmand/plus/track/TrackWidthCard.java
@@ -184,7 +184,7 @@ public class TrackWidthCard extends BaseCard {
}
}
- private class GpxWidthAdapter extends RecyclerView.Adapter {
+ private class GpxWidthAdapter extends RecyclerView.Adapter {
private List items;
@@ -194,13 +194,13 @@ public class TrackWidthCard extends BaseCard {
@NonNull
@Override
- public TrackAppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
- TrackAppearanceViewHolder holder = new TrackAppearanceViewHolder(view);
+ AppearanceViewHolder holder = new AppearanceViewHolder(view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp);
@@ -209,7 +209,7 @@ public class TrackWidthCard extends BaseCard {
}
@Override
- public void onBindViewHolder(@NonNull final TrackAppearanceViewHolder holder, int position) {
+ public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
AppearanceListItem item = items.get(position);
holder.title.setText(item.getLocalizedValue());
@@ -238,7 +238,7 @@ public class TrackWidthCard extends BaseCard {
});
}
- private void updateWidthIcon(TrackAppearanceViewHolder holder, AppearanceListItem item) {
+ private void updateWidthIcon(AppearanceViewHolder holder, AppearanceListItem item) {
int color = trackDrawInfo.getColor();
int iconId;
@@ -251,7 +251,7 @@ public class TrackWidthCard extends BaseCard {
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(iconId, color));
}
- private void updateButtonBg(TrackAppearanceViewHolder holder, AppearanceListItem item) {
+ private void updateButtonBg(AppearanceViewHolder holder, AppearanceListItem item) {
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) {
if (getSelectedItem() != null && getSelectedItem().equals(item)) {
diff --git a/OsmAnd/src/net/osmand/plus/views/OsmandMapLayer.java b/OsmAnd/src/net/osmand/plus/views/OsmandMapLayer.java
index 67e046c1de..f79489b52d 100644
--- a/OsmAnd/src/net/osmand/plus/views/OsmandMapLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/OsmandMapLayer.java
@@ -377,6 +377,7 @@ public abstract class OsmandMapLayer {
public Paint paint;
public Paint customColorPaint;
public int customColor = 0;
+ public float customWidth = 0;
public int defaultWidth = 0;
public int defaultColor = 0;
public boolean isPaint2;
@@ -481,8 +482,13 @@ public abstract class OsmandMapLayer {
if (isShadowPaint) {
canvas.drawPath(path, shadowPaint);
}
- if (customColor != 0) {
- customColorPaint.setColor(customColor);
+ if (customColor != 0 || customWidth != 0) {
+ if (customColor != 0) {
+ customColorPaint.setColor(customColor);
+ }
+ if (customWidth != 0) {
+ customColorPaint.setStrokeWidth(customWidth);
+ }
canvas.drawPath(path, customColorPaint);
} else {
canvas.drawPath(path, paint);
diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java
index ed425c0993..0bfde7edcf 100644
--- a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java
@@ -872,14 +872,16 @@ public class MapControlsLayer extends OsmandMapLayer {
boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode)
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
&& !isInPlanRouteMode() && !shouldHideTopControls && !isInChoosingRoutesMode()
- && !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode();
+ && !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode()
+ && !isInRouteLineAppearanceMode();
routePlanningBtn.updateVisibility(showBottomMenuButtons);
menuControl.updateVisibility(showBottomMenuButtons);
boolean additionalDialogsHide = !isInGpxApproximationMode()
&& !isInTrackAppearanceMode()
&& !isInChoosingRoutesMode()
- && !isInWaypointsChoosingMode();
+ && !isInWaypointsChoosingMode()
+ && !isInRouteLineAppearanceMode();
boolean showZoomButtons = !routeDialogOpened && !shouldHideTopControls
&& !isInFollowTrackMode()
&& (additionalDialogsHide || !portrait);
@@ -888,7 +890,8 @@ public class MapControlsLayer extends OsmandMapLayer {
boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode()
|| isInPlanRouteMode() || shouldHideTopControls || isInChoosingRoutesMode()
- || isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode();
+ || isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode()
+ || isInRouteLineAppearanceMode();
compassHud.forceHideCompass = forceHideCompass;
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
@@ -899,7 +902,8 @@ public class MapControlsLayer extends OsmandMapLayer {
}
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls
&& !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode()
- && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode();
+ && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode()
+ && !isInRouteLineAppearanceMode();
layersHud.updateVisibility(showTopButtons);
quickSearchHud.updateVisibility(showTopButtons);
@@ -1029,7 +1033,8 @@ public class MapControlsLayer extends OsmandMapLayer {
&& !isInGpxApproximationMode()
&& !isInChoosingRoutesMode()
&& !isInWaypointsChoosingMode()
- && !isInFollowTrackMode();
+ && !isInFollowTrackMode()
+ && !isInRouteLineAppearanceMode();
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
&& (additionalDialogsHide || !isPotrait()));
}
@@ -1397,6 +1402,10 @@ public class MapControlsLayer extends OsmandMapLayer {
return MapRouteInfoMenu.waypointsVisible;
}
+ private boolean isInRouteLineAppearanceMode() {
+ return mapActivity.getMapLayers().getRouteLayer().isInRouteLineAppearanceMode();
+ }
+
private boolean isInFollowTrackMode() {
return MapRouteInfoMenu.followTrackVisible;
}
diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java
index 4ba977235e..3591a2eca9 100644
--- a/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java
@@ -61,6 +61,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
private final MapMarkersLayer mapMarkersLayer;
private final MapControlsLayer mapControlsLayer;
private final GPXLayer gpxLayer;
+ private final RouteLayer routeLayer;
private ImageView contextMarker;
private final MapActivity mapActivity;
private final OsmandApplication app;
@@ -90,6 +91,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
mapMarkersLayer = mapActivity.getMapLayers().getMapMarkersLayer();
gpxLayer = mapActivity.getMapLayers().getGpxLayer();
mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer();
+ routeLayer = mapActivity.getMapLayers().getRouteLayer();
}
@Override
@@ -426,6 +428,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
mapMarkersLayer.isInPlanRouteMode() ||
gpxLayer.isInTrackAppearanceMode() ||
mapControlsLayer.isInTrackMenuMode() ||
+ routeLayer.isInRouteLineAppearanceMode() ||
mapRouteInfoMenu.isVisible() ||
MapRouteInfoMenu.chooseRoutesVisible ||
MapRouteInfoMenu.waypointsVisible ||
diff --git a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java
index 083d94f4ff..2a432c8041 100644
--- a/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/layers/RouteLayer.java
@@ -11,17 +11,21 @@ import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
+import androidx.core.graphics.drawable.DrawableCompat;
import net.osmand.AndroidUtils;
import net.osmand.Location;
+import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
+import net.osmand.data.QuadPoint;
import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox;
import net.osmand.data.TransportStop;
@@ -30,8 +34,11 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.profiles.LocationIcon;
+import net.osmand.plus.render.OsmandRenderer;
+import net.osmand.plus.render.OsmandRenderer.RenderingContext;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo;
+import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteService;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper;
@@ -41,18 +48,31 @@ import net.osmand.plus.views.layers.geometry.PublicTransportGeometryWay;
import net.osmand.plus.views.layers.geometry.PublicTransportGeometryWayContext;
import net.osmand.plus.views.layers.geometry.RouteGeometryWay;
import net.osmand.plus.views.layers.geometry.RouteGeometryWayContext;
+import net.osmand.render.RenderingRuleProperty;
+import net.osmand.render.RenderingRuleSearchRequest;
+import net.osmand.render.RenderingRulesStorage;
import net.osmand.router.TransportRouteResult;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
+import org.apache.commons.logging.Log;
+
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+
+import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR;
public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider {
+ private static final Log log = PlatformUtil.getLog(RouteLayer.class);
+
+ private static final int DEFAULT_WIDTH_MULTIPLIER = 7;
+
private OsmandMapTileView view;
-
+
private final RoutingHelper helper;
private final TransportRoutingHelper transportHelper;
// keep array lists created
@@ -64,13 +84,16 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
private Paint paintIconAction;
private Paint paintGridOuterCircle;
private Paint paintGridCircle;
+ private Paint paintRouteLinePreview;
private LayerDrawable selectedPoint;
private TrackChartPoints trackChartPoints;
+ private RouteLineDrawInfo routeLineDrawInfo;
private RenderingLineAttributes attrs;
private RenderingLineAttributes attrsPT;
private RenderingLineAttributes attrsW;
+ private Map cachedRouteLineWidth = new HashMap<>();
private boolean nightMode;
private RouteGeometryWayContext routeWayContext;
@@ -79,6 +102,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
private PublicTransportGeometryWay publicTransportRouteGeometry;
private LayerDrawable projectionIcon;
+ private LayerDrawable previewIcon;
public RouteLayer(RoutingHelper helper) {
this.helper = helper;
@@ -149,6 +173,8 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
paintGridOuterCircle.setAntiAlias(true);
paintGridOuterCircle.setColor(Color.WHITE);
paintGridOuterCircle.setAlpha(204);
+
+ paintRouteLinePreview = new Paint();
}
@Override
@@ -202,12 +228,12 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
canvas.rotate(tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
}
}
-
+
}
private boolean isPlanRouteGraphsAvailable() {
- if (view.getContext() instanceof MapActivity) {
- MapActivity mapActivity = (MapActivity) view.getContext();
+ MapActivity mapActivity = getMapActivity();
+ if (mapActivity != null) {
MeasurementToolFragment fragment = mapActivity.getMeasurementToolFragment();
if (fragment != null) {
return fragment.hasVisibleGraph();
@@ -216,6 +242,24 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
return false;
}
+ public boolean isInRouteLineAppearanceMode() {
+ return routeLineDrawInfo != null;
+ }
+
+ public void setRouteLineDrawInfo(RouteLineDrawInfo drawInfo) {
+ this.routeLineDrawInfo = drawInfo;
+ if (drawInfo == null) {
+ previewIcon = null;
+ }
+ }
+
+ private MapActivity getMapActivity() {
+ if (view.getContext() instanceof MapActivity) {
+ return (MapActivity) view.getContext();
+ }
+ return null;
+ }
+
private void updateAttrs(DrawSettings settings, RotatedTileBox tileBox) {
boolean updatePaints = attrs.updatePaints(view.getApplication(), settings, tileBox);
attrs.isPaint3 = false;
@@ -263,9 +307,39 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
}
}
}
-
+
@Override
- public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {}
+ public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
+ if (routeLineDrawInfo != null) {
+ float angle = tileBox.getRotate();
+ QuadPoint c = tileBox.getCenterPixelPoint();
+
+ canvas.rotate(-angle, c.x, c.y);
+ drawRouteLinePreview(canvas, tileBox, routeLineDrawInfo);
+ canvas.rotate(angle, c.x, c.y);
+ }
+ }
+
+ private void drawRouteLinePreview(Canvas canvas,
+ RotatedTileBox tileBox,
+ RouteLineDrawInfo drawInfo) {
+ paintRouteLinePreview.setColor(getRouteLineColor(nightMode));
+ paintRouteLinePreview.setStrokeWidth(getRouteLineWidth(tileBox));
+
+ int centerX = drawInfo.getCenterX();
+ int centerY = drawInfo.getCenterY();
+ int screenHeight = drawInfo.getScreenHeight();
+
+ canvas.drawLine(centerX, 0, centerX, screenHeight, paintRouteLinePreview);
+
+ if (previewIcon == null) {
+ previewIcon = (LayerDrawable) AppCompatResources.getDrawable(view.getContext(), drawInfo.getIconId());
+ DrawableCompat.setTint(previewIcon.getDrawable(1), drawInfo.getIconColor());
+ }
+ canvas.rotate(-90, centerX, centerY);
+ drawIcon(canvas, previewIcon, centerX, centerY);
+ canvas.rotate(90, centerX, centerY);
+ }
private void drawAction(RotatedTileBox tb, Canvas canvas, List actionPoints) {
if (actionPoints.size() > 0) {
@@ -328,21 +402,78 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
}
int locationX = (int) projectionXY[0];
int locationY = (int) projectionXY[1];
+ drawIcon(canvas, projectionIcon, locationX, locationY);
+ }
- projectionIcon.setBounds(locationX - projectionIcon.getIntrinsicWidth() / 2,
- locationY - projectionIcon.getIntrinsicHeight() / 2,
- locationX + projectionIcon.getIntrinsicWidth() / 2,
- locationY + projectionIcon.getIntrinsicHeight() / 2);
- projectionIcon.draw(canvas);
-
+ private static void drawIcon(Canvas canvas, Drawable drawable, int locationX, int locationY) {
+ drawable.setBounds(locationX - drawable.getIntrinsicWidth() / 2,
+ locationY - drawable.getIntrinsicHeight() / 2,
+ locationX + drawable.getIntrinsicWidth() / 2,
+ locationY + drawable.getIntrinsicHeight() / 2);
+ drawable.draw(canvas);
}
@ColorInt
public int getRouteLineColor(boolean night) {
- updateAttrs(new DrawSettings(night), view.getCurrentRotatedTileBox());
- return attrs.paint.getColor();
+ Integer color;
+ if (routeLineDrawInfo != null) {
+ color = routeLineDrawInfo.getColor();
+ } else {
+ int storedValue = view.getSettings().ROUTE_LINE_COLOR.getModeValue(helper.getAppMode());
+ color = storedValue != 0 ? storedValue : null;
+ }
+
+ if (color == null) {
+ updateAttrs(new DrawSettings(night), view.getCurrentRotatedTileBox());
+ color = attrs.paint.getColor();
+ }
+ return color;
}
-
+
+ private float getRouteLineWidth(@NonNull RotatedTileBox tileBox) {
+ String widthKey;
+ if (routeLineDrawInfo != null) {
+ widthKey = routeLineDrawInfo.getWidth();
+ } else {
+ widthKey = view.getSettings().ROUTE_LINE_WIDTH.getModeValue(helper.getAppMode());
+ }
+ return widthKey != null ? getWidthByKey(tileBox, widthKey) : attrs.paint.getStrokeWidth();
+ }
+
+ @Nullable
+ private Float getWidthByKey(RotatedTileBox tileBox, String widthKey) {
+ Float resultValue = cachedRouteLineWidth.get(widthKey);
+ if (resultValue != null) {
+ return resultValue;
+ }
+ if (!Algorithms.isEmpty(widthKey) && Algorithms.isInt(widthKey)) {
+ try {
+ int widthDp = Integer.parseInt(widthKey);
+ resultValue = (float) AndroidUtils.dpToPx(view.getApplication(), widthDp);
+ } catch (NumberFormatException e) {
+ log.error(e.getMessage(), e);
+ resultValue = DEFAULT_WIDTH_MULTIPLIER * view.getDensity();
+ }
+ } else {
+ RenderingRulesStorage rrs = view.getApplication().getRendererRegistry().getCurrentSelectedRenderer();
+ RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs);
+ req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, nightMode);
+ req.setIntFilter(rrs.PROPS.R_MINZOOM, tileBox.getZoom());
+ req.setIntFilter(rrs.PROPS.R_MAXZOOM, tileBox.getZoom());
+ RenderingRuleProperty ctWidth = rrs.PROPS.get(CURRENT_TRACK_WIDTH_ATTR);
+ if (ctWidth != null) {
+ req.setStringFilter(ctWidth, widthKey);
+ }
+ if (req.searchRenderingAttribute("gpx")) {
+ RenderingContext rc = new OsmandRenderer.RenderingContext(view.getContext());
+ rc.setDensityValue((float) tileBox.getMapDensity());
+ resultValue = rc.getComplexValue(req, req.ALL.R_STROKE_WIDTH);
+ }
+ }
+ cachedRouteLineWidth.put(widthKey, resultValue);
+ return resultValue;
+ }
+
public void drawLocations(RotatedTileBox tb, Canvas canvas, double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) {
if (helper.isPublicTransportMode()) {
int currentRoute = transportHelper.getCurrentRoute();
@@ -364,6 +495,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
boolean straight = route.getRouteService() == RouteService.STRAIGHT;
publicTransportRouteGeometry.clearRoute();
routeGeometry.updateRoute(tb, route);
+ routeGeometry.setRouteStyleParams(getRouteLineColor(nightMode), getRouteLineWidth(tb));
if (directTo) {
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
null, 0);
@@ -636,12 +768,12 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
@Override
public boolean disableSingleTap() {
- return false;
+ return isInRouteLineAppearanceMode();
}
@Override
public boolean disableLongPressOnMap() {
- return false;
+ return isInRouteLineAppearanceMode();
}
@Override
diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java
index 0bfa86f43b..494375d404 100644
--- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java
+++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayDrawer.java
@@ -95,6 +95,7 @@ public class GeometryWayDrawer {
public void drawPath(Canvas canvas, Path path, GeometryWayStyle> style) {
context.getAttrs().customColor = style.getColor();
+ context.getAttrs().customWidth = style.getWidth();
context.getAttrs().drawPath(canvas, path);
}
diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayStyle.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayStyle.java
index 27e37132db..d5a38ccd5d 100644
--- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayStyle.java
+++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/GeometryWayStyle.java
@@ -7,6 +7,7 @@ public abstract class GeometryWayStyle {
private T context;
protected Integer color;
+ protected Float width;
public GeometryWayStyle(T context) {
this.context = context;
@@ -17,6 +18,12 @@ public abstract class GeometryWayStyle {
this.color = color;
}
+ public GeometryWayStyle(T context, Integer color, Float width) {
+ this.context = context;
+ this.color = color;
+ this.width = width;
+ }
+
public T getContext() {
return context;
}
@@ -29,6 +36,10 @@ public abstract class GeometryWayStyle {
return color;
}
+ public Float getWidth() {
+ return width;
+ }
+
public Integer getStrokeColor() {
return context.getStrokeColor(color);
}
diff --git a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java
index 610ea41454..f6e26b039f 100644
--- a/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java
+++ b/OsmAnd/src/net/osmand/plus/views/layers/geometry/RouteGeometryWay.java
@@ -1,8 +1,11 @@
package net.osmand.plus.views.layers.geometry;
import android.graphics.Bitmap;
+import android.graphics.Paint;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import net.osmand.Location;
import net.osmand.data.RotatedTileBox;
@@ -17,15 +20,26 @@ public class RouteGeometryWay extends GeometryWay(context));
this.helper = context.getApp().getRoutingHelper();
}
+ public void setRouteStyleParams(@Nullable @ColorInt Integer color, @Nullable Float width) {
+ this.customColor = color;
+ this.customWidth = width;
+ }
+
@NonNull
@Override
public GeometryWayStyle getDefaultWayStyle() {
- return new GeometrySolidWayStyle(getContext(), getContext().getAttrs().paint.getColor());
+ Paint paint = getContext().getAttrs().paint;
+ int color = customColor != null ? customColor : paint.getColor();
+ float width = customWidth != null ? customWidth : paint.getStrokeWidth();
+ return new GeometrySolidWayStyle(getContext(), color, width);
}
public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) {
@@ -50,8 +64,8 @@ public class RouteGeometryWay extends GeometryWay {
- GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color) {
- super(context, color);
+ GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color, Float width) {
+ super(context, color, width);
}
@Override
diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java
index 6bc09a5987..993790bfea 100644
--- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java
+++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java
@@ -1207,6 +1207,7 @@ public class MapInfoWidgetsFactory {
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && !map.shouldHideTopControls()
&& map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive()
&& !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
+ && !map.getMapLayers().getRouteLayer().isInRouteLineAppearanceMode()
&& !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible
&& !MapRouteInfoMenu.followTrackVisible;
diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java
index 52801776cd..1490ab32b1 100644
--- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java
+++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java
@@ -191,7 +191,8 @@ public class MapMarkersWidgetsFactory {
|| map.isTopToolbarActive()
|| map.shouldHideTopControls()
|| map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
- || map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()) {
+ || map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()
+ || map.getMapLayers().getRouteLayer().isInRouteLineAppearanceMode()) {
updateVisibility(false);
return;
}