Merge pull request #11248 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2021-03-24 21:00:48 +01:00 committed by GitHub
commit bbb5fedfa3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 2189 additions and 151 deletions

View file

@ -10,8 +10,6 @@ import net.osmand.router.GeneralRouter.RouteDataObjectAttribute;
public class TransportRoutingConfiguration { public class TransportRoutingConfiguration {
public static final String KEY = "public_transport";
public int ZOOM_TO_LOAD_TILES = 15; public int ZOOM_TO_LOAD_TILES = 15;
public int walkRadius = 1500; // ? 3000 public int walkRadius = 1500; // ? 3000

View file

@ -13,7 +13,7 @@
<string name="si_km_m">Kilomter/meter</string> <string name="si_km_m">Kilomter/meter</string>
<string name="si_mi_yard">Miles/yard</string> <string name="si_mi_yard">Miles/yard</string>
<string name="si_mi_feet">Miles/fot</string> <string name="si_mi_feet">Miles/fot</string>
<string name="si_nm_h">Distansminuter per timme (knop)</string> <string name="si_nm_h">Sjömil per timme (knop)</string>
<string name="si_min_m">Minuter per mile</string> <string name="si_min_m">Minuter per mile</string>
<string name="si_min_km">Minuter per kilometer</string> <string name="si_min_km">Minuter per kilometer</string>
<string name="si_m_s">Meter per sekund</string> <string name="si_m_s">Meter per sekund</string>

View file

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_transparent">
<LinearLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/context_menu_top_shadow" />
<LinearLayout
android:id="@+id/route_menu_top_shadow_all"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:minHeight="@dimen/bottom_sheet_title_height"
android:orientation="vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<View
android:layout_width="@dimen/content_padding"
android:layout_height="2dp"
android:layout_gravity="center"
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
android:layout_marginBottom="@dimen/list_item_button_padding"
android:background="?attr/bg_dash_line" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/header_title"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="center_vertical"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal">
<net.osmand.plus.LockableScrollView
android:id="@+id/route_menu_bottom_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/route_info_bg">
<LinearLayout
android:id="@+id/route_menu_cards_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/route_info_bg"
android:orientation="vertical"
android:paddingBottom="@dimen/dialog_button_ex_height" />
</net.osmand.plus.LockableScrollView>
</FrameLayout>
</LinearLayout>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/context_menu_toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/card_and_list_background_basic"
android:minHeight="@dimen/toolbar_height"
android:padding="0dp"
osmand:contentInsetEnd="0dp"
osmand:contentInsetLeft="0dp"
osmand:contentInsetRight="0dp"
osmand:contentInsetStart="0dp"
osmand:theme="@style/ThemeOverlay.AppCompat.ActionBar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="@dimen/toolbar_height">
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/close_button"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/toolbar_height"
android:layout_height="@dimen/toolbar_height"
android:tint="?android:textColorPrimary"
android:contentDescription="@string/access_shared_string_navigate_up"
osmand:srcCompat="@drawable/ic_arrow_back" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/toolbar_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:ellipsize="end"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium"
android:text="@string/shared_string_route_line" />
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/context_menu_controls" />
<LinearLayout
android:id="@+id/control_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/buttons_shadow"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_gravity="bottom"
android:background="@drawable/shadow" />
<include
layout="@layout/bottom_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_ex_height"
android:layout_gravity="bottom" />
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/shared_string_color"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/color_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="Orange" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
tools:itemCount="2"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_group_select_item"
tools:orientation="horizontal" />
</LinearLayout>
<FrameLayout
android:id="@+id/theme_toggle_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/content_padding_small" >
<include layout="@layout/custom_radio_buttons" />
</FrameLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Specify color for map mode: day." />
<FrameLayout
android:id="@+id/colors_card_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/content_padding_small"/>
</LinearLayout>

View file

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<View
android:id="@+id/top_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color_basic"
android:focusable="false" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/select_track_width"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="21" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="@dimen/context_menu_padding_margin_tiny">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_half"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
tools:itemCount="3"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_group_select_item"
tools:orientation="horizontal" />
</LinearLayout>
<LinearLayout
android:id="@+id/slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/content_padding"
android:paddingBottom="@dimen/favorites_select_group_button_height">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:text="@string/shared_string_custom"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_tv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="1" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/width_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:stepSize="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_min"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="1" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/width_value_max"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="24" />
</LinearLayout>
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Route line would be use width specified on selected map style: OsmAnd." />
</LinearLayout>

View file

@ -4045,4 +4045,7 @@
<string name="shared_string_interval">Intertempo</string> <string name="shared_string_interval">Intertempo</string>
<string name="rendering_attr_noNatureReserveBoundaries_description">Kaŝi limojn de naturaj rezervejoj, protektataj areoj kaj naciaj parkoj</string> <string name="rendering_attr_noNatureReserveBoundaries_description">Kaŝi limojn de naturaj rezervejoj, protektataj areoj kaj naciaj parkoj</string>
<string name="rendering_attr_noNatureReserveBoundaries_name">Limoj de rezervejoj</string> <string name="rendering_attr_noNatureReserveBoundaries_name">Limoj de rezervejoj</string>
<string name="trip_recording_logging_interval_info">Agordita periodo de intertempo de registrado, dum kiu OsmAnd petos la nunajn poziciajn datumojn.</string>
<string name="lost_data_warning">Ĉiuj nekonservitaj datumoj perdiĝos.</string>
<string name="trip_recording_save_and_continue">Konservi kaj daŭrigi</string>
</resources> </resources>

View file

@ -4052,4 +4052,6 @@
<string name="map_widget_distance_by_tap">Kaugus toksamise järgi</string> <string name="map_widget_distance_by_tap">Kaugus toksamise järgi</string>
<string name="rendering_attr_noNatureReserveBoundaries_description">Peida (loodus)kaitsealade ja rahvusparkide piirid</string> <string name="rendering_attr_noNatureReserveBoundaries_description">Peida (loodus)kaitsealade ja rahvusparkide piirid</string>
<string name="rendering_attr_noNatureReserveBoundaries_name">Looduse piirid</string> <string name="rendering_attr_noNatureReserveBoundaries_name">Looduse piirid</string>
<string name="trip_recording_save_and_continue">Salvesta ja jätka</string>
<string name="lost_data_warning">Kõik salvestamata andmed lähevad kaotsi.</string>
</resources> </resources>

View file

@ -492,7 +492,7 @@
<string name="safe_mode_description">اجرای برنامه در حالت ایمن (به‌جای کد native از کد Android که کُندتر است استفاده می‌کند).</string> <string name="safe_mode_description">اجرای برنامه در حالت ایمن (به‌جای کد native از کد Android که کُندتر است استفاده می‌کند).</string>
<string name="native_library_not_running">برنامه در حالت ایمن اجرا شده است (از طریق تنظیمات آن را غیرفعال کنید).</string> <string name="native_library_not_running">برنامه در حالت ایمن اجرا شده است (از طریق تنظیمات آن را غیرفعال کنید).</string>
<string name="background_service_is_enabled_question">سرویس پس‌زمینهٔ OsmAnd هنوز در حال اجراست. آن را هم متوقف می‌کنید؟</string> <string name="background_service_is_enabled_question">سرویس پس‌زمینهٔ OsmAnd هنوز در حال اجراست. آن را هم متوقف می‌کنید؟</string>
<string name="close_changeset">بستن بستهٔ تغییرات</string> <string name="close_changeset">بستن بستهٔ تغییر</string>
<string name="zxing_barcode_scanner_not_found">برنامهٔ اسکنر بارکد ZXing نصب نشده است. در گوگل‌پلی جست‌وجو می‌کنید؟</string> <string name="zxing_barcode_scanner_not_found">برنامهٔ اسکنر بارکد ZXing نصب نشده است. در گوگل‌پلی جست‌وجو می‌کنید؟</string>
<string name="rendering_attr_roadColors_description">یکی از رنگ‌بندی‌های راه را انتخاب کنید:</string> <string name="rendering_attr_roadColors_description">یکی از رنگ‌بندی‌های راه را انتخاب کنید:</string>
<string name="rendering_attr_roadColors_name">رنگ‌بندی راه</string> <string name="rendering_attr_roadColors_name">رنگ‌بندی راه</string>
@ -787,8 +787,8 @@
<string name="converting_names">در حال تبدیل اسامی محلی/انگلیسی…</string> <string name="converting_names">در حال تبدیل اسامی محلی/انگلیسی…</string>
<string name="failed_op">ناموفق</string> <string name="failed_op">ناموفق</string>
<string name="auth_failed">اجازهٔ دسترسی احراز نشد</string> <string name="auth_failed">اجازهٔ دسترسی احراز نشد</string>
<string name="closing_changeset">بستن بستهٔ تغییرات</string> <string name="closing_changeset">بستن بستهٔ تغییر…</string>
<string name="opening_changeset">بازکردن بستهٔ تغییرات</string> <string name="opening_changeset">بازکردن بستهٔ تغییر…</string>
<string name="list_index_files_was_not_loaded">دریافت لیست مناطق از https://osmand.net ناموفق بود.</string> <string name="list_index_files_was_not_loaded">دریافت لیست مناطق از https://osmand.net ناموفق بود.</string>
<string name="downloading_list_indexes">در حال دانلود لیست مناطق موجود…</string> <string name="downloading_list_indexes">در حال دانلود لیست مناطق موجود…</string>
<string name="download_question_exist">دادهٔ آفلاینِ {0} از قبل وجود دارد ({1}). آن را روزآمد می‌کنید ({2})؟</string> <string name="download_question_exist">دادهٔ آفلاینِ {0} از قبل وجود دارد ({1}). آن را روزآمد می‌کنید ({2})؟</string>
@ -1478,7 +1478,7 @@
<string name="welcome_text">برنامهٔ OsmAnd نقشه‌گردی و ناوبری آفلاین را برایتان به ارمغان می‌آورد.</string> <string name="welcome_text">برنامهٔ OsmAnd نقشه‌گردی و ناوبری آفلاین را برایتان به ارمغان می‌آورد.</string>
<string name="welcome_header">خوش آمدید</string> <string name="welcome_header">خوش آمدید</string>
<string name="current_route">مسیر فعلی</string> <string name="current_route">مسیر فعلی</string>
<string name="osm_changes_added_to_local_edits">تغییرات OSM به بستهٔ تغییرات محلی اضافه شد</string> <string name="osm_changes_added_to_local_edits">تغییرات OSM به بستهٔ تغییر محلی اضافه شد</string>
<string name="mark_to_delete">برای حذف‌کردن علامت بزنید</string> <string name="mark_to_delete">برای حذف‌کردن علامت بزنید</string>
<string name="local_osm_changes_upload_all_confirm">از آپلود این %1$d تغییر در OSM مطمئن هستید؟</string> <string name="local_osm_changes_upload_all_confirm">از آپلود این %1$d تغییر در OSM مطمئن هستید؟</string>
<string name="confirmation_to_clear_history">سوابق را پاک می‌کنید؟</string> <string name="confirmation_to_clear_history">سوابق را پاک می‌کنید؟</string>
@ -2589,7 +2589,7 @@
<string name="empty_state_markers_history_desc">نشانه‌هایی که به‌عنوان گذرانده مشخص شود در این صفحه نشان داده می‌شود.</string> <string name="empty_state_markers_history_desc">نشانه‌هایی که به‌عنوان گذرانده مشخص شود در این صفحه نشان داده می‌شود.</string>
<string name="shared_string_more_without_dots">بیشتر</string> <string name="shared_string_more_without_dots">بیشتر</string>
<string name="looking_for_tracks_with_waypoints">در حال جست‌وجوی ردهای دارای راه‌نشان</string> <string name="looking_for_tracks_with_waypoints">در حال جست‌وجوی ردهای دارای راه‌نشان</string>
<string name="empty_state_osm_edits">اشیای OSM را بسازید یا ویرایش کنید</string> <string name="empty_state_osm_edits">مکان‌های OSM را ایجاد یا ویرایش کنید</string>
<string name="empty_state_osm_edits_descr">POIها را اضافه یا ویرایش کنید، یادداشت‌های OSMای اضافه کنید یا روی آن‌ها نظر بدهید و فایل‌های GPX ضبط‌شده را آپلود کنید.</string> <string name="empty_state_osm_edits_descr">POIها را اضافه یا ویرایش کنید، یادداشت‌های OSMای اضافه کنید یا روی آن‌ها نظر بدهید و فایل‌های GPX ضبط‌شده را آپلود کنید.</string>
<string name="shared_string_deleted">حذف‌شده(ها)</string> <string name="shared_string_deleted">حذف‌شده(ها)</string>
<string name="shared_string_edited">ویرایش شد</string> <string name="shared_string_edited">ویرایش شد</string>
@ -3479,7 +3479,7 @@
<string name="shared_string_importing">در حال درون‌برد</string> <string name="shared_string_importing">در حال درون‌برد</string>
<string name="shared_string_import_complete">درون‌برد کامل شد</string> <string name="shared_string_import_complete">درون‌برد کامل شد</string>
<string name="import_complete_description">همهٔ داده از %1$s درون‌برد شد. با استفاده از دکمه‌های زیر می‌توانید بخش موردنیاز برنامه را برای مدیریت آن باز کنید.</string> <string name="import_complete_description">همهٔ داده از %1$s درون‌برد شد. با استفاده از دکمه‌های زیر می‌توانید بخش موردنیاز برنامه را برای مدیریت آن باز کنید.</string>
<string name="shared_string_poi_types">انواع POI</string> <string name="shared_string_poi_types">گونه‌های POI</string>
<string name="listed_exist">%1$s که در زیر آمده، هم‌اکنون در OsmAnd وجود دارد.</string> <string name="listed_exist">%1$s که در زیر آمده، هم‌اکنون در OsmAnd وجود دارد.</string>
<string name="checking_for_duplicate_description">OsmAnd در حال بررسی %1$s برای چیزهای تکراری موجود در برنامه است. <string name="checking_for_duplicate_description">OsmAnd در حال بررسی %1$s برای چیزهای تکراری موجود در برنامه است.
\n \n
@ -4068,5 +4068,5 @@
<string name="on_pause">مکث کرده</string> <string name="on_pause">مکث کرده</string>
<string name="quick_action_coordinates_widget_descr">دکمه‌ای برای آشکار یا پنهان کردن ابزارک مختصات روی نقشه.</string> <string name="quick_action_coordinates_widget_descr">دکمه‌ای برای آشکار یا پنهان کردن ابزارک مختصات روی نقشه.</string>
<string name="shared_string_interval">بازه</string> <string name="shared_string_interval">بازه</string>
<string name="map_widget_distance_by_tap">فاصله با لمس دوانگشتی</string> <string name="map_widget_distance_by_tap">مسافت با لمس</string>
</resources> </resources>

View file

@ -1192,11 +1192,11 @@
<string name="gpx_file_is_empty">Fichier GPX vide</string> <string name="gpx_file_is_empty">Fichier GPX vide</string>
<string name="shared_string_tracks">Traces</string> <string name="shared_string_tracks">Traces</string>
<string name="shared_string_my_favorites">Favoris</string> <string name="shared_string_my_favorites">Favoris</string>
<string name="shared_string_my_places">Mes lieux favoris</string> <string name="shared_string_my_places">Lieux favoris</string>
<string name="selected_gpx_info_show">\n\nAppui long pour afficher sur la carte</string> <string name="selected_gpx_info_show">\n\nAppui long pour afficher sur la carte</string>
<string name="delay_navigation_start">Démarrer la navigation pas à pas automatiquement</string> <string name="delay_navigation_start">Démarrer la navigation pas à pas automatiquement</string>
<string name="shared_string_selected_lowercase">sélectionné(s)</string> <string name="shared_string_selected_lowercase">sélectionné(s)</string>
<string name="gpx_split_interval">Intervalle de division</string> <string name="gpx_split_interval">Intervalle de fractionnement</string>
<string name="local_index_gpx_info_show">\n\nAppui long pour afficher les options</string> <string name="local_index_gpx_info_show">\n\nAppui long pour afficher les options</string>
<string name="gpx_info_subtracks">Sections : %1$s </string> <string name="gpx_info_subtracks">Sections : %1$s </string>
<string name="gpx_info_waypoints">Points de passage : %1$s</string> <string name="gpx_info_waypoints">Points de passage : %1$s</string>
@ -4035,4 +4035,7 @@
<string name="quick_action_coordinates_widget_descr">Appuyer pour afficher ou cacher le widget Coordonnées sur la carte.</string> <string name="quick_action_coordinates_widget_descr">Appuyer pour afficher ou cacher le widget Coordonnées sur la carte.</string>
<string name="snap_to_road_descr">Licône de localisation va se déplacer sur le trajet en cours.</string> <string name="snap_to_road_descr">Licône de localisation va se déplacer sur le trajet en cours.</string>
<string name="select_another_colorization">Veuillez sélectionner un autre type de colorisation.</string> <string name="select_another_colorization">Veuillez sélectionner un autre type de colorisation.</string>
<string name="trip_recording_logging_interval_info">L\'intervalle denregistrement définit la fréquence à laquelle OsmAnd récupérera les données de localisation.</string>
<string name="trip_recording_save_and_continue">Enregistrer et continuer</string>
<string name="lost_data_warning">Toutes les données non enregistrées seront perdues.</string>
</resources> </resources>

View file

@ -4039,4 +4039,7 @@
<string name="live_update_frequency_week_variant">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).</string> <string name="live_update_frequency_week_variant">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).</string>
<string name="live_update_frequency_day_variant">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).</string> <string name="live_update_frequency_day_variant">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).</string>
<string name="live_update_frequency_hour_variant">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).</string> <string name="live_update_frequency_hour_variant">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).</string>
<string name="trip_recording_logging_interval_info">A naplózási intervallum az az időköz, amelyben az OsmAnd lekéri az aktuális helyadatokat.</string>
<string name="trip_recording_save_and_continue">Mentés és folytatás</string>
<string name="lost_data_warning">Minden nem mentett adat törlődni fog.</string>
</resources> </resources>

View file

@ -9,7 +9,7 @@
<string name="map_widget_show_destination_arrow">הצגת הכיוון ליעד</string> <string name="map_widget_show_destination_arrow">הצגת הכיוון ליעד</string>
<string name="enable_plugin_monitoring_services">יש להפעיל את תוסף „מעקב הטיול” כדי להשתמש בשירותי רישום מיקום (מעקב חי, רישום GPX)</string> <string name="enable_plugin_monitoring_services">יש להפעיל את תוסף „מעקב הטיול” כדי להשתמש בשירותי רישום מיקום (מעקב חי, רישום GPX)</string>
<string name="non_optimal_route_calculation">יש לחשב מסלול בלתי יעיל למרחקים ארוכים</string> <string name="non_optimal_route_calculation">יש לחשב מסלול בלתי יעיל למרחקים ארוכים</string>
<string name="gps_not_available">נא להפעיל את רכיב האיכון (GPS) בהגדרות</string> <string name="gps_not_available">נא להפעיל את ה־GPS בהגדרות</string>
<string name="map_widget_monitoring_services">שירותי רישום</string> <string name="map_widget_monitoring_services">שירותי רישום</string>
<string name="no_route">אין מסלול</string> <string name="no_route">אין מסלול</string>
<string name="delete_target_point">הסרת יעד</string> <string name="delete_target_point">הסרת יעד</string>
@ -1881,7 +1881,7 @@
<string name="si_m_s">מטרים לשנייה</string> <string name="si_m_s">מטרים לשנייה</string>
<string name="si_min_km">דקות לקילומטר</string> <string name="si_min_km">דקות לקילומטר</string>
<string name="si_min_m">דקות למייל</string> <string name="si_min_m">דקות למייל</string>
<string name="si_nm_h">מיל ימי לשעה (קשר)</string> <string name="si_nm_h">מייל ימי לשעה (קשר)</string>
<string name="nm_h">קשר</string> <string name="nm_h">קשר</string>
<string name="m_s">מ/שנ׳</string> <string name="m_s">מ/שנ׳</string>
<string name="shared_string_trip_recording">הקלטת טיול</string> <string name="shared_string_trip_recording">הקלטת טיול</string>
@ -4047,4 +4047,8 @@
<string name="latest_openstreetmap_update">קיים עדכון ל־OpenStreetMap:</string> <string name="latest_openstreetmap_update">קיים עדכון ל־OpenStreetMap:</string>
<string name="rendering_attr_noNatureReserveBoundaries_description">להסתיר גבולות של שמורות טבע, אזורים מוגנים ופארקים ציבוריים</string> <string name="rendering_attr_noNatureReserveBoundaries_description">להסתיר גבולות של שמורות טבע, אזורים מוגנים ופארקים ציבוריים</string>
<string name="rendering_attr_noNatureReserveBoundaries_name">גבולות טבעיים</string> <string name="rendering_attr_noNatureReserveBoundaries_name">גבולות טבעיים</string>
<string name="live_update_delete_updates_msg">למחוק את כל העדכונים החיים של %s\?</string>
<string name="trip_recording_logging_interval_info">הגדרת הפרש קבוע בין הבקשות של OsmAnd לקבלת נתוני המיקום הנוכחיים.</string>
<string name="trip_recording_save_and_continue">לשמור ולהמשיך</string>
<string name="lost_data_warning">כל הנתונים שלא נשמרו יאבדו.</string>
</resources> </resources>

View file

@ -3950,4 +3950,7 @@ POIの更新は利用できません</string>
<string name="track_has_no_altitude">経路には標高データは含まれていません。</string> <string name="track_has_no_altitude">経路には標高データは含まれていません。</string>
<string name="track_has_no_speed">経路には速度データは含まれていません。</string> <string name="track_has_no_speed">経路には速度データは含まれていません。</string>
<string name="select_another_colorization">別タイプのカラーを選択してください。</string> <string name="select_another_colorization">別タイプのカラーを選択してください。</string>
<string name="trip_recording_logging_interval_info">ログ記録間隔は、OsmAndが現在の位置データを要求する期間を設定します。</string>
<string name="trip_recording_save_and_continue">保存して続行</string>
<string name="lost_data_warning">保存されていないデータはすべて失われます。</string>
</resources> </resources>

View file

@ -3939,4 +3939,6 @@
<string name="routing_attr_short_way_description">Optimalisert kortere rute (energisparende)</string> <string name="routing_attr_short_way_description">Optimalisert kortere rute (energisparende)</string>
<string name="snap_to_road_descr">Aktuelle posisjonsikon vil bli festet til gjeldende navigeringsrute</string> <string name="snap_to_road_descr">Aktuelle posisjonsikon vil bli festet til gjeldende navigeringsrute</string>
<string name="routing_attr_height_obstacles_description">Ruting kan unngå kraftige oppoverbakker.</string> <string name="routing_attr_height_obstacles_description">Ruting kan unngå kraftige oppoverbakker.</string>
<string name="trip_recording_save_and_continue">Lagre og fortsett</string>
<string name="lost_data_warning">All ulagret data vil gå tapt.</string>
</resources> </resources>

View file

@ -4040,4 +4040,6 @@
<string name="select_another_colorization">Selecione outro tipo de colorização.</string> <string name="select_another_colorization">Selecione outro tipo de colorização.</string>
<string name="rendering_attr_noNatureReserveBoundaries_name">Limites naturais</string> <string name="rendering_attr_noNatureReserveBoundaries_name">Limites naturais</string>
<string name="segments_count">Segmento %1$d</string> <string name="segments_count">Segmento %1$d</string>
<string name="trip_recording_save_and_continue">Salvar e continuar</string>
<string name="lost_data_warning">Todos os dados não salvos serão perdidos.</string>
</resources> </resources>

View file

@ -84,7 +84,8 @@
<string name="select_animate_speedup">Välj animerad ruttacceleration</string> <string name="select_animate_speedup">Välj animerad ruttacceleration</string>
<string name="global_app_allocated_memory_descr">Allokerat minne %1$s MB (Android-gräns %2$s MB, Dalvik %3$s MB).</string> <string name="global_app_allocated_memory_descr">Allokerat minne %1$s MB (Android-gräns %2$s MB, Dalvik %3$s MB).</string>
<string name="global_app_allocated_memory">Allokerat minne</string> <string name="global_app_allocated_memory">Allokerat minne</string>
<string name="native_app_allocated_memory_descr">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).</string> <string name="native_app_allocated_memory_descr">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).</string>
<string name="native_app_allocated_memory">Totalt inbyggt minne</string> <string name="native_app_allocated_memory">Totalt inbyggt minne</string>
<string name="starting_point_too_far">Startpunkten ligger för långt från närmaste väg.</string> <string name="starting_point_too_far">Startpunkten ligger för långt från närmaste väg.</string>
<string name="shared_location">Delad plats</string> <string name="shared_location">Delad plats</string>
@ -165,9 +166,8 @@
<string name="osmand_parking_pm">em</string> <string name="osmand_parking_pm">em</string>
<string name="osmand_parking_am">fm</string> <string name="osmand_parking_am">fm</string>
<string name="osmand_parking_position_name">Parkeringsplats</string> <string name="osmand_parking_position_name">Parkeringsplats</string>
<string name="osmand_parking_plugin_description">Modulen Parkeringsplats hjälper dig att hålla reda på var din bil är parkerad och vid behov hur mycket parkeringstid det är kvar. <string name="osmand_parking_plugin_description">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.</string>
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.</string>
<string name="osmand_parking_plugin_name">Parkeringsplats</string> <string name="osmand_parking_plugin_name">Parkeringsplats</string>
<string name="context_menu_item_add_parking_point">Markera som parkeringsplats</string> <string name="context_menu_item_add_parking_point">Markera som parkeringsplats</string>
<string name="context_menu_item_delete_parking_point">Ta bort P-markering</string> <string name="context_menu_item_delete_parking_point">Ta bort P-markering</string>
@ -192,11 +192,11 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
<string name="map_online_data">Online-kartor och kartrutor</string> <string name="map_online_data">Online-kartor och kartrutor</string>
<string name="map_online_data_descr">Använd online-kartor (hämta och cacha kartbitar på SD-kortet).</string> <string name="map_online_data_descr">Använd online-kartor (hämta och cacha kartbitar på SD-kortet).</string>
<string name="online_map_settings_descr">Konfigurera online- eller cachade källor för kartbitar.</string> <string name="online_map_settings_descr">Konfigurera online- eller cachade källor för kartbitar.</string>
<string name="osmand_rastermaps_plugin_description">"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. <string name="osmand_rastermaps_plugin_description">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 \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 \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. "</string> \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.</string>
<string name="osmand_background_plugin_description">Visa inställningarna för att aktivera spårning och navigering i bakgrundsläge (skärm av) genom att periodvis väcka GPS-enheten.</string> <string name="osmand_background_plugin_description">Visa inställningarna för att aktivera spårning och navigering i bakgrundsläge (skärm av) genom att periodvis väcka GPS-enheten.</string>
<string name="osmand_development_plugin_description">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.</string> <string name="osmand_development_plugin_description">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.</string>
<string name="plugins_screen">Hantera insticksmoduler</string> <string name="plugins_screen">Hantera insticksmoduler</string>
@ -208,19 +208,33 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
<string name="osmand_parking_position_description">Din parkerade bils plats. %1$s</string> <string name="osmand_parking_position_description">Din parkerade bils plats. %1$s</string>
<string name="prefs_plugins_descr">Insticksmoduler aktiverar avancerade inställningar samt ger ytterligare funktionalitet.</string> <string name="prefs_plugins_descr">Insticksmoduler aktiverar avancerade inställningar samt ger ytterligare funktionalitet.</string>
<string name="prefs_plugins">Insticksmoduler</string> <string name="prefs_plugins">Insticksmoduler</string>
<string name="osm_editing_plugin_description">"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."</string> <string name="osm_editing_plugin_description">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.</string>
<string name="vector_maps_may_display_faster_on_some_devices">Vektorkartor ritas sannolikt upp snabbare. Fungerar kanske inte så bra på vissa enheter.</string> <string name="vector_maps_may_display_faster_on_some_devices">Vektorkartor ritas sannolikt upp snabbare. Fungerar kanske inte så bra på vissa enheter.</string>
<string name="play_commands_of_currently_selected_voice">Spela upp kommandon med vald röst</string> <string name="play_commands_of_currently_selected_voice">Spela upp kommandon med vald röst</string>
<string name="test_voice_prompts">Test av röstmeddelanden</string> <string name="test_voice_prompts">Test av röstmeddelanden</string>
<string name="switch_to_raster_map_to_see">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).</string> <string name="switch_to_raster_map_to_see">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).</string>
<string name="osmand_long_description_1000_chars">"OsmAnd (Open Street Maps Automated Navigation Directions) <string name="osmand_long_description_1000_chars">OsmAnd (OSM Automated Navigation Directions)
\n \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 \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 \n
\nBegränsningar i denna gratisversion av OsmAnd: - Antalet hämtningar av kartor är begränsat - Ingen tillgång till Wikipedia offline POIs \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 \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. \nBegränsningar av denna gratisversion av OsmAnd:
\n "</string> \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.</string>
<string name="native_rendering">Inbyggd rendering</string> <string name="native_rendering">Inbyggd rendering</string>
<string name="default_buttons_support">Support</string> <string name="default_buttons_support">Support</string>
<string name="support_new_features">Ge stöd till nya funktioner</string> <string name="support_new_features">Ge stöd till nya funktioner</string>
@ -297,9 +311,8 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
<string name="osmand_service">Bakgrundsläge</string> <string name="osmand_service">Bakgrundsläge</string>
<string name="osmand_service_descr">OsmAnd körs i bakgrunden medan skärmen är avstängd.</string> <string name="osmand_service_descr">OsmAnd körs i bakgrunden medan skärmen är avstängd.</string>
<string name="download_files_not_enough_space">Det finns inte tillräckligt med ledigt utrymme för att hämta %1$s MB (ledigt: %2$s).</string> <string name="download_files_not_enough_space">Det finns inte tillräckligt med ledigt utrymme för att hämta %1$s MB (ledigt: %2$s).</string>
<string name="download_files_question_space">Hämta {0} fil(er)? <string name="download_files_question_space">Hämta {0} fil(er)\?
Nyttjat utrymme är {1} MB. \n{1} MB (av {2} MB) kommer att användas.</string>
(Tillgängligt utrymme är {2} MB.)</string>
<string name="use_transparent_map_theme">Genomskinligt tema</string> <string name="use_transparent_map_theme">Genomskinligt tema</string>
<string name="native_library_not_supported">Inbyggt bibliotek stöds inte på den här enheten.</string> <string name="native_library_not_supported">Inbyggt bibliotek stöds inte på den här enheten.</string>
<string name="init_native_library">Initierar inbyggt bibliotek …</string> <string name="init_native_library">Initierar inbyggt bibliotek …</string>
@ -382,7 +395,7 @@ Nyttjat utrymme är {1} MB.
<string name="installing_new_resources">Packar upp nya data …</string> <string name="installing_new_resources">Packar upp nya data …</string>
<string name="internet_connection_required_for_online_route">En online-navigeringstjänst är vald men ingen internetanslutning är tillgänglig.</string> <string name="internet_connection_required_for_online_route">En online-navigeringstjänst är vald men ingen internetanslutning är tillgänglig.</string>
<string name="tts_language_not_supported_title">Språket stöds inte</string> <string name="tts_language_not_supported_title">Språket stöds inte</string>
<string name="tts_language_not_supported">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.</string> <string name="tts_language_not_supported">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\?</string>
<string name="tts_missing_language_data_title">Data saknas</string> <string name="tts_missing_language_data_title">Data saknas</string>
<string name="tts_missing_language_data">Inga data för det valda språket är installerade. Vill du besöka Google Play för att installera?</string> <string name="tts_missing_language_data">Inga data för det valda språket är installerade. Vill du besöka Google Play för att installera?</string>
<string name="gpx_option_reverse_route">Omvänd GPX-riktning</string> <string name="gpx_option_reverse_route">Omvänd GPX-riktning</string>
@ -701,7 +714,7 @@ Nyttjat utrymme är {1} MB.
<string name="search_villages_and_postcodes">Sök efter fler byar/postnummer</string> <string name="search_villages_and_postcodes">Sök efter fler byar/postnummer</string>
<string name="rendering_attr_showRoadMaps_description">Välj när du vill visa kartor som endast har vägar:</string> <string name="rendering_attr_showRoadMaps_description">Välj när du vill visa kartor som endast har vägar:</string>
<string name="rendering_attr_showRoadMaps_name">Kartor med enbart vägar</string> <string name="rendering_attr_showRoadMaps_name">Kartor med enbart vägar</string>
<string name="download_roads_only_item">"Vägar "</string> <string name="download_roads_only_item">Bara vägar</string>
<string name="download_regular_maps">Standardkartor</string> <string name="download_regular_maps">Standardkartor</string>
<string name="download_roads_only_maps">Karta med enbart vägar</string> <string name="download_roads_only_maps">Karta med enbart vägar</string>
<string name="safe_mode_description">Kör appen i felsäkert läge (för långsammare Android istället för intern kod).</string> <string name="safe_mode_description">Kör appen i felsäkert läge (för långsammare Android istället för intern kod).</string>
@ -783,9 +796,9 @@ Nyttjat utrymme är {1} MB.
<string name="av_settings">Inställningar för ljud och video </string> <string name="av_settings">Inställningar för ljud och video </string>
<string name="recording_error">Ett fel uppstod under inspelningen </string> <string name="recording_error">Ett fel uppstod under inspelningen </string>
<string name="recording_camera_not_available">Ingen kamera tillgänglig</string> <string name="recording_camera_not_available">Ingen kamera tillgänglig</string>
<string name="srtm_plugin_description">"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. <string name="srtm_plugin_description">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 \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). "</string> \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).</string>
<string name="delete_target_point">Ta bort destination</string> <string name="delete_target_point">Ta bort destination</string>
<string name="intermediate_point">Mellanliggande destination %1$s</string> <string name="intermediate_point">Mellanliggande destination %1$s</string>
<string name="poi_filter_nominatim">Online Nominatim</string> <string name="poi_filter_nominatim">Online Nominatim</string>
@ -874,11 +887,11 @@ Nyttjat utrymme är {1} MB.
<string name="prefer_in_routing_descr">Föredra motorvägar.</string> <string name="prefer_in_routing_descr">Föredra motorvägar.</string>
<string name="item_checked">markerad</string> <string name="item_checked">markerad</string>
<string name="item_unchecked">ej markerad</string> <string name="item_unchecked">ej markerad</string>
<string name="av_def_action_choose">Välj vid användning</string> <string name="av_def_action_choose">På förfrågan\?</string>
<string name="enable_plugin_monitoring_services">Aktivera Trippinspelningspluginen för att använda positionsloggningstjänster (GPX-loggning, online-spårning)</string> <string name="enable_plugin_monitoring_services">Aktivera Trippinspelningspluginen för att använda positionsloggningstjänster (GPX-loggning, online-spårning)</string>
<string name="osmand_srtm_long_description_1000_chars">"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. <string name="osmand_srtm_long_description_1000_chars">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 \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). "</string> \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).</string>
<string name="access_arrival_time">Ankomsttid</string> <string name="access_arrival_time">Ankomsttid</string>
<string name="index_name_openmaps">OpenMaps EU</string> <string name="index_name_openmaps">OpenMaps EU</string>
<string name="layer_hillshade">Skuggad relief-lager</string> <string name="layer_hillshade">Skuggad relief-lager</string>
@ -892,7 +905,7 @@ Nyttjat utrymme är {1} MB.
<string name="files_limit">%1$d filer kvar</string> <string name="files_limit">%1$d filer kvar</string>
<string name="available_downloads_left">Du har %1$d filer kvar att hämta</string> <string name="available_downloads_left">Du har %1$d filer kvar att hämta</string>
<string name="install_paid">Fullversion</string> <string name="install_paid">Fullversion</string>
<string name="cancel_route">Avbryt rutten</string> <string name="cancel_route">Avbryt rutten\?</string>
<string name="cancel_navigation">Avbryt navigeringen</string> <string name="cancel_navigation">Avbryt navigeringen</string>
<string name="clear_destination">Ta bort destinationen</string> <string name="clear_destination">Ta bort destinationen</string>
<string name="download_using_mobile_internet">Wi-Fi är för tillfället inte anslutet. Vill du hämta med din nuvarande anslutning till Internet?</string> <string name="download_using_mobile_internet">Wi-Fi är för tillfället inte anslutet. Vill du hämta med din nuvarande anslutning till Internet?</string>
@ -1218,9 +1231,9 @@ Nyttjat utrymme är {1} MB.
<string name="speak_poi">Närbelägna intresssepunkter</string> <string name="speak_poi">Närbelägna intresssepunkter</string>
<string name="index_tours">Rundturer</string> <string name="index_tours">Rundturer</string>
<string name="shared_string_all">Alla</string> <string name="shared_string_all">Alla</string>
<string name="record_plugin_description">"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. <string name="record_plugin_description">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 \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. "</string> \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.</string>
<string name="record_plugin_name">Inspelning av resa</string> <string name="record_plugin_name">Inspelning av resa</string>
<string name="int_hour">h</string> <string name="int_hour">h</string>
<string name="duration">Längd</string> <string name="duration">Längd</string>
@ -1279,7 +1292,7 @@ Nyttjat utrymme är {1} MB.
<string name="everything_up_to_date">Alla filer är uppdaterade</string> <string name="everything_up_to_date">Alla filer är uppdaterade</string>
<string name="use_opengl_render">Använd OpenGL-rendering</string> <string name="use_opengl_render">Använd OpenGL-rendering</string>
<string name="use_opengl_render_descr">Använd hårdvaruaccelererad OpenGL-rendering (fungerar kanske inte på vissa enheter).</string> <string name="use_opengl_render_descr">Använd hårdvaruaccelererad OpenGL-rendering (fungerar kanske inte på vissa enheter).</string>
<string name="no_internet_connection">Kan inte hämta; kontrollera din internetsanslutning.</string> <string name="no_internet_connection">Kan inte hämta, kontrollera din internetsanslutning.</string>
<string name="rendering_attr_roadStyle_name">Vägtyp</string> <string name="rendering_attr_roadStyle_name">Vägtyp</string>
<string name="rendering_value_default_name">Standard</string> <string name="rendering_value_default_name">Standard</string>
<string name="rendering_value_orange_name">Brandgul</string> <string name="rendering_value_orange_name">Brandgul</string>
@ -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\'. \nEn kartfil som innehåller alla nautiska symboler globalt finns tillgänglig som en enda nedladdning med namnet \'World seamarks\'.
\n \n
\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor.</string> \nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor.</string>
<string name="plugin_ski_descr">"Om du aktiverar denna vy ändras kartstilen till Vinter och skidor, och visar landskapet i vinterskrud. <string name="plugin_ski_descr">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\nEn global karta med alla pister och längdskidspår i denna vy finns tillgänglig under Alla kartor som \'World ski map\'. \n
\n\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor. "</string> \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.</string>
<string name="plugin_touringview_descr">"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. <string name="plugin_touringview_descr">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
\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. \nDenna vy ger, vid varje zoomnivå, maximalt antal detaljer som är tillgängliga i kartdatat (speciellt vägar, stigar och orienteringsmärken).
\n\nDenna vy kan ändras genom att antingen inaktivera den här igen eller genom att ändra kartstilen under Konfigurera kartor. "</string> \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.</string>
<string name="location_on_map">Plats:\n Lat %1$s\n Lon %2$s</string> <string name="location_on_map">Plats:\n Lat %1$s\n Lon %2$s</string>
<string name="plugin_touringview_name">Vägkartsvy</string> <string name="plugin_touringview_name">Vägkartsvy</string>
<string name="days_behind">dagar efter</string> <string name="days_behind">dagar efter</string>
@ -1423,7 +1443,7 @@ Nyttjat utrymme är {1} MB.
<string name="simulate_your_location">Simulera din plats</string> <string name="simulate_your_location">Simulera din plats</string>
<string name="drawer">Platt lista</string> <string name="drawer">Platt lista</string>
<string name="short_location_on_map">Lat %1$s <string name="short_location_on_map">Lat %1$s
Long %2$s</string> \nLong %2$s</string>
<string name="tips_and_tricks_descr">Frågor och svar, nyliga förändringar och annat.</string> <string name="tips_and_tricks_descr">Frågor och svar, nyliga förändringar och annat.</string>
<string name="routing_settings_2">Navigeringsinställningar</string> <string name="routing_settings_2">Navigeringsinställningar</string>
<string name="general_settings_2">Allmänna inställningar</string> <string name="general_settings_2">Allmänna inställningar</string>
@ -1495,7 +1515,7 @@ Long %2$s</string>
<string name="local_recordings_delete_all_confirm">Du håller på att ta bort %1$d anteckningar. Är du säker?</string> <string name="local_recordings_delete_all_confirm">Du håller på att ta bort %1$d anteckningar. Är du säker?</string>
<string name="download_wikipedia_maps">Wikipedia</string> <string name="download_wikipedia_maps">Wikipedia</string>
<string name="shared_string_import2osmand">Importera till OsmAnd</string> <string name="shared_string_import2osmand">Importera till OsmAnd</string>
<string name="gps_network_not_enabled">Platstjänsten är inte aktiverad. Vill du slå på den?</string> <string name="gps_network_not_enabled">Platstjänsten är av. Vill du slå på den\?</string>
<string name="archive_wikipedia_data">Du har gamla och inkompatibla data från Wikipedia. Vill du arkivera dem?</string> <string name="archive_wikipedia_data">Du har gamla och inkompatibla data från Wikipedia. Vill du arkivera dem?</string>
<string name="download_wikipedia_files">Hämta ytterligare data från Wikipedia (%1$s MB)?</string> <string name="download_wikipedia_files">Hämta ytterligare data från Wikipedia (%1$s MB)?</string>
<string name="lang_vo">Volapük</string> <string name="lang_vo">Volapük</string>
@ -1611,7 +1631,7 @@ Long %2$s</string>
<string name="si_m_s">Meter per sekund</string> <string name="si_m_s">Meter per sekund</string>
<string name="si_min_km">Minuter per kilometer</string> <string name="si_min_km">Minuter per kilometer</string>
<string name="si_min_m">Minuter per mile</string> <string name="si_min_m">Minuter per mile</string>
<string name="si_nm_h">Sjömil i timmen (knop)</string> <string name="si_nm_h">Sjömil per timme (knop)</string>
<string name="shared_string_trip_recording">Inspelning av resa</string> <string name="shared_string_trip_recording">Inspelning av resa</string>
<string name="shared_string_navigation">Navigering</string> <string name="shared_string_navigation">Navigering</string>
<string name="osmand_running_in_background">Körs i bakgrunden</string> <string name="osmand_running_in_background">Körs i bakgrunden</string>
@ -1619,7 +1639,7 @@ Long %2$s</string>
<string name="favorite_category_select">Välj kategori</string> <string name="favorite_category_select">Välj kategori</string>
<string name="count_of_lines">Antal rader</string> <string name="count_of_lines">Antal rader</string>
<string name="nm">di</string> <string name="nm">di</string>
<string name="nm_h">nmi/h</string> <string name="nm_h">M</string>
<string name="min_mile">min/mi</string> <string name="min_mile">min/mi</string>
<string name="min_km">min/km</string> <string name="min_km">min/km</string>
<string name="m_s">m/s</string> <string name="m_s">m/s</string>
@ -1746,7 +1766,7 @@ Long %2$s</string>
<string name="route_distance">Avstånd:</string> <string name="route_distance">Avstånd:</string>
<string name="route_duration">Tid:</string> <string name="route_duration">Tid:</string>
<string name="missing_write_external_storage_permission">Appen har inte tillåtelse att använda SD-kortet</string> <string name="missing_write_external_storage_permission">Appen har inte tillåtelse att använda SD-kortet</string>
<string name="no_location_permission">Appen har inte tillräckliga behörigheter för att komma åt platsdata.</string> <string name="no_location_permission">Appen saknar behörigheter för att komma åt platsdata.</string>
<string name="no_camera_permission">Appen har inte tillräckliga behörigheter för att komma åt kameran.</string> <string name="no_camera_permission">Appen har inte tillräckliga behörigheter för att komma åt kameran.</string>
<string name="no_microphone_permission">Appen har inte tillräckliga behörigheter för att komma åt mikrofonen.</string> <string name="no_microphone_permission">Appen har inte tillräckliga behörigheter för att komma åt mikrofonen.</string>
<string name="select_voice_provider">Välj röstvägledning</string> <string name="select_voice_provider">Välj röstvägledning</string>
@ -1807,9 +1827,10 @@ Long %2$s</string>
<string name="shared_string_toolbar">Verktygsfält</string> <string name="shared_string_toolbar">Verktygsfält</string>
<string name="shared_string_widgets">Widgetar</string> <string name="shared_string_widgets">Widgetar</string>
<string name="download_files_error_not_enough_space">Inte tillräckligt med utrymme! <string name="download_files_error_not_enough_space">Inte tillräckligt med utrymme!
Detta skulle kräva {3} MB temporärt och {1} MB permanent. \n{3} MB temporärt och {1} MB permanent.
Tillgängligt utrymme är blott {2} MB.</string> \n(Bara {2} MB tillgängligt.)</string>
<string name="download_files_question_space_with_temp">Hämta {0} fil(er)? Nyttjat utrymme är {3} MB temporärt och {1} MB permanent. (Tillgängligt utrymme är {2} MB.)</string> <string name="download_files_question_space_with_temp">Hämta {0} fil(er)\?
\n{3} MB används temporärt och {1} MB permanent. (Av{2} MB.)</string>
<string name="upload_osm_note">Ladda upp OSM-anteckning</string> <string name="upload_osm_note">Ladda upp OSM-anteckning</string>
<string name="upload_anonymously">Ladda upp anonymt</string> <string name="upload_anonymously">Ladda upp anonymt</string>
<string name="select_map_marker">Välj kartmarkör</string> <string name="select_map_marker">Välj kartmarkör</string>
@ -1879,8 +1900,8 @@ Tillgängligt utrymme är blott {2} MB.</string>
<string name="storage_permission_restart_is_required">Nu har appen tillåtelse att skriva till extern lagringsplats. En manuell omstart av appen krävs.</string> <string name="storage_permission_restart_is_required">Nu har appen tillåtelse att skriva till extern lagringsplats. En manuell omstart av appen krävs.</string>
<string name="osm_live_support_region">Stödregion</string> <string name="osm_live_support_region">Stödregion</string>
<string name="osm_live_header">Denna prenumeration aktiverar uppdateringar varje timme av kartor runt omkring i världen. <string name="osm_live_header">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. \nEn 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å.</string> \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å.</string>
<string name="access_no_destination">Destinationen är inte fastställd</string> <string name="access_no_destination">Destinationen är inte fastställd</string>
<string name="map_widget_magnetic_bearing">Magnetisk bäring</string> <string name="map_widget_magnetic_bearing">Magnetisk bäring</string>
<string name="rec_split_clip_length">Klipplängd</string> <string name="rec_split_clip_length">Klipplängd</string>
@ -1936,7 +1957,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
<string name="delete_filter">Ta bort filter</string> <string name="delete_filter">Ta bort filter</string>
<string name="new_filter">Nytt filter</string> <string name="new_filter">Nytt filter</string>
<string name="new_filter_desc">Ange ett namn på det nya filtret. Det kommer att läggas till på fliken Kategorier.</string> <string name="new_filter_desc">Ange ett namn på det nya filtret. Det kommer att läggas till på fliken Kategorier.</string>
<string name="translit_name_if_miss">"Transkribera om %1$s namn saknas"</string> <string name="translit_name_if_miss">Transkribera om %1$s namn saknas</string>
<string name="skip_map_downloading">Hoppa över nerladdning av kartor</string> <string name="skip_map_downloading">Hoppa över nerladdning av kartor</string>
<string name="search_another_country">Välj en annan region</string> <string name="search_another_country">Välj en annan region</string>
<string name="osmand_plus_banner_desc">Obegränsade nedladdningar av kartor, uppdateringar och Wikipedia-plugin.</string> <string name="osmand_plus_banner_desc">Obegränsade nedladdningar av kartor, uppdateringar och Wikipedia-plugin.</string>
@ -1960,7 +1981,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
<string name="donation_to_osm">Donation till OpenStreetMap-gemenskapen</string> <string name="donation_to_osm">Donation till OpenStreetMap-gemenskapen</string>
<string name="get_it">Skaffa det</string> <string name="get_it">Skaffa det</string>
<string name="get_for">Skaffa för %1$s</string> <string name="get_for">Skaffa för %1$s</string>
<string name="skip_map_downloading_desc">"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\'."</string> <string name="skip_map_downloading_desc">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\'.</string>
<string name="search_map">Söker efter kartor …</string> <string name="search_map">Söker efter kartor …</string>
<string name="first_usage_greeting">Erhåll vägbeskrivningar och upptäck nya platser utan Internetuppkoppling</string> <string name="first_usage_greeting">Erhåll vägbeskrivningar och upptäck nya platser utan Internetuppkoppling</string>
<string name="search_my_location">Sök efter min plats</string> <string name="search_my_location">Sök efter min plats</string>
@ -2047,7 +2068,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
<string name="navigate_point_olc_info_invalid">Ogiltig OLC <string name="navigate_point_olc_info_invalid">Ogiltig OLC
\n</string> \n</string>
<string name="navigate_point_olc_info_short">Kort OLC <string name="navigate_point_olc_info_short">Kort OLC
Vänligen tillhandahåll fullständig kod</string> \nVänligen tillhandahåll fullständig kod</string>
<string name="file_can_not_be_moved">Filen kan inte flyttas.</string> <string name="file_can_not_be_moved">Filen kan inte flyttas.</string>
<string name="shared_string_move">Flytta</string> <string name="shared_string_move">Flytta</string>
<string name="shared_string_gpx_tracks">Spår</string> <string name="shared_string_gpx_tracks">Spår</string>
@ -2090,7 +2111,7 @@ Vänligen tillhandahåll fullständig kod</string>
<string name="shared_string_action_name">Åtgärdsnamn</string> <string name="shared_string_action_name">Åtgärdsnamn</string>
<string name="quick_action_map_overlay_title">Kartöverlägg</string> <string name="quick_action_map_overlay_title">Kartöverlägg</string>
<string name="quick_action_map_overlay_action">Lägg till överlägg</string> <string name="quick_action_map_overlay_action">Lägg till överlägg</string>
<string name="quick_action_map_overlay_switch">"Kartöverlägget har ändrats till \"%s\"."</string> <string name="quick_action_map_overlay_switch">Kartöverlägget har ändrats till \"%s\".</string>
<string name="quick_action_btn_tutorial_descr">Tryck länge och dra knappen för att ändra dess position på skärmen.</string> <string name="quick_action_btn_tutorial_descr">Tryck länge och dra knappen för att ändra dess position på skärmen.</string>
<string name="routing_attr_height_obstacles_name">Använd höjddata</string> <string name="routing_attr_height_obstacles_name">Använd höjddata</string>
<string name="rendering_attr_depthContours_description">Visa djupkonturer och punkter.</string> <string name="rendering_attr_depthContours_description">Visa djupkonturer och punkter.</string>
@ -2420,7 +2441,9 @@ Vänligen tillhandahåll fullständig kod</string>
<string name="max_min">Max/Min</string> <string name="max_min">Max/Min</string>
<string name="min_max">Min/Max</string> <string name="min_max">Min/Max</string>
<string name="route_is_too_long_v2">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.</string> <string name="route_is_too_long_v2">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.</string>
<string name="osmand_extended_description_part1">"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."</string> <string name="osmand_extended_description_part1">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.</string>
<string name="osmand_extended_description_part2">GPS-navigering <string name="osmand_extended_description_part2">GPS-navigering
\n• Välj mellan offline- (inga roaming-avgifter när du är utomlands) eller online-läge a(snabbare) \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) \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</string>
\n • Låter dig välja hur du vill visa namn på kartan: på svenska, lokala, eller fonetisk stavning \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 • Visar specialiserade online-rutor, satellitvy (från Bing), olika överlägg som tour/navigering GPX-spår och ytterligare lager med anpassningsbar transparens
\n</string> \n</string>
<string name="osmand_extended_description_part4">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.</string> <string name="osmand_extended_description_part4">Skidåkning
<string name="osmand_extended_description_part5">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</string> \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.</string>
<string name="osmand_extended_description_part5">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</string>
<string name="osmand_extended_description_part6">Promenader, vandring, stadsrundtur <string name="osmand_extended_description_part6">Promenader, vandring, stadsrundtur
\n • Kartan visar promenad- och vandringsleder \n • Kartan visar promenad- och vandringsleder
\n • Wikipedia på ditt föredragna språk kan berätta en hel del under en stadsrundtur \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</string>
\n</string> \n</string>
<string name="clear_all_intermediates">Rensa alla mellanliggande punkter</string> <string name="clear_all_intermediates">Rensa alla mellanliggande punkter</string>
<string name="rendering_attr_whiteWaterSports_name">Strömsporter</string> <string name="rendering_attr_whiteWaterSports_name">Strömsporter</string>
<string name="osmand_extended_description_part8">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 &amp; 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.</string> <string name="osmand_extended_description_part8">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.
<string name="osmand_plus_long_description_1000_chars">OsmAnd+ (OSM Automated Navigation Directions) \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.</string>
<string name="osmand_plus_long_description_1000_chars">OsmAnd + (OSM Automated Navigation Directions)
\n \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 \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 \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
\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- Offline sökning efter adresser och platser (POI)
\n \n- Offline-dirigering för medelstora avstånd
\n - Valfri hastighetsbunden kartzoom - valfri kartjustering enligt kompass eller riktning - som tillval körfältsguide, hastighetsgräns visas, inspelade- och TTS-röster</string> \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</string>
<string name="nothing_found_in_radius">Kunde inte hitta något inom:</string> <string name="nothing_found_in_radius">Kunde inte hitta något inom:</string>
<string name="select_waypoints_category_description">Lägg till alla spårens vägpunkter, eller välj separata kategorier.</string> <string name="select_waypoints_category_description">Lägg till alla spårens vägpunkter, eller välj separata kategorier.</string>
<string name="shared_string_total">Totalt</string> <string name="shared_string_total">Totalt</string>
<string name="osmand_plus_extended_description_part1">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:</string> <string name="osmand_plus_extended_description_part1">OsmAnd+ (OSM Automated Navigation Directions) är en kartnavigationsapp med tillgång till gratis världsomfattande och högkvalitativa OSM-data.
<string name="osmand_plus_extended_description_part2">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</string> \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:</string>
<string name="osmand_plus_extended_description_part2">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</string>
<string name="osmand_plus_extended_description_part3">Kartvisning <string name="osmand_plus_extended_description_part3">Kartvisning
\n • Visa din position och orientering \n • Visa din position och orientering
\n • Eventuellt justera bilden i förhållande till kompass eller din riktning \n • Eventuellt justera bilden i förhållande till kompass eller din riktning
@ -2490,8 +2554,7 @@ Vänligen tillhandahåll fullständig kod</string>
<string name="save_poi_too_many_uppercase">Namnet innehåller för många versaler. Vill du fortsätta?</string> <string name="save_poi_too_many_uppercase">Namnet innehåller för många versaler. Vill du fortsätta?</string>
<string name="quick_action_add_gpx_descr">Knackning på åtgärdsknappen kommer att lägga till en GPX-punkt vid skärmens mitt.</string> <string name="quick_action_add_gpx_descr">Knackning på åtgärdsknappen kommer att lägga till en GPX-punkt vid skärmens mitt.</string>
<string name="quick_action_take_audio_note_descr">Knackning på åtgärdsknappen kommer att lägga en ljudanteckning vid skärmens mitt.</string> <string name="quick_action_take_audio_note_descr">Knackning på åtgärdsknappen kommer att lägga en ljudanteckning vid skärmens mitt.</string>
<string name="quick_action_take_video_note_descr">Att trycka på denna åtgärdsknapp lägger <string name="quick_action_take_video_note_descr">Att trycka på denna åtgärdsknapp lägger till en videoanteckning mitt på skärmen.</string>
\ntill en videoanteckning mitt på skärmen.</string>
<string name="quick_action_take_photo_note_descr">Knackning på åtgärdsknappen kommer att lägga till en fotoanteckning vid skärmens mitt.</string> <string name="quick_action_take_photo_note_descr">Knackning på åtgärdsknappen kommer att lägga till en fotoanteckning vid skärmens mitt.</string>
<string name="quick_action_add_osm_bug_descr">Knackning på åtgärdsknappen kommer att lägga till en OSM-anteckning vid skärmens mitt.</string> <string name="quick_action_add_osm_bug_descr">Knackning på åtgärdsknappen kommer att lägga till en OSM-anteckning vid skärmens mitt.</string>
<string name="quick_action_add_poi_descr">Knackning på åtgärdsknappen kommer att lägga till en Intressepunkt vid skärmens mitt.</string> <string name="quick_action_add_poi_descr">Knackning på åtgärdsknappen kommer att lägga till en Intressepunkt vid skärmens mitt.</string>
@ -2600,7 +2663,13 @@ Vänligen tillhandahåll fullständig kod</string>
\n• Valfri hastighetsbaserad zoomning \n• Valfri hastighetsbaserad zoomning
\n• Dela din position så att dina vänner kan hitta dig \n• Dela din position så att dina vänner kan hitta dig
\n</string> \n</string>
<string name="osmand_plus_extended_description_part6">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)</string> <string name="osmand_plus_extended_description_part6">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)</string>
<string name="osmand_plus_extended_description_part7">Bidra direkt till OSM <string name="osmand_plus_extended_description_part7">Bidra direkt till OSM
\n• Rapportera databuggar \n• Rapportera databuggar
\n• Ladda upp GPX-spår till OSM direkt från appen \n• Ladda upp GPX-spår till OSM direkt från appen
@ -3267,4 +3336,9 @@ Vänligen tillhandahåll fullständig kod</string>
<string name="track_has_no_altitude">Spåret innehåller inte höjddata.</string> <string name="track_has_no_altitude">Spåret innehåller inte höjddata.</string>
<string name="track_has_no_speed">Spåret innehåller inte hastighetsdata.</string> <string name="track_has_no_speed">Spåret innehåller inte hastighetsdata.</string>
<string name="select_another_colorization">Välj en annan typ av färgning.</string> <string name="select_another_colorization">Välj en annan typ av färgning.</string>
<string name="save_heading_descr">Spara riktning till varje spårningspunkt under inspelning.</string>
<string name="app_mode_go_cart">Go-cart</string>
<string name="trip_recording_logging_interval_info">Loggningsintervall ställde in den tidsperiod under vilken OsmAnd kommer att be om aktuell positionspositionsdata.</string>
<string name="trip_recording_save_and_continue">Spara och fortsätt</string>
<string name="lost_data_warning">All osparad data kommer att försvinna.</string>
</resources> </resources>

View file

@ -4044,4 +4044,7 @@
<string name="select_another_colorization">Виберіть інший тип забарвлення.</string> <string name="select_another_colorization">Виберіть інший тип забарвлення.</string>
<string name="rendering_attr_noNatureReserveBoundaries_description">Сховати природні заповідники, заповідні території та межі національних парків</string> <string name="rendering_attr_noNatureReserveBoundaries_description">Сховати природні заповідники, заповідні території та межі національних парків</string>
<string name="rendering_attr_noNatureReserveBoundaries_name">Межі природи</string> <string name="rendering_attr_noNatureReserveBoundaries_name">Межі природи</string>
<string name="trip_recording_logging_interval_info">Інтервал журналювання встановлює проміжок часу, впродовж якого OsmAnd запитуватиме дані про поточне розташування.</string>
<string name="trip_recording_save_and_continue">Зберегти й продовжити</string>
<string name="lost_data_warning">Усі незбережені дані буде втрачено.</string>
</resources> </resources>

View file

@ -4038,4 +4038,7 @@
<string name="select_another_colorization">請選擇另一種顏色。</string> <string name="select_another_colorization">請選擇另一種顏色。</string>
<string name="rendering_attr_noNatureReserveBoundaries_description">隱藏自然保留區、保護區與國家公園界線</string> <string name="rendering_attr_noNatureReserveBoundaries_description">隱藏自然保留區、保護區與國家公園界線</string>
<string name="rendering_attr_noNatureReserveBoundaries_name">自然界線</string> <string name="rendering_attr_noNatureReserveBoundaries_name">自然界線</string>
<string name="trip_recording_logging_interval_info">紀錄間隔設定的時段OsmAnd 將會要求目前位置的位置資料。</string>
<string name="trip_recording_save_and_continue">儲存並繼續</string>
<string name="lost_data_warning">所有未儲存的資料都將會遺失。</string>
</resources> </resources>

View file

@ -11,6 +11,17 @@
Thx - Hardy Thx - Hardy
--> -->
<string name="release_4_0_beta">
• 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
</string>
<string name="specify_color_for_map_mode">Specify color for map mode: %1$s.</string>
<string name="route_line_use_map_style_appearance">Route line would be use %1$s specified on selected map style: %2$s.</string>
<string name="shared_string_route_line">Route line</string>
<string name="customize_route_line">Customize route line</string>
<string name="trip_recording_show_start_dialog_setting">If disabled, recording will start right after tap on the widget or menu item, skipping the confirmation dialog.</string> <string name="trip_recording_show_start_dialog_setting">If disabled, recording will start right after tap on the widget or menu item, skipping the confirmation dialog.</string>
<string name="show_start_dialog">Show start dialog</string> <string name="show_start_dialog">Show start dialog</string>
<string name="lost_data_warning">All unsaved data will be lost.</string> <string name="lost_data_warning">All unsaved data will be lost.</string>

View file

@ -76,4 +76,11 @@
android:title="@string/select_navigation_icon" android:title="@string/select_navigation_icon"
android:selectable="false"/> android:selectable="false"/>
<Preference
android:key="customize_route_line"
android:layout="@layout/preference_button"
android:persistent="false"
android:title="@string/customize_route_line"
android:icon="@drawable/ic_action_route_distance" />
</PreferenceScreen> </PreferenceScreen>

View file

@ -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;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType; import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.plus.settings.fragments.ConfigureProfileFragment; 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.TrackAppearanceFragment;
import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint; import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
@ -2265,6 +2266,10 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
return getFragment(TrackMenuFragment.TAG); return getFragment(TrackMenuFragment.TAG);
} }
public RouteLineAppearanceFragment getRouteLineAppearanceFragment() {
return getFragment(RouteLineAppearanceFragment.TAG);
}
public void backToConfigureProfileFragment() { public void backToConfigureProfileFragment() {
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentManager fragmentManager = getSupportFragmentManager();
int backStackEntryCount = fragmentManager.getBackStackEntryCount(); int backStackEntryCount = fragmentManager.getBackStackEntryCount();

View file

@ -193,10 +193,7 @@ public class SelectMapStyleBottomSheetDialogFragment extends MenuBottomSheetDial
List<String> names = new ArrayList<>(renderers.keySet()); List<String> names = new ArrayList<>(renderers.keySet());
for (String name : names) { for (String name : names) {
String translation = RendererRegistry.getTranslatedRendererName(context, name); String translation = RendererRegistry.getRendererName(context, name);
if (translation == null) {
translation = name.replace('_', ' ').replace('-', ' ');
}
res.put(translation, name); res.put(translation, name);
} }

View file

@ -30,7 +30,7 @@ public class WhatsNewDialogFragment extends DialogFragment {
final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication(); final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication();
final String appVersion = Version.getAppVersion(osmandApplication); final String appVersion = Version.getAppVersion(osmandApplication);
builder.setTitle(getString(R.string.whats_new) + " " + appVersion) 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); .setNegativeButton(R.string.shared_string_close, null);
if (AppInitializer.LATEST_CHANGES_URL != null) { if (AppInitializer.LATEST_CHANGES_URL != null) {
builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() {

View file

@ -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.AFTER;
import static net.osmand.plus.measurementtool.command.ClearPointsCommand.ClearCommandMode.ALL; 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.measurementtool.command.ClearPointsCommand.ClearCommandMode.BEFORE;
import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener, public class MeasurementToolFragment extends BaseOsmAndFragment implements RouteBetweenPointsFragmentListener,
OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener, OptionsFragmentListener, GpxApproximationFragmentListener, SelectedPointFragmentListener,
@ -906,7 +907,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
case SnapTrackWarningFragment.CONTINUE_RESULT_CODE: case SnapTrackWarningFragment.CONTINUE_RESULT_CODE:
if (mapActivity != null) { if (mapActivity != null) {
ApplicationMode mode = editingCtx.getAppMode(); 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; mode = null;
} }
List<List<WptPt>> pointsSegments = editingCtx.getPointsSegments(true, false); List<List<WptPt>> pointsSegments = editingCtx.getPointsSegments(true, false);

View file

@ -20,6 +20,8 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class ProfileCard extends BaseCard { public class ProfileCard extends BaseCard {
private ApplicationMode selectedMode; private ApplicationMode selectedMode;
@ -42,7 +44,7 @@ public class ProfileCard extends BaseCard {
Iterator<ApplicationMode> iterator = modes.iterator(); Iterator<ApplicationMode> iterator = modes.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
ApplicationMode mode = iterator.next(); ApplicationMode mode = iterator.next();
if ("public_transport".equals(mode.getRoutingProfile())) { if (PUBLIC_TRANSPORT_KEY.equals(mode.getRoutingProfile())) {
iterator.remove(); iterator.remove();
} }
} }

View file

@ -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.UiUtilities.CustomRadioButtonType.START;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.DEFAULT_APP_MODE; 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.measurementtool.SelectFileBottomSheet.BOTTOM_SHEET_HEIGHT_DP;
import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBehaviourDialogFragment { public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBehaviourDialogFragment {
@ -116,7 +117,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetBeha
for (int i = 0; i < modes.size(); i++) { for (int i = 0; i < modes.size(); i++) {
ApplicationMode mode = modes.get(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)); icon = app.getUIUtilities().getPaintedIcon(mode.getIconRes(), mode.getProfileColor(nightMode));
addProfileView(navigationType, onClickListener, i, icon, mode.toHumanString(), mode.equals(appMode)); addProfileView(navigationType, onClickListener, i, icon, mode.toHumanString(), mode.equals(appMode));
} }

View file

@ -102,9 +102,7 @@ public class MapStyleAction extends SwitchableAction<String> {
@Override @Override
public String getTranslatedItemName(Context context, String item) { public String getTranslatedItemName(Context context, String item) {
String translation = RendererRegistry.getTranslatedRendererName(context, item); return RendererRegistry.getRendererName(context, item);
return translation != null ? translation
: item.replace('_', ' ').replace('-', ' ');
} }
public List<String> getFilteredStyles() { public List<String> getFilteredStyles() {
@ -175,9 +173,8 @@ public class MapStyleAction extends SwitchableAction<String> {
List<String> visibleNamesList = new ArrayList<>(); List<String> visibleNamesList = new ArrayList<>();
final List<String> items = new ArrayList<>(renderers.keySet()); final List<String> items = new ArrayList<>(renderers.keySet());
for (String item : items) { for (String item : items) {
String translation = RendererRegistry.getTranslatedRendererName(activity, item); String name = RendererRegistry.getRendererName(activity, item);
visibleNamesList.add(translation != null ? translation visibleNamesList.add(name);
: item.replace('_', ' ').replace('-', ' '));
} }
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(themedContext, R.layout.dialog_text_item); final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(themedContext, R.layout.dialog_text_item);

View file

@ -289,6 +289,20 @@ public class RendererRegistry {
return renderers; 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 @Nullable
public static String getTranslatedRendererName(@NonNull Context ctx, @NonNull String key) { public static String getTranslatedRendererName(@NonNull Context ctx, @NonNull String key) {
switch (key) { switch (key) {

View file

@ -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;
}
}

View file

@ -55,6 +55,8 @@ public class TransportRoutingHelper {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(TransportRoutingHelper.class); private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(TransportRoutingHelper.class);
public static final String PUBLIC_TRANSPORT_KEY = "public_transport";
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>(); private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
private final OsmandApplication app; private final OsmandApplication app;

View file

@ -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<Integer> 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<AppearanceViewHolder> {
private List<ColorMode> 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);
}
}

View file

@ -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<AppearanceViewHolder> {
private final List<WidthMode> 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);
}
}
}

View file

@ -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.CONFIGURE_MAP_ITEM_ID_SCHEME;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_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.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_ACTIONS;
import static net.osmand.plus.routing.TransportRoutingHelper.PUBLIC_TRANSPORT_KEY;
public class OsmandSettings { public class OsmandSettings {
@ -998,7 +999,7 @@ public class OsmandSettings {
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.CAR, "car"); ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.CAR, "car");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.BICYCLE, "bicycle"); ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.BICYCLE, "bicycle");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.PEDESTRIAN, "pedestrian"); 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.BOAT, "boat");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.AIRCRAFT, "STRAIGHT_LINE_MODE"); ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.AIRCRAFT, "STRAIGHT_LINE_MODE");
ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.SKI, "ski"); ROUTING_PROFILE.setModeDefaultValue(ApplicationMode.SKI, "ski");
@ -2690,6 +2691,9 @@ public class OsmandSettings {
public final CommonPreference<Float> ROUTE_RECALCULATION_DISTANCE = new FloatPreference(this, "routing_recalc_distance", 0.f).makeProfile(); public final CommonPreference<Float> ROUTE_RECALCULATION_DISTANCE = new FloatPreference(this, "routing_recalc_distance", 0.f).makeProfile();
public final CommonPreference<Float> ROUTE_STRAIGHT_ANGLE = new FloatPreference(this, "routing_straight_angle", 30.f).makeProfile(); public final CommonPreference<Float> 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<Integer> ROUTE_LINE_COLOR = new IntPreference(this, "route_line_color", 0).makeProfile();
public final CommonPreference<String> ROUTE_LINE_WIDTH = new StringPreference(this, "route_line_width", null).makeProfile();
public final OsmandPreference<Boolean> USE_OSM_LIVE_FOR_ROUTING = new BooleanPreference(this, "enable_osmc_routing", true).makeProfile(); public final OsmandPreference<Boolean> USE_OSM_LIVE_FOR_ROUTING = new BooleanPreference(this, "enable_osmc_routing", true).makeProfile();

View file

@ -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); 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 @ColorRes
protected int getBackgroundColorRes() { protected int getBackgroundColorRes() {
return isNightMode() ? R.color.list_background_color_dark : R.color.list_background_color_light; return isNightMode() ? R.color.list_background_color_dark : R.color.list_background_color_light;

View file

@ -54,10 +54,13 @@ import net.osmand.plus.profiles.SelectProfileBottomSheet.DialogMode;
import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback; import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback;
import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteService; import net.osmand.plus.routing.RouteService;
import net.osmand.plus.settings.backend.ApplicationMode; 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.ProfileSettingsItem;
import net.osmand.plus.settings.backend.backup.SettingsHelper; 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.ColorsCard;
import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener; import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
import net.osmand.plus.widgets.FlowLayout; 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.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID;
import static net.osmand.plus.profiles.SelectProfileBottomSheet.PROFILES_LIST_UPDATED_ARG; 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.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); 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 LOCATION_ICON_ITEMS = "location_icon_items";
private static final String SELECT_NAV_ICON = "select_nav_icon"; private static final String SELECT_NAV_ICON = "select_nav_icon";
private static final String NAV_ICON_ITEMS = "nav_icon_items"; 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_NAME_KEY = "profile_name_key";
private static final String PROFILE_STRINGKEY_KEY = "profile_stringkey_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.routeService = profile.routeService;
changedProfile.locationIcon = profile.locationIcon; changedProfile.locationIcon = profile.locationIcon;
changedProfile.navigationIcon = profile.navigationIcon; changedProfile.navigationIcon = profile.navigationIcon;
changedProfile.routeLineDrawInfo = profile.routeLineDrawInfo;
isNewProfile = ApplicationMode.valueOfStringKey(changedProfile.stringKey, null) == null; isNewProfile = ApplicationMode.valueOfStringKey(changedProfile.stringKey, null) == null;
} }
requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@ -179,6 +185,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
profile.routeService = baseModeForNewProfile.getRouteService(); profile.routeService = baseModeForNewProfile.getRouteService();
profile.locationIcon = baseModeForNewProfile.getLocationIcon(); profile.locationIcon = baseModeForNewProfile.getLocationIcon();
profile.navigationIcon = baseModeForNewProfile.getNavigationIcon(); profile.navigationIcon = baseModeForNewProfile.getNavigationIcon();
profile.routeLineDrawInfo = createRouteLineDrawInfo(baseModeForNewProfile);
} }
@Override @Override
@ -239,6 +246,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
findPreference(SELECT_ICON).setVisible(false); findPreference(SELECT_ICON).setVisible(false);
findPreference(ICON_ITEMS).setVisible(false); findPreference(ICON_ITEMS).setVisible(false);
} }
updateRouteLinePreference();
} }
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
@ -318,6 +326,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
outState.putBoolean(IS_BASE_PROFILE_IMPORTED, isBaseProfileImported); outState.putBoolean(IS_BASE_PROFILE_IMPORTED, isBaseProfileImported);
outState.putSerializable(PROFILE_LOCATION_ICON_KEY, changedProfile.locationIcon); outState.putSerializable(PROFILE_LOCATION_ICON_KEY, changedProfile.locationIcon);
outState.putSerializable(PROFILE_NAVIGATION_ICON_KEY, changedProfile.navigationIcon); outState.putSerializable(PROFILE_NAVIGATION_ICON_KEY, changedProfile.navigationIcon);
changedProfile.routeLineDrawInfo.saveToBundle(outState);
} }
private void restoreState(Bundle savedInstanceState) { private void restoreState(Bundle savedInstanceState) {
@ -331,6 +340,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
isBaseProfileImported = savedInstanceState.getBoolean(IS_BASE_PROFILE_IMPORTED); isBaseProfileImported = savedInstanceState.getBoolean(IS_BASE_PROFILE_IMPORTED);
changedProfile.locationIcon = (LocationIcon) savedInstanceState.getSerializable(PROFILE_LOCATION_ICON_KEY); changedProfile.locationIcon = (LocationIcon) savedInstanceState.getSerializable(PROFILE_LOCATION_ICON_KEY);
changedProfile.navigationIcon = (NavigationIcon) savedInstanceState.getSerializable(PROFILE_NAVIGATION_ICON_KEY); changedProfile.navigationIcon = (NavigationIcon) savedInstanceState.getSerializable(PROFILE_NAVIGATION_ICON_KEY);
changedProfile.routeLineDrawInfo = new RouteLineDrawInfo(savedInstanceState);
isNewProfile = savedInstanceState.getBoolean(IS_NEW_PROFILE_KEY); isNewProfile = savedInstanceState.getBoolean(IS_NEW_PROFILE_KEY);
} }
@ -709,6 +719,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
changedProfile.routingProfile = changedProfile.parent.getRoutingProfile(); changedProfile.routingProfile = changedProfile.parent.getRoutingProfile();
changedProfile.routeService = changedProfile.parent.getRouteService(); changedProfile.routeService = changedProfile.parent.getRouteService();
this.isBaseProfileImported = isBaseProfileImported; this.isBaseProfileImported = isBaseProfileImported;
updateRouteLinePreference();
} }
private void setupBaseProfileView(String stringKey) { private void setupBaseProfileView(String stringKey) {
@ -716,6 +727,14 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
baseProfileName.setText(Algorithms.capitalizeFirstLetter(mode.toHumanString())); 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() { private boolean checkProfileName() {
if (Algorithms.isBlank(changedProfile.name)) { if (Algorithms.isBlank(changedProfile.name)) {
Activity activity = getActivity(); Activity activity = getActivity();
@ -756,6 +775,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
mode.setCustomIconColor(changedProfile.customColor); mode.setCustomIconColor(changedProfile.customColor);
mode.setLocationIcon(changedProfile.locationIcon); mode.setLocationIcon(changedProfile.locationIcon);
mode.setNavigationIcon(changedProfile.navigationIcon); mode.setNavigationIcon(changedProfile.navigationIcon);
saveRouteLineAppearance(mode, changedProfile.routeLineDrawInfo);
FragmentActivity activity = getActivity(); FragmentActivity activity = getActivity();
if (activity != null) { if (activity != null) {
@ -783,6 +803,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
if (!ApplicationMode.values(app).contains(mode)) { if (!ApplicationMode.values(app).contains(mode)) {
ApplicationMode.changeProfileAvailability(mode, true, app); ApplicationMode.changeProfileAvailability(mode, true, app);
} }
saveRouteLineAppearance(mode, changedProfile.routeLineDrawInfo);
return mode; 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 @Override
public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) { public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) {
} }
@ -977,6 +1013,29 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
this.onCardPressed(colorsCard); 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) { public static boolean showInstance(FragmentActivity activity, SettingsScreenType screenType, @Nullable String appMode, boolean imported) {
try { try {
Fragment fragment = Fragment.instantiate(activity, screenType.fragmentName); Fragment fragment = Fragment.instantiate(activity, screenType.fragmentName);
@ -1008,6 +1067,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
RouteService routeService; RouteService routeService;
NavigationIcon navigationIcon; NavigationIcon navigationIcon;
LocationIcon locationIcon; LocationIcon locationIcon;
RouteLineDrawInfo routeLineDrawInfo;
@ColorInt @ColorInt
public int getActualColor() { public int getActualColor() {
@ -1044,6 +1104,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
return false; return false;
if (routeService != that.routeService) return false; if (routeService != that.routeService) return false;
if (navigationIcon != that.navigationIcon) return false; if (navigationIcon != that.navigationIcon) return false;
if (routeLineDrawInfo != null ? !routeLineDrawInfo.equals(that.routeLineDrawInfo) : that.routeLineDrawInfo != null) return false;
return locationIcon == that.locationIcon; 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 + (routeService != null ? routeService.hashCode() : 0);
result = 31 * result + (navigationIcon != null ? navigationIcon.hashCode() : 0); result = 31 * result + (navigationIcon != null ? navigationIcon.hashCode() : 0);
result = 31 * result + (locationIcon != null ? locationIcon.hashCode() : 0); result = 31 * result + (locationIcon != null ? locationIcon.hashCode() : 0);
result = 31 * result + (routeLineDrawInfo != null ? routeLineDrawInfo.hashCode() : 0);
return result; return result;
} }
} }

View file

@ -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);
}
}

View file

@ -8,13 +8,13 @@ import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.R; import net.osmand.plus.R;
public class TrackAppearanceViewHolder extends RecyclerView.ViewHolder { public class AppearanceViewHolder extends RecyclerView.ViewHolder {
final TextView title; public final TextView title;
final ImageView icon; public final ImageView icon;
final ImageView button; public final ImageView button;
TrackAppearanceViewHolder(View itemView) { public AppearanceViewHolder(View itemView) {
super(itemView); super(itemView);
title = itemView.findViewById(R.id.groupName); title = itemView.findViewById(R.id.groupName);
icon = itemView.findViewById(R.id.groupIcon); icon = itemView.findViewById(R.id.groupIcon);

View file

@ -6,7 +6,6 @@ import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@ -28,12 +27,6 @@ import org.apache.commons.logging.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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 class ColorsCard extends BaseCard implements ColorPickerListener {
public static final int MAX_CUSTOM_COLORS = 6; public static final int MAX_CUSTOM_COLORS = 6;
@ -58,7 +51,12 @@ public class ColorsCard extends BaseCard implements ColorPickerListener {
return R.layout.colors_card; return R.layout.colors_card;
} }
public ColorsCard(MapActivity mapActivity, int selectedColor, Fragment targetFragment, List<Integer> colors, ListStringPreference colorsListPreference, ApplicationMode appMode) { public ColorsCard(MapActivity mapActivity,
int selectedColor,
Fragment targetFragment,
List<Integer> colors,
ListStringPreference colorsListPreference,
ApplicationMode appMode) {
super(mapActivity); super(mapActivity);
this.targetFragment = targetFragment; this.targetFragment = targetFragment;
this.selectedColor = selectedColor; this.selectedColor = selectedColor;

View file

@ -135,7 +135,7 @@ public class TrackColoringCard extends BaseCard {
updateHeader(); updateHeader();
} }
private class TrackColoringAdapter extends RecyclerView.Adapter<TrackAppearanceViewHolder> { private class TrackColoringAdapter extends RecyclerView.Adapter<AppearanceViewHolder> {
private List<TrackAppearanceItem> items; private List<TrackAppearanceItem> items;
@ -145,16 +145,16 @@ public class TrackColoringCard extends BaseCard {
@NonNull @NonNull
@Override @Override
public TrackAppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode); LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false); 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().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height); view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
return new TrackAppearanceViewHolder(view); return new AppearanceViewHolder(view);
} }
@Override @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); final TrackAppearanceItem item = items.get(position);
if (item.isActive() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 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); GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) { if (rectContourDrawable != null) {
Context ctx = holder.itemView.getContext(); 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(); Context ctx = holder.itemView.getContext();
boolean isSelected = item.getAttrName().equals(getSelectedAppearanceItem().getAttrName()); boolean isSelected = item.getAttrName().equals(getSelectedAppearanceItem().getAttrName());
int iconColorId; int iconColorId;

View file

@ -184,7 +184,7 @@ public class TrackWidthCard extends BaseCard {
} }
} }
private class GpxWidthAdapter extends RecyclerView.Adapter<TrackAppearanceViewHolder> { private class GpxWidthAdapter extends RecyclerView.Adapter<AppearanceViewHolder> {
private List<AppearanceListItem> items; private List<AppearanceListItem> items;
@ -194,13 +194,13 @@ public class TrackWidthCard extends BaseCard {
@NonNull @NonNull
@Override @Override
public TrackAppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public AppearanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode); LayoutInflater themedInflater = UiUtilities.getInflater(parent.getContext(), nightMode);
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false); 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().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height); 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) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp, AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
R.drawable.ripple_solid_dark_6dp); R.drawable.ripple_solid_dark_6dp);
@ -209,7 +209,7 @@ public class TrackWidthCard extends BaseCard {
} }
@Override @Override
public void onBindViewHolder(@NonNull final TrackAppearanceViewHolder holder, int position) { public void onBindViewHolder(@NonNull final AppearanceViewHolder holder, int position) {
AppearanceListItem item = items.get(position); AppearanceListItem item = items.get(position);
holder.title.setText(item.getLocalizedValue()); 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 color = trackDrawInfo.getColor();
int iconId; int iconId;
@ -251,7 +251,7 @@ public class TrackWidthCard extends BaseCard {
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(iconId, color)); 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); GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
if (rectContourDrawable != null) { if (rectContourDrawable != null) {
if (getSelectedItem() != null && getSelectedItem().equals(item)) { if (getSelectedItem() != null && getSelectedItem().equals(item)) {

View file

@ -377,6 +377,7 @@ public abstract class OsmandMapLayer {
public Paint paint; public Paint paint;
public Paint customColorPaint; public Paint customColorPaint;
public int customColor = 0; public int customColor = 0;
public float customWidth = 0;
public int defaultWidth = 0; public int defaultWidth = 0;
public int defaultColor = 0; public int defaultColor = 0;
public boolean isPaint2; public boolean isPaint2;
@ -481,8 +482,13 @@ public abstract class OsmandMapLayer {
if (isShadowPaint) { if (isShadowPaint) {
canvas.drawPath(path, shadowPaint); canvas.drawPath(path, shadowPaint);
} }
if (customColor != 0) { if (customColor != 0 || customWidth != 0) {
customColorPaint.setColor(customColor); if (customColor != 0) {
customColorPaint.setColor(customColor);
}
if (customWidth != 0) {
customColorPaint.setStrokeWidth(customWidth);
}
canvas.drawPath(path, customColorPaint); canvas.drawPath(path, customColorPaint);
} else { } else {
canvas.drawPath(path, paint); canvas.drawPath(path, paint);

View file

@ -872,14 +872,16 @@ public class MapControlsLayer extends OsmandMapLayer {
boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode) boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode)
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
&& !isInPlanRouteMode() && !shouldHideTopControls && !isInChoosingRoutesMode() && !isInPlanRouteMode() && !shouldHideTopControls && !isInChoosingRoutesMode()
&& !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode(); && !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode()
&& !isInRouteLineAppearanceMode();
routePlanningBtn.updateVisibility(showBottomMenuButtons); routePlanningBtn.updateVisibility(showBottomMenuButtons);
menuControl.updateVisibility(showBottomMenuButtons); menuControl.updateVisibility(showBottomMenuButtons);
boolean additionalDialogsHide = !isInGpxApproximationMode() boolean additionalDialogsHide = !isInGpxApproximationMode()
&& !isInTrackAppearanceMode() && !isInTrackAppearanceMode()
&& !isInChoosingRoutesMode() && !isInChoosingRoutesMode()
&& !isInWaypointsChoosingMode(); && !isInWaypointsChoosingMode()
&& !isInRouteLineAppearanceMode();
boolean showZoomButtons = !routeDialogOpened && !shouldHideTopControls boolean showZoomButtons = !routeDialogOpened && !shouldHideTopControls
&& !isInFollowTrackMode() && !isInFollowTrackMode()
&& (additionalDialogsHide || !portrait); && (additionalDialogsHide || !portrait);
@ -888,7 +890,8 @@ public class MapControlsLayer extends OsmandMapLayer {
boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode() boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode()
|| isInPlanRouteMode() || shouldHideTopControls || isInChoosingRoutesMode() || isInPlanRouteMode() || shouldHideTopControls || isInChoosingRoutesMode()
|| isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode(); || isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode()
|| isInRouteLineAppearanceMode();
compassHud.forceHideCompass = forceHideCompass; compassHud.forceHideCompass = forceHideCompass;
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass()); compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
@ -899,7 +902,8 @@ public class MapControlsLayer extends OsmandMapLayer {
} }
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls
&& !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode() && !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode()
&& !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode(); && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode()
&& !isInRouteLineAppearanceMode();
layersHud.updateVisibility(showTopButtons); layersHud.updateVisibility(showTopButtons);
quickSearchHud.updateVisibility(showTopButtons); quickSearchHud.updateVisibility(showTopButtons);
@ -1029,7 +1033,8 @@ public class MapControlsLayer extends OsmandMapLayer {
&& !isInGpxApproximationMode() && !isInGpxApproximationMode()
&& !isInChoosingRoutesMode() && !isInChoosingRoutesMode()
&& !isInWaypointsChoosingMode() && !isInWaypointsChoosingMode()
&& !isInFollowTrackMode(); && !isInFollowTrackMode()
&& !isInRouteLineAppearanceMode();
backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode() backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode()
&& (additionalDialogsHide || !isPotrait())); && (additionalDialogsHide || !isPotrait()));
} }
@ -1397,6 +1402,10 @@ public class MapControlsLayer extends OsmandMapLayer {
return MapRouteInfoMenu.waypointsVisible; return MapRouteInfoMenu.waypointsVisible;
} }
private boolean isInRouteLineAppearanceMode() {
return mapActivity.getMapLayers().getRouteLayer().isInRouteLineAppearanceMode();
}
private boolean isInFollowTrackMode() { private boolean isInFollowTrackMode() {
return MapRouteInfoMenu.followTrackVisible; return MapRouteInfoMenu.followTrackVisible;
} }

View file

@ -61,6 +61,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
private final MapMarkersLayer mapMarkersLayer; private final MapMarkersLayer mapMarkersLayer;
private final MapControlsLayer mapControlsLayer; private final MapControlsLayer mapControlsLayer;
private final GPXLayer gpxLayer; private final GPXLayer gpxLayer;
private final RouteLayer routeLayer;
private ImageView contextMarker; private ImageView contextMarker;
private final MapActivity mapActivity; private final MapActivity mapActivity;
private final OsmandApplication app; private final OsmandApplication app;
@ -90,6 +91,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
mapMarkersLayer = mapActivity.getMapLayers().getMapMarkersLayer(); mapMarkersLayer = mapActivity.getMapLayers().getMapMarkersLayer();
gpxLayer = mapActivity.getMapLayers().getGpxLayer(); gpxLayer = mapActivity.getMapLayers().getGpxLayer();
mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer(); mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer();
routeLayer = mapActivity.getMapLayers().getRouteLayer();
} }
@Override @Override
@ -426,6 +428,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
mapMarkersLayer.isInPlanRouteMode() || mapMarkersLayer.isInPlanRouteMode() ||
gpxLayer.isInTrackAppearanceMode() || gpxLayer.isInTrackAppearanceMode() ||
mapControlsLayer.isInTrackMenuMode() || mapControlsLayer.isInTrackMenuMode() ||
routeLayer.isInRouteLineAppearanceMode() ||
mapRouteInfoMenu.isVisible() || mapRouteInfoMenu.isVisible() ||
MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.chooseRoutesVisible ||
MapRouteInfoMenu.waypointsVisible || MapRouteInfoMenu.waypointsVisible ||

View file

@ -11,17 +11,21 @@ import android.graphics.Path;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.graphics.drawable.DrawableCompat;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.data.QuadPoint;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.data.TransportStop; 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.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.measurementtool.MeasurementToolFragment; import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.profiles.LocationIcon; 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.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RouteLineDrawInfo;
import net.osmand.plus.routing.RouteService; import net.osmand.plus.routing.RouteService;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper;
@ -41,16 +48,29 @@ import net.osmand.plus.views.layers.geometry.PublicTransportGeometryWay;
import net.osmand.plus.views.layers.geometry.PublicTransportGeometryWayContext; import net.osmand.plus.views.layers.geometry.PublicTransportGeometryWayContext;
import net.osmand.plus.views.layers.geometry.RouteGeometryWay; import net.osmand.plus.views.layers.geometry.RouteGeometryWay;
import net.osmand.plus.views.layers.geometry.RouteGeometryWayContext; 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.router.TransportRouteResult;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; 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 { 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 OsmandMapTileView view;
private final RoutingHelper helper; private final RoutingHelper helper;
@ -64,13 +84,16 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
private Paint paintIconAction; private Paint paintIconAction;
private Paint paintGridOuterCircle; private Paint paintGridOuterCircle;
private Paint paintGridCircle; private Paint paintGridCircle;
private Paint paintRouteLinePreview;
private LayerDrawable selectedPoint; private LayerDrawable selectedPoint;
private TrackChartPoints trackChartPoints; private TrackChartPoints trackChartPoints;
private RouteLineDrawInfo routeLineDrawInfo;
private RenderingLineAttributes attrs; private RenderingLineAttributes attrs;
private RenderingLineAttributes attrsPT; private RenderingLineAttributes attrsPT;
private RenderingLineAttributes attrsW; private RenderingLineAttributes attrsW;
private Map<String, Float> cachedRouteLineWidth = new HashMap<>();
private boolean nightMode; private boolean nightMode;
private RouteGeometryWayContext routeWayContext; private RouteGeometryWayContext routeWayContext;
@ -79,6 +102,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
private PublicTransportGeometryWay publicTransportRouteGeometry; private PublicTransportGeometryWay publicTransportRouteGeometry;
private LayerDrawable projectionIcon; private LayerDrawable projectionIcon;
private LayerDrawable previewIcon;
public RouteLayer(RoutingHelper helper) { public RouteLayer(RoutingHelper helper) {
this.helper = helper; this.helper = helper;
@ -149,6 +173,8 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
paintGridOuterCircle.setAntiAlias(true); paintGridOuterCircle.setAntiAlias(true);
paintGridOuterCircle.setColor(Color.WHITE); paintGridOuterCircle.setColor(Color.WHITE);
paintGridOuterCircle.setAlpha(204); paintGridOuterCircle.setAlpha(204);
paintRouteLinePreview = new Paint();
} }
@Override @Override
@ -206,8 +232,8 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
} }
private boolean isPlanRouteGraphsAvailable() { private boolean isPlanRouteGraphsAvailable() {
if (view.getContext() instanceof MapActivity) { MapActivity mapActivity = getMapActivity();
MapActivity mapActivity = (MapActivity) view.getContext(); if (mapActivity != null) {
MeasurementToolFragment fragment = mapActivity.getMeasurementToolFragment(); MeasurementToolFragment fragment = mapActivity.getMeasurementToolFragment();
if (fragment != null) { if (fragment != null) {
return fragment.hasVisibleGraph(); return fragment.hasVisibleGraph();
@ -216,6 +242,24 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
return false; 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) { private void updateAttrs(DrawSettings settings, RotatedTileBox tileBox) {
boolean updatePaints = attrs.updatePaints(view.getApplication(), settings, tileBox); boolean updatePaints = attrs.updatePaints(view.getApplication(), settings, tileBox);
attrs.isPaint3 = false; attrs.isPaint3 = false;
@ -265,7 +309,37 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
} }
@Override @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<Location> actionPoints) { private void drawAction(RotatedTileBox tb, Canvas canvas, List<Location> actionPoints) {
if (actionPoints.size() > 0) { if (actionPoints.size() > 0) {
@ -328,19 +402,76 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
} }
int locationX = (int) projectionXY[0]; int locationX = (int) projectionXY[0];
int locationY = (int) projectionXY[1]; int locationY = (int) projectionXY[1];
drawIcon(canvas, projectionIcon, locationX, locationY);
}
projectionIcon.setBounds(locationX - projectionIcon.getIntrinsicWidth() / 2, private static void drawIcon(Canvas canvas, Drawable drawable, int locationX, int locationY) {
locationY - projectionIcon.getIntrinsicHeight() / 2, drawable.setBounds(locationX - drawable.getIntrinsicWidth() / 2,
locationX + projectionIcon.getIntrinsicWidth() / 2, locationY - drawable.getIntrinsicHeight() / 2,
locationY + projectionIcon.getIntrinsicHeight() / 2); locationX + drawable.getIntrinsicWidth() / 2,
projectionIcon.draw(canvas); locationY + drawable.getIntrinsicHeight() / 2);
drawable.draw(canvas);
} }
@ColorInt @ColorInt
public int getRouteLineColor(boolean night) { public int getRouteLineColor(boolean night) {
updateAttrs(new DrawSettings(night), view.getCurrentRotatedTileBox()); Integer color;
return attrs.paint.getColor(); 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) { public void drawLocations(RotatedTileBox tb, Canvas canvas, double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) {
@ -364,6 +495,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
boolean straight = route.getRouteService() == RouteService.STRAIGHT; boolean straight = route.getRouteService() == RouteService.STRAIGHT;
publicTransportRouteGeometry.clearRoute(); publicTransportRouteGeometry.clearRoute();
routeGeometry.updateRoute(tb, route); routeGeometry.updateRoute(tb, route);
routeGeometry.setRouteStyleParams(getRouteLineColor(nightMode), getRouteLineWidth(tb));
if (directTo) { if (directTo) {
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude, routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
null, 0); null, 0);
@ -636,12 +768,12 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
@Override @Override
public boolean disableSingleTap() { public boolean disableSingleTap() {
return false; return isInRouteLineAppearanceMode();
} }
@Override @Override
public boolean disableLongPressOnMap() { public boolean disableLongPressOnMap() {
return false; return isInRouteLineAppearanceMode();
} }
@Override @Override

View file

@ -95,6 +95,7 @@ public class GeometryWayDrawer<T extends GeometryWayContext> {
public void drawPath(Canvas canvas, Path path, GeometryWayStyle<?> style) { public void drawPath(Canvas canvas, Path path, GeometryWayStyle<?> style) {
context.getAttrs().customColor = style.getColor(); context.getAttrs().customColor = style.getColor();
context.getAttrs().customWidth = style.getWidth();
context.getAttrs().drawPath(canvas, path); context.getAttrs().drawPath(canvas, path);
} }

View file

@ -7,6 +7,7 @@ public abstract class GeometryWayStyle<T extends GeometryWayContext> {
private T context; private T context;
protected Integer color; protected Integer color;
protected Float width;
public GeometryWayStyle(T context) { public GeometryWayStyle(T context) {
this.context = context; this.context = context;
@ -17,6 +18,12 @@ public abstract class GeometryWayStyle<T extends GeometryWayContext> {
this.color = color; this.color = color;
} }
public GeometryWayStyle(T context, Integer color, Float width) {
this.context = context;
this.color = color;
this.width = width;
}
public T getContext() { public T getContext() {
return context; return context;
} }
@ -29,6 +36,10 @@ public abstract class GeometryWayStyle<T extends GeometryWayContext> {
return color; return color;
} }
public Float getWidth() {
return width;
}
public Integer getStrokeColor() { public Integer getStrokeColor() {
return context.getStrokeColor(color); return context.getStrokeColor(color);
} }

View file

@ -1,8 +1,11 @@
package net.osmand.plus.views.layers.geometry; package net.osmand.plus.views.layers.geometry;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Paint;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
@ -17,15 +20,26 @@ public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, Geome
private RoutingHelper helper; private RoutingHelper helper;
private RouteCalculationResult route; private RouteCalculationResult route;
private Integer customColor;
private Float customWidth;
public RouteGeometryWay(RouteGeometryWayContext context) { public RouteGeometryWay(RouteGeometryWayContext context) {
super(context, new GeometryWayDrawer<>(context)); super(context, new GeometryWayDrawer<>(context));
this.helper = context.getApp().getRoutingHelper(); this.helper = context.getApp().getRoutingHelper();
} }
public void setRouteStyleParams(@Nullable @ColorInt Integer color, @Nullable Float width) {
this.customColor = color;
this.customWidth = width;
}
@NonNull @NonNull
@Override @Override
public GeometryWayStyle<RouteGeometryWayContext> getDefaultWayStyle() { public GeometryWayStyle<RouteGeometryWayContext> 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) { public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) {
@ -50,8 +64,8 @@ public class RouteGeometryWay extends GeometryWay<RouteGeometryWayContext, Geome
private static class GeometrySolidWayStyle extends GeometryWayStyle<RouteGeometryWayContext> { private static class GeometrySolidWayStyle extends GeometryWayStyle<RouteGeometryWayContext> {
GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color) { GeometrySolidWayStyle(RouteGeometryWayContext context, Integer color, Float width) {
super(context, color); super(context, color, width);
} }
@Override @Override

View file

@ -1207,6 +1207,7 @@ public class MapInfoWidgetsFactory {
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && !map.shouldHideTopControls() boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && !map.shouldHideTopControls()
&& map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive() && map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive()
&& !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode() && !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
&& !map.getMapLayers().getRouteLayer().isInRouteLineAppearanceMode()
&& !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible
&& !MapRouteInfoMenu.followTrackVisible; && !MapRouteInfoMenu.followTrackVisible;

View file

@ -191,7 +191,8 @@ public class MapMarkersWidgetsFactory {
|| map.isTopToolbarActive() || map.isTopToolbarActive()
|| map.shouldHideTopControls() || map.shouldHideTopControls()
|| map.getMapLayers().getGpxLayer().isInTrackAppearanceMode() || map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|| map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()) { || map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()
|| map.getMapLayers().getRouteLayer().isInRouteLineAppearanceMode()) {
updateVisibility(false); updateVisibility(false);
return; return;
} }