Merge branch 'master' into points_menu_gpx

This commit is contained in:
Vitaliy 2021-01-25 09:13:30 +02:00
commit 32b4d32376
35 changed files with 1804 additions and 315 deletions

View file

@ -449,6 +449,10 @@ public class GPXUtilities {
public String getArticleLang() {
return getExtensionsToRead().get("article_lang");
}
public String getDescription() {
return getExtensionsToRead().get("desc");
}
}
public static class Author extends GPXExtensions {

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="?attr/switch_button_active" />
</shape>

View file

@ -1,19 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/background">
<shape android:shape="rectangle" >
<solid
android:color="#4d007eb3" />
<corners android:radius="30dp" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape android:shape="rectangle" >
<solid
android:color="@color/profile_icon_color_blue_light" />
<corners android:radius="30dp" />
</shape>
</clip>
</item>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/background">
<shape android:shape="rectangle">
<solid android:color="#4d007eb3" />
<corners android:radius="30dp" />
</shape>
</item>
<item android:id="@+id/progress">
<shape android:shape="rectangle">
<solid android:color="@color/color_white" />
<corners android:radius="30dp" />
</shape>
</item>
</layer-list>

View file

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<item>
<shape android:shape="oval">
<size
android:height="12dp"
android:width="12dp" />
<solid android:color="@color/profile_icon_color_blue_light" />
</shape>
</item>
android:layout_width="match_parent"
android:layout_height="match_parent">
<item android:id="@+id/thump">
<shape android:shape="oval">
<size
android:width="12dp"
android:height="12dp" />
<solid android:color="@color/profile_icon_color_blue_light" />
</shape>
</item>
</layer-list>

View file

@ -27,6 +27,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:lineSpacingMultiplier="1.1"
@ -70,8 +71,6 @@
android:maxHeight="2dp"
android:paddingTop="11dp"
android:paddingBottom="11dp"
android:progressDrawable="@drawable/seekbar_progress_announcement_time"
android:thumb="@drawable/seekbar_thumb_announcement_time"
osmand:tickMark="@drawable/seekbar_tickmark_announcement_time"
tools:max="3"
tools:progress="1" />

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?attr/card_and_list_background_basic"
xmlns:tools="http://schemas.android.com/tools"
xmlns:osmand="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/action_bar_height"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/card_padding"
android:layout_marginLeft="@dimen/card_padding"
android:padding="@dimen/context_menu_padding_margin_small"
android:paddingStart="@dimen/context_menu_padding_margin_small"
android:paddingEnd="@dimen/context_menu_padding_margin_small">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="@dimen/favorites_icon_size_small"
android:layout_height="@dimen/favorites_icon_size_small"
android:tint="?attr/default_icon_color"
osmand:srcCompat="@drawable/ic_action_close" />
</FrameLayout>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/card_content_padding_large"
android:layout_marginStart="@dimen/card_content_padding_large"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:text="@string/context_menu_edit_descr"
android:textColor="?attr/searchbar_text"
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/content_padding_half"
android:layout_marginEnd="@dimen/content_padding_half"
android:layout_gravity="center_vertical"
android:background="@drawable/btn_border_active"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_half"
android:text="@string/shared_string_save"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color" />
<net.osmand.plus.widgets.EditTextEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:background="?attr/card_and_list_background_basic"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife." />
</LinearLayout>

View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?attr/list_background_color">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/pstsTabBackground">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/action_bar_height"
app:titleTextColor="?attr/list_background_color" />
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?attr/list_background_color">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/main_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:adjustViewBounds="true"
tools:visibility="visible"
tools:src="@drawable/img_help_announcement_time_day"/>
<net.osmand.plus.widgets.WebViewEx
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:background="@color/color_transparent" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color"
android:visibility="gone"
tools:visibility="visible"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginBottom="@dimen/context_menu_padding_margin_small"
android:gravity="center_vertical"
android:padding="@dimen/context_menu_padding_margin_small"
android:paddingStart="@dimen/context_menu_padding_margin_small"
android:paddingEnd="@dimen/context_menu_padding_margin_small"
android:drawablePadding="@dimen/list_content_padding_large"
osmand:drawableLeftCompat="@drawable/ic_action_edit_dark"
osmand:drawableStartCompat="@drawable/ic_action_edit_dark"
osmand:drawableTint="?attr/active_color_basic"
android:visibility="gone"
android:text="@string/shared_string_edit"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:visibility="visible" />
<FrameLayout
android:id="@+id/bottom_empty_space"
android:layout_width="match_parent"
android:layout_height="@dimen/card_row_min_height"
android:foreground="@drawable/bg_contextmenu_shadow"
android:foregroundGravity="top|fill_horizontal"
android:visibility="gone"
tools:visibility="visible">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/activity_background_basic" />
</FrameLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

View file

@ -0,0 +1,121 @@
<?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="match_parent"
android:orientation="vertical"
android:background="?attr/list_background_color">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/activity_background_basic">
<include layout="@layout/list_item_divider" />
</FrameLayout>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:text="@string/shared_string_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/main_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/content_padding_small"
android:visibility="gone"
android:adjustViewBounds="true"
tools:visibility="visible"
tools:src="@drawable/img_help_announcement_time_day"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:lineSpacingMultiplier="1.1"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife."/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginBottom="@dimen/context_menu_padding_margin_small"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_read_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/context_menu_padding_margin_small"
android:layout_marginLeft="@dimen/context_menu_padding_margin_small"
android:layout_gravity="start"
android:gravity="center_vertical"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingLeft="@dimen/bottom_sheet_content_padding_small"
android:paddingTop="@dimen/bottom_sheet_content_padding_small"
android:paddingRight="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableStartCompat="@drawable/ic_action_read_article"
osmand:drawableLeftCompat="@drawable/ic_action_read_article"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/context_menu_read_full"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/context_menu_padding_margin_small"
android:layout_marginEnd="@dimen/context_menu_padding_margin_small"
android:layout_gravity="end"
android:gravity="center_vertical"
android:padding="@dimen/bottom_sheet_content_padding_small"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableRightCompat="@drawable/ic_action_edit_dark"
osmand:drawableEndCompat="@drawable/ic_action_edit_dark"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/shared_string_edit"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/activity_background_basic">
<include
android:id="@+id/shadow"
layout="@layout/card_bottom_divider" />
</FrameLayout>
</LinearLayout>

View file

@ -0,0 +1,104 @@
<?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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_overview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding_small_half"
android:clipToPadding="false"
android:orientation="horizontal"
tools:itemCount="4"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_gpx_stat_block" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="@dimen/dash_margin"
android:paddingBottom="@dimen/dash_margin">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/direction"
android:layout_width="@dimen/context_menu_transport_icon_size"
android:layout_height="@dimen/context_menu_transport_icon_size"
osmand:srcCompat="@drawable/ic_direction_arrow" />
<TextView
android:id="@+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding_small_half"
android:layout_marginLeft="@dimen/content_padding_small_half"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="300 km" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding"
android:orientation="horizontal"
android:weightSum="4">
<!-- todo stretch buttons correctly -->
<include
android:id="@+id/show_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Space
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
android:id="@+id/appearance_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Space
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
android:id="@+id/edit_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Space
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
android:id="@+id/directions_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/filled"
android:layout_width="@dimen/fab_recycler_view_padding_bottom"
android:layout_height="@dimen/setting_list_item_small_height"
tools:alpha="0.1"
tools:srcCompat="@drawable/bg_topbar_shield_exit_ref" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center"
tools:srcCompat="@drawable/ic_action_hide" />
</FrameLayout>

View file

@ -0,0 +1,44 @@
<?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="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="700 km" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="@dimen/context_menu_transport_icon_size"
android:layout_height="@dimen/context_menu_transport_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/context_menu_first_line_top_margin"
android:layout_marginLeft="@dimen/context_menu_first_line_top_margin"
tools:src="@drawable/ic_action_track_16" />
</LinearLayout>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="@string/distance" />
</LinearLayout>

View file

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/list_background_color"
android:orientation="vertical">
android:background="?attr/list_background_color">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
@ -15,21 +14,41 @@
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:id="@+id/segments_scroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
android:layout_height="match_parent"
android:layout_marginBottom="@dimen/dialog_button_ex_height">
<LinearLayout
android:id="@+id/segments_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
android:orientation="vertical"
android:paddingTop="@dimen/dialog_button_ex_height"
android:paddingBottom="@dimen/context_menu_buttons_bottom_height" />
</ScrollView>
<include
layout="@layout/bottom_buttons"
<LinearLayout
android:id="@+id/control_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_ex_height" />
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical">
</LinearLayout>
<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

@ -164,36 +164,4 @@
tools:visibility="visible"
android:visibility="gone" />
<LinearLayout
android:id="@+id/result_container"
android:layout_width="match_parent"
android:layout_height="@dimen/setting_list_item_group_height"
android:orientation="horizontal"
tools:visibility="visible"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/result_icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:tint="?attr/default_icon_color"
tools:src="@drawable/ic_action_gdirections_dark" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/result_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:letterSpacing="@dimen/description_letter_spacing"
android:singleLine="true"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="OK" />
</LinearLayout>
</LinearLayout>

View file

@ -43,12 +43,13 @@
android:paddingStart="@dimen/context_menu_padding_margin_default"
android:paddingLeft="@dimen/context_menu_padding_margin_default"
android:paddingEnd="@dimen/context_menu_padding_margin_default"
android:paddingRight="@dimen/context_menu_padding_margin_default">
android:paddingRight="@dimen/context_menu_padding_margin_default"
android:paddingBottom="@dimen/context_menu_direction_margin">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_first_line_top_margin"
android:layout_marginTop="@dimen/context_menu_second_line_top_margin"
android:layout_marginEnd="@dimen/context_menu_padding_margin_default"
android:layout_marginRight="@dimen/context_menu_padding_margin_default"
android:layout_weight="1"
@ -71,7 +72,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
tools:text="@string/amenity_type_finance" />
android:visibility="gone"
tools:text="@string/amenity_type_finance" />
</LinearLayout>
@ -79,7 +81,7 @@
android:id="@+id/icon_view"
android:layout_width="@dimen/map_widget_icon"
android:layout_height="@dimen/map_widget_icon"
android:layout_marginTop="@dimen/context_menu_padding_margin_default"
android:layout_marginTop="@dimen/context_menu_second_line_top_margin"
android:tint="?attr/default_icon_color"
osmand:srcCompat="@drawable/ic_action_polygom_dark" />

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_edit"
android:icon="@drawable/ic_action_edit_dark"
osmand:showAsAction="always"
android:title="@string/shared_string_edit"/>
</menu>

View file

@ -1,14 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <item-->
<!-- android:id="@+id/action_overview"-->
<!-- android:icon="@drawable/ic_action_trail_overview"-->
<!-- android:title="@string/shared_string_overview" />-->
<item
android:id="@+id/action_overview"
android:icon="@drawable/ic_action_trail_overview"
android:title="@string/shared_string_overview" />
<item
android:id="@+id/action_track"
android:icon="@drawable/ic_action_polygom_dark"
android:title="@string/shared_string_gpx_track" />
<item
android:id="@+id/action_points"
android:icon="@drawable/ic_action_waypoint"

View file

@ -141,6 +141,7 @@
<attr name="bg_dash_line" format="reference"/>
<attr name="text_input_background" format="reference"/>
<attr name="image_help_announcement_time" format="reference"/>
<attr name="switch_button_active" format="reference" />
</declare-styleable>
<declare-styleable name="PagerSlidingTabStrip">

View file

@ -274,6 +274,7 @@
<color name="gpx_chart_green_label">#197d2a</color>
<color name="gpx_split_segment_icon_color">#b3b3b3</color>
<color name="gpx_pale_green">#87CC70</color>
<color name="map_background_color_light">#fafafa</color>
<color name="map_background_color_dark">#101821</color>

View file

@ -12,6 +12,9 @@
-->
<string name="context_menu_edit_descr">Edit description</string>
<string name="context_menu_read_full">Read full</string>
<string name="delete_online_routing_engine">Delete this online routing engine?</string>
<string name="message_name_is_already_exists">The name is already exists</string>
<string name="message_server_error">Server error: %1$s</string>
<string name="routing_engine_vehicle_type_mtb">MTB</string>

View file

@ -248,6 +248,7 @@
<item name="radioButtonStyle">@style/RadioButtonStyle</item>
<item name="text_input_background">@color/text_input_background_light</item>
<item name="image_help_announcement_time">@drawable/img_help_announcement_time_day</item>
<item name="switch_button_active">@color/switch_button_active_light</item>
</style>
<style name="ToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
@ -545,6 +546,7 @@
<item name="radioButtonStyle">@style/RadioButtonStyle</item>
<item name="text_input_background">@color/text_input_background_dark</item>
<item name="image_help_announcement_time">@drawable/img_help_announcement_time_night</item>
<item name="switch_button_active">@color/switch_button_active_dark</item>
</style>
<style name="FreeVersionBanner" parent="OsmandDarkTheme">

View file

@ -89,7 +89,7 @@
<net.osmand.plus.settings.preferences.ListPreferenceEx
android:key="arrival_distance_factor"
android:layout="@layout/preference_with_descr"
android:title="@string/arrival_distance" />
android:title="@string/announcement_time_title" />
<Preference
android:layout="@layout/simple_divider_item"

View file

@ -38,6 +38,7 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.LineGraphType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.track.TrackDisplayHelper;
@ -687,8 +688,50 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
}
void openAnalyzeOnMap(GPXTabItemType tabType) {
List<ILineDataSet> ds = getDataSets(null, tabType, null, null);
actionsListener.openAnalyzeOnMap(gpxItem, ds, tabType);
List<ILineDataSet> dataSets = getDataSets(null, tabType, null, null);
prepareGpxItemChartTypes(gpxItem, dataSets);
actionsListener.openAnalyzeOnMap(gpxItem);
}
public static void prepareGpxItemChartTypes(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets) {
WptPt wpt = null;
gpxItem.chartTypes = null;
if (dataSets != null && dataSets.size() > 0) {
gpxItem.chartTypes = new GPXDataSetType[dataSets.size()];
for (int i = 0; i < dataSets.size(); i++) {
OrderedLineDataSet orderedDataSet = (OrderedLineDataSet) dataSets.get(i);
gpxItem.chartTypes[i] = orderedDataSet.getDataSetType();
}
if (gpxItem.chartHighlightPos != -1) {
TrkSegment segment = null;
for (Track t : gpxItem.group.getGpx().tracks) {
for (TrkSegment s : t.segments) {
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
segment = s;
break;
}
}
if (segment != null) {
break;
}
}
if (segment != null) {
OrderedLineDataSet dataSet = (OrderedLineDataSet) dataSets.get(0);
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
for (WptPt p : segment.points) {
if (p.distance >= distance) {
wpt = p;
break;
}
}
}
}
}
if (wpt != null) {
gpxItem.locationOnMap = wpt;
} else {
gpxItem.locationOnMap = gpxItem.locationStart;
}
}
private void openSplitIntervalScreen() {

View file

@ -2,13 +2,9 @@ package net.osmand.plus.myplaces;
import android.view.View;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import java.util.List;
public interface SegmentActionsListener {
void updateContent();
@ -23,5 +19,5 @@ public interface SegmentActionsListener {
void showOptionsPopupMenu(View view, TrkSegment trkSegment, boolean confirmDeletion);
void openAnalyzeOnMap(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets, GPXTabItemType tabType);
void openAnalyzeOnMap(GpxDisplayItem gpxItem);
}

View file

@ -34,7 +34,6 @@ import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Metadata;
import net.osmand.GPXUtilities.WptPt;
@ -409,7 +408,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
}
@Nullable
private String getMetadataImageLink(@NonNull Metadata metadata) {
public static String getMetadataImageLink(@NonNull Metadata metadata) {
String link = metadata.link;
if (!TextUtils.isEmpty(link)) {
String lowerCaseLink = link.toLowerCase();

View file

@ -22,16 +22,11 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.FileUtils.RenameCallback;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Track;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
@ -43,8 +38,6 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.base.OsmAndListFragment;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.SaveGpxAsyncTask;
@ -299,55 +292,9 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
}
@Override
public void openAnalyzeOnMap(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets, GPXTabItemType tabType) {
LatLon location = null;
WptPt wpt = null;
gpxItem.chartTypes = null;
if (dataSets != null && dataSets.size() > 0) {
gpxItem.chartTypes = new GPXDataSetType[dataSets.size()];
for (int i = 0; i < dataSets.size(); i++) {
OrderedLineDataSet orderedDataSet = (OrderedLineDataSet) dataSets.get(i);
gpxItem.chartTypes[i] = orderedDataSet.getDataSetType();
}
if (gpxItem.chartHighlightPos != -1) {
TrkSegment segment = null;
for (Track t : gpxItem.group.getGpx().tracks) {
for (TrkSegment s : t.segments) {
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
segment = s;
break;
}
}
if (segment != null) {
break;
}
}
if (segment != null) {
OrderedLineDataSet dataSet = (OrderedLineDataSet) dataSets.get(0);
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
for (WptPt p : segment.points) {
if (p.distance >= distance) {
wpt = p;
break;
}
}
if (wpt != null) {
location = new LatLon(wpt.lat, wpt.lon);
}
}
}
}
if (location == null) {
location = new LatLon(gpxItem.locationStart.lat, gpxItem.locationStart.lon);
}
if (wpt != null) {
gpxItem.locationOnMap = wpt;
} else {
gpxItem.locationOnMap = gpxItem.locationStart;
}
public void openAnalyzeOnMap(GpxDisplayItem gpxItem) {
OsmandSettings settings = app.getSettings();
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
settings.setMapLocationToShow(gpxItem.locationOnMap.lat, gpxItem.locationOnMap.lon,
settings.getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_WPT, gpxItem.name),
false,

View file

@ -25,8 +25,6 @@ import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
@ -123,8 +121,8 @@ public class OnlineRoutingCard extends BaseCard {
}
public void setSelectionMenu(@NonNull List<HorizontalSelectionItem> items,
@NonNull String selectedItemTitle,
@NonNull final CallbackWithObject<HorizontalSelectionItem> callback) {
@NonNull String selectedItemTitle,
@NonNull final CallbackWithObject<HorizontalSelectionItem> callback) {
showElements(rvSelectionMenu);
rvSelectionMenu.setLayoutManager(
new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
@ -137,23 +135,15 @@ public class OnlineRoutingCard extends BaseCard {
if (callback.processResult(item)) {
adapter.setSelectedItem(item);
}
Object obj = item.getObject();
updateBottomMarginSelectionMenu(obj);
}
});
Object item = adapter.getItemByTitle(selectedItemTitle).getObject();
updateBottomMarginSelectionMenu(item);
rvSelectionMenu.setAdapter(adapter);
}
private void updateBottomMarginSelectionMenu(Object item) {
if (item instanceof VehicleType) {
VehicleType vt = (VehicleType) item;
boolean hasPadding = vt.equals(OnlineRoutingEngine.CUSTOM_VEHICLE);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) rvSelectionMenu.getLayoutParams();
int contentPadding = app.getResources().getDimensionPixelSize(R.dimen.content_padding);
params.bottomMargin = hasPadding ? contentPadding : 0;
}
private void updateBottomMarginSelectionMenu() {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) rvSelectionMenu.getLayoutParams();
int contentPadding = app.getResources().getDimensionPixelSize(R.dimen.content_padding);
params.bottomMargin = isVisibleViewsBelowSelectionMenu() ? contentPadding : 0;
}
public void setDescription(@NonNull String description) {
@ -166,6 +156,10 @@ public class OnlineRoutingCard extends BaseCard {
textFieldBoxes.setLabelText(labelText);
}
public void hideFieldBoxLabel() {
textFieldBoxes.makeCompactPadding();
}
public void setFieldBoxHelperText(@NonNull String helperText) {
showElements(fieldBoxContainer, tvHelperText);
fieldBoxHelperTextShowed = true;
@ -202,7 +196,7 @@ public class OnlineRoutingCard extends BaseCard {
}
public void setButton(@NonNull String title,
@NonNull OnClickListener listener) {
@NonNull OnClickListener listener) {
showElements(button);
button.setOnClickListener(listener);
UiUtilities.setupDialogButton(nightMode, button, DialogButtonType.PRIMARY, title);
@ -226,10 +220,20 @@ public class OnlineRoutingCard extends BaseCard {
private void showElements(View... views) {
AndroidUiHelper.setVisibility(View.VISIBLE, views);
updateBottomMarginSelectionMenu();
}
private void hideElements(View... views) {
AndroidUiHelper.setVisibility(View.GONE, views);
updateBottomMarginSelectionMenu();
}
private boolean isVisibleViewsBelowSelectionMenu() {
return isVisible(tvDescription) || isVisible(fieldBoxContainer) || isVisible(button);
}
public boolean isVisible(View view) {
return view.getVisibility() == View.VISIBLE;
}
public void setOnTextChangedListener(@Nullable OnTextChangedListener onTextChangedListener) {

View file

@ -12,8 +12,8 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ScrollView;
@ -23,6 +23,7 @@ import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
@ -42,9 +43,9 @@ import net.osmand.plus.onlinerouting.OnlineRoutingFactory;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.onlinerouting.OnlineRoutingUtils;
import net.osmand.plus.onlinerouting.VehicleType;
import net.osmand.plus.onlinerouting.ui.OnlineRoutingCard.OnTextChangedListener;
import net.osmand.plus.onlinerouting.engine.EngineType;
import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine;
import net.osmand.plus.onlinerouting.ui.OnlineRoutingCard.OnTextChangedListener;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.util.Algorithms;
@ -82,7 +83,9 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
private View testResultsContainer;
private View saveButton;
private ScrollView scrollView;
private AppCompatImageView buttonsShadow;
private OnGlobalLayoutListener onGlobalLayout;
private OnScrollChangedListener onScroll;
private boolean isKeyboardShown = false;
private OnlineRoutingEngine engine;
@ -112,7 +115,6 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
});
}
@SuppressLint("ClickableViewAccessibility")
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@ -121,7 +123,8 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
view = getInflater().inflate(
R.layout.online_routing_engine_fragment, container, false);
segmentsContainer = (ViewGroup) view.findViewById(R.id.segments_container);
scrollView = (ScrollView) segmentsContainer.getParent();
scrollView = (ScrollView) view.findViewById(R.id.segments_scroll);
buttonsShadow = (AppCompatImageView) view.findViewById(R.id.buttons_shadow);
if (Build.VERSION.SDK_INT >= 21) {
AndroidUtils.addStatusBarPadding21v(getContext(), view);
}
@ -138,67 +141,9 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
generateUniqueNameIfNeeded();
updateCardViews(nameCard, typeCard, vehicleCard, exampleCard);
scrollView.setOnTouchListener(new View.OnTouchListener() {
int scrollViewY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
int y = scrollView.getScrollY();
if (isKeyboardShown && scrollViewY != y) {
scrollViewY = y;
View focus = mapActivity.getCurrentFocus();
if (focus != null) {
AndroidUtils.hideSoftKeyboard(mapActivity, focus);
focus.clearFocus();
}
}
return false;
}
});
onGlobalLayout = new ViewTreeObserver.OnGlobalLayoutListener() {
private int layoutHeightPrevious;
private int layoutHeightMin;
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Rect visibleDisplayFrame = new Rect();
view.getWindowVisibleDisplayFrame(visibleDisplayFrame);
int layoutHeight = visibleDisplayFrame.bottom;
if (layoutHeight < layoutHeightPrevious) {
isKeyboardShown = true;
layoutHeightMin = layoutHeight;
} else {
isKeyboardShown = layoutHeight == layoutHeightMin;
}
if (layoutHeight != layoutHeightPrevious) {
FrameLayout.LayoutParams rootViewLayout = (FrameLayout.LayoutParams) view.getLayoutParams();
rootViewLayout.height = layoutHeight;
view.requestLayout();
layoutHeightPrevious = layoutHeight;
}
view.post(new Runnable() {
@Override
public void run() {
view.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayout);
}
});
}
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayout);
}
showShadowBelowButtons();
showButtonsAboveKeyboard();
hideKeyboardOnScroll();
return view;
}
@ -223,8 +168,7 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
actionBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onDeleteEngine();
dismiss();
delete(mapActivity);
}
});
} else {
@ -359,6 +303,7 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
exampleCard = new OnlineRoutingCard(mapActivity, isNightMode(), appMode);
exampleCard.build(mapActivity);
exampleCard.setHeaderTitle(getString(R.string.shared_string_example));
exampleCard.hideFieldBoxLabel();
List<HorizontalSelectionItem> locationItems = new ArrayList<>();
for (ExampleLocation location : ExampleLocation.values()) {
locationItems.add(new HorizontalSelectionItem(location.getName(), location));
@ -390,7 +335,7 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
private void setupResultsContainer() {
testResultsContainer = getInflater().inflate(
R.layout.bottom_sheet_item_with_descr_64dp, segmentsContainer, false);
testResultsContainer.setVisibility(View.INVISIBLE);
testResultsContainer.setVisibility(View.GONE);
segmentsContainer.addView(testResultsContainer);
}
@ -480,6 +425,22 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
helper.deleteEngine(engine);
}
private void delete(Activity activity) {
if (engine != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(UiUtilities.getThemedContext(activity, isNightMode()));
builder.setMessage(getString(R.string.delete_online_routing_engine));
builder.setNegativeButton(R.string.shared_string_no, null);
builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onDeleteEngine();
dismiss();
}
});
builder.create().show();
}
}
private boolean isEditingMode() {
return editedEngineKey != null;
}
@ -511,8 +472,8 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
}
private void showTestResults(final boolean resultOk,
final @NonNull String message,
final @NonNull ExampleLocation location) {
final @NonNull String message,
final @NonNull ExampleLocation location) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
@ -528,6 +489,12 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
tvTitle.setText(String.format(getString(R.string.message_server_error), message));
}
tvDescription.setText(location.getName());
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, scrollView.getChildAt(0).getBottom());
}
});
}
});
}
@ -567,6 +534,10 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
public void showExitDialog() {
View focus = view.findFocus();
AndroidUtils.hideSoftKeyboard(mapActivity, focus);
if (hasNameDuplicate(initEngine)) {
List<OnlineRoutingEngine> cachedEngines = helper.getEnginesExceptMentionedKeys(editedEngineKey);
OnlineRoutingUtils.generateUniqueName(app, initEngine, cachedEngines);
}
if (!engine.equals(initEngine)) {
AlertDialog.Builder dismissDialog = createWarningDialog(mapActivity,
R.string.shared_string_dismiss, R.string.exit_without_saving, R.string.shared_string_cancel);
@ -627,11 +598,8 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
@Override
public void onDestroyView() {
super.onDestroyView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayout);
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(onGlobalLayout);
}
removeOnGlobalLayoutListener();
removeOnScrollListener();
}
@Override
@ -699,8 +667,8 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
}
public static void showInstance(@NonNull FragmentActivity activity,
@NonNull ApplicationMode appMode,
@Nullable String editedEngineKey) {
@NonNull ApplicationMode appMode,
@Nullable String editedEngineKey) {
FragmentManager fm = activity.getSupportFragmentManager();
if (!fm.isStateSaved() && fm.findFragmentByTag(OnlineRoutingEngineFragment.TAG) == null) {
OnlineRoutingEngineFragment fragment = new OnlineRoutingEngineFragment();
@ -711,4 +679,122 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
.addToBackStack(TAG).commitAllowingStateLoss();
}
}
@SuppressLint("ClickableViewAccessibility")
private void hideKeyboardOnScroll() {
scrollView.setOnTouchListener(new View.OnTouchListener() {
int scrollViewY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
int y = scrollView.getScrollY();
if (isKeyboardShown && scrollViewY != y) {
scrollViewY = y;
View focus = mapActivity.getCurrentFocus();
if (focus != null) {
AndroidUtils.hideSoftKeyboard(mapActivity, focus);
focus.clearFocus();
}
}
return false;
}
});
}
private void showShadowBelowButtons() {
scrollView.getViewTreeObserver().addOnScrollChangedListener(getShowShadowOnScrollListener());
}
private void showButtonsAboveKeyboard() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().addOnGlobalLayoutListener(getShowButtonsOnGlobalListener());
}
}
private OnScrollChangedListener getShowShadowOnScrollListener() {
if (onScroll == null) {
onScroll = new OnScrollChangedListener() {
@Override
public void onScrollChanged() {
boolean scrollToBottomAvailable = scrollView.canScrollVertically(1);
if (scrollToBottomAvailable) {
showShadowButton();
} else {
hideShadowButton();
}
}
};
}
return onScroll;
}
private OnGlobalLayoutListener getShowButtonsOnGlobalListener() {
if (onGlobalLayout == null) {
onGlobalLayout = new OnGlobalLayoutListener() {
private int layoutHeightPrevious;
private int layoutHeightMin;
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Rect visibleDisplayFrame = new Rect();
view.getWindowVisibleDisplayFrame(visibleDisplayFrame);
int layoutHeight = visibleDisplayFrame.bottom;
if (layoutHeight < layoutHeightPrevious) {
isKeyboardShown = true;
layoutHeightMin = layoutHeight;
} else {
isKeyboardShown = layoutHeight == layoutHeightMin;
}
if (layoutHeight != layoutHeightPrevious) {
FrameLayout.LayoutParams rootViewLayout = (FrameLayout.LayoutParams) view.getLayoutParams();
rootViewLayout.height = layoutHeight;
view.requestLayout();
layoutHeightPrevious = layoutHeight;
}
view.post(new Runnable() {
@Override
public void run() {
view.getViewTreeObserver().addOnGlobalLayoutListener(getShowButtonsOnGlobalListener());
}
});
}
};
}
return onGlobalLayout;
}
private void removeOnScrollListener() {
scrollView.getViewTreeObserver().removeOnScrollChangedListener(getShowShadowOnScrollListener());
}
private void removeOnGlobalLayoutListener() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver().removeOnGlobalLayoutListener(getShowButtonsOnGlobalListener());
} else {
view.getViewTreeObserver().removeGlobalOnLayoutListener(getShowButtonsOnGlobalListener());
}
}
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);
}
}

View file

@ -1,12 +1,18 @@
package net.osmand.plus.settings.bottomsheets;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@ -133,6 +139,7 @@ public class AnnouncementTimeBottomSheet extends BasePreferenceBottomSheet
ivArrow = rootView.findViewById(R.id.iv_arrow);
tvIntervalsDescr = rootView.findViewById(R.id.tv_interval_descr);
setProfileColorToSeekBar();
seekBarArrival.setOnSeekBarChangeListener(this);
seekBarArrival.setProgress(selectedEntryIndex);
seekBarArrival.setMax(listPreference.getEntries().length - 1);
@ -163,6 +170,31 @@ public class AnnouncementTimeBottomSheet extends BasePreferenceBottomSheet
AndroidUiHelper.updateVisibility(tvIntervalsDescr, !collapsed);
}
private void setProfileColorToSeekBar() {
int color = ContextCompat.getColor(app, getAppMode().getIconColorInfo().getColor(nightMode));
LayerDrawable seekBarProgressLayer =
(LayerDrawable) ContextCompat.getDrawable(app, R.drawable.seekbar_progress_announcement_time);
GradientDrawable background = (GradientDrawable) seekBarProgressLayer.findDrawableByLayerId(R.id.background);
background.setColor(color);
background.setAlpha(70);
GradientDrawable progress = (GradientDrawable) seekBarProgressLayer.findDrawableByLayerId(R.id.progress);
progress.setColor(color);
Drawable clippedProgress = new ClipDrawable(progress, Gravity.CENTER_VERTICAL | Gravity.START, 1);
seekBarArrival.setProgressDrawable(new LayerDrawable(new Drawable[] {
background, clippedProgress
}));
LayerDrawable seekBarThumpLayer =
(LayerDrawable) ContextCompat.getDrawable(app, R.drawable.seekbar_thumb_announcement_time);
GradientDrawable thump = (GradientDrawable) seekBarThumpLayer.findDrawableByLayerId(R.id.thump);
thump.setColor(color);
seekBarArrival.setThumb(thump);
}
public static void showInstance(@NonNull FragmentManager fm, String prefKey, Fragment target,
@Nullable ApplicationMode appMode, boolean usedOnMap) {
try {

View file

@ -0,0 +1,102 @@
package net.osmand.plus.track;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PicassoUtils;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.util.Algorithms;
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.getMetadataImageLink;
public class DescriptionCard extends BaseCard {
private final GPXFile gpxFile;
public DescriptionCard(@NonNull MapActivity mapActivity, @NonNull GPXFile gpxFile) {
super(mapActivity);
this.gpxFile = gpxFile;
}
@Override
public int getCardLayoutId() {
return R.layout.gpx_description_preview_card;
}
@Override
protected void updateContent() {
if (gpxFile.metadata == null || gpxFile.metadata.getDescription() == null) {
AndroidUiHelper.updateVisibility(view, false);
return;
} else {
AndroidUiHelper.updateVisibility(view, true);
}
final String title = gpxFile.metadata.getArticleTitle();
final String imageUrl = getMetadataImageLink(gpxFile.metadata);
final String descriptionHtml = gpxFile.metadata.getDescription();
setupImage(imageUrl);
TextViewEx tvDescription = view.findViewById(R.id.description);
tvDescription.setText(getFirstParagraph(descriptionHtml));
TextViewEx readBtn = view.findViewById(R.id.btn_read_full);
readBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GpxReadDescriptionDialogFragment.showInstance(mapActivity, title, imageUrl, descriptionHtml);
}
});
TextViewEx editBtn = view.findViewById(R.id.btn_edit);
editBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GpxEditDescriptionDialogFragment.showInstance(mapActivity, descriptionHtml, null);
}
});
}
private String getFirstParagraph(String descriptionHtml) {
if (descriptionHtml != null) {
String firstParagraph = WikiArticleHelper.getPartialContent(descriptionHtml);
if (!Algorithms.isEmpty(firstParagraph)) {
return firstParagraph;
}
}
return descriptionHtml;
}
private void setupImage(final String imageUrl) {
if (imageUrl == null) {
return;
}
final PicassoUtils picasso = PicassoUtils.getPicasso(app);
RequestCreator rc = Picasso.get().load(imageUrl);
final AppCompatImageView image = view.findViewById(R.id.main_image);
rc.into(image, new Callback() {
@Override
public void onSuccess() {
picasso.setResultLoaded(imageUrl, true);
AndroidUiHelper.updateVisibility(image, true);
}
@Override
public void onError(Exception e) {
picasso.setResultLoaded(imageUrl, false);
}
});
}
}

View file

@ -0,0 +1,131 @@
package net.osmand.plus.track;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.plus.widgets.EditTextEx;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
public static final String TAG = GpxEditDescriptionDialogFragment.class.getSimpleName();
private static final Log log = PlatformUtil.getLog(GpxEditDescriptionDialogFragment.class);
private static final String CONTENT_KEY = "content_key";
private EditTextEx editableHtml;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
OsmandApplication app = getMyApplication();
boolean nightMode = app.getDaynightHelper().isNightModeForMapControls();
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.dialog_edit_gpx_description, container, false);
editableHtml = view.findViewById(R.id.description);
view.findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
view.findViewById(R.id.btn_save).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Editable editable = editableHtml.getText();
if (!Algorithms.isEmpty(editable) && !saveGpx(editable.toString())) {
dismiss();
}
}
});
Bundle args = getArguments();
if (args != null) {
String html = args.getString(CONTENT_KEY);
if (html != null) {
editableHtml.setText(html);
}
}
return view;
}
private boolean saveGpx(final String html) {
MapActivity mapActivity = getMapActivity();
if (mapActivity == null || mapActivity.getTrackMenuFragment() == null) {
return false;
}
TrackMenuFragment trackMenuFragment = mapActivity.getTrackMenuFragment();
GPXFile gpx = trackMenuFragment.getGpx();
gpx.metadata.getExtensionsToWrite().put("desc", html);
File file = trackMenuFragment.getDisplayHelper().getFile();
new SaveGpxAsyncTask(file, gpx, new SaveGpxListener() {
@Override
public void gpxSavingStarted() {
}
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (errorMessage != null) {
log.error(errorMessage);
}
MapActivity mapActivity = getMapActivity();
if (mapActivity == null || mapActivity.getTrackMenuFragment() == null) {
TrackMenuFragment trackMenuFragment = mapActivity.getTrackMenuFragment();
trackMenuFragment.updateContent();
}
Fragment target = getTargetFragment();
if (target instanceof GpxReadDescriptionDialogFragment) {
((GpxReadDescriptionDialogFragment) target).updateContent(html);
}
dismiss();
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return true;
}
@Nullable
private MapActivity getMapActivity() {
return (MapActivity) getActivity();
}
public static void showInstance(@NonNull FragmentActivity activity, @NonNull String description, @Nullable Fragment target) {
FragmentManager fragmentManager = activity.getSupportFragmentManager();
if (!fragmentManager.isStateSaved()) {
Bundle args = new Bundle();
args.putString(CONTENT_KEY, description);
GpxEditDescriptionDialogFragment fragment = new GpxEditDescriptionDialogFragment();
fragment.setArguments(args);
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, GpxEditDescriptionDialogFragment.TAG);
}
}
}

View file

@ -0,0 +1,251 @@
package net.osmand.plus.track;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import net.osmand.AndroidUtils;
import net.osmand.PicassoUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.widgets.WebViewEx;
import net.osmand.plus.wikivoyage.WikivoyageUtils;
import net.osmand.util.Algorithms;
public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment {
public static final String TAG = GpxReadDescriptionDialogFragment.class.getSimpleName();
private static final String TITLE_KEY = "title_key";
private static final String IMAGE_URL_KEY = "image_url_key";
private static final String CONTENT_KEY = "content_key";
private static final int EDIT_ID = 1;
private WebViewEx webView;
private String title;
private String imageUrl;
private String contentHtml;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (savedInstanceState != null) {
readBundle(savedInstanceState);
} else if (args != null) {
readBundle(args);
}
}
private void readBundle(Bundle bundle) {
title = bundle.getString(TITLE_KEY);
imageUrl = bundle.getString(IMAGE_URL_KEY);
contentHtml = bundle.getString(CONTENT_KEY);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
OsmandApplication app = getMyApplication();
boolean nightMode = app.getDaynightHelper().isNightModeForMapControls();
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.dialog_read_gpx_description, container, false);
setupToolbar(view);
setupImage(view);
setupWebView(view);
return view;
}
@Override
public void onResume() {
super.onResume();
loadWebviewData();
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == EDIT_ID) {
FragmentActivity activity = getActivity();
if (activity != null) {
GpxEditDescriptionDialogFragment.showInstance(activity, contentHtml, this);
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
menu.clear();
OsmandApplication app = getMyApplication();
int color = AndroidUtils.resolveAttribute(app, R.attr.pstsTextColor);
MenuItem menuItem = menu.add(0, EDIT_ID, 0, app.getString(R.string.shared_string_edit));
menuItem.setIcon(getIcon(R.drawable.ic_action_edit_dark, color));
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return onOptionsItemSelected(item);
}
});
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(TITLE_KEY, title);
outState.putString(IMAGE_URL_KEY, imageUrl);
outState.putString(CONTENT_KEY, contentHtml);
}
private void setupToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.toolbar);
getMyActivity().setSupportActionBar(toolbar);
setHasOptionsMenu(true);
toolbar.setClickable(true);
Context ctx = getMyActivity();
int iconColor = AndroidUtils.resolveAttribute(ctx, R.attr.pstsTextColor);
Drawable icBack = getMyApplication().getUIUtilities().getIcon(R.drawable.ic_arrow_back, iconColor);
toolbar.setNavigationIcon(icBack);
toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up);
if (!Algorithms.isEmpty(title)) {
toolbar.setTitle(title);
int titleColor = AndroidUtils.resolveAttribute(ctx, R.attr.pstsTextColor);
toolbar.setTitleTextColor(ContextCompat.getColor(ctx, titleColor));
}
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
dismiss();
}
});
}
private void setupImage(View view) {
if (imageUrl == null) {
return;
}
final OsmandApplication app = getMyApplication();
final PicassoUtils picasso = PicassoUtils.getPicasso(app);
final AppCompatImageView image = view.findViewById(R.id.main_image);
RequestCreator rc = Picasso.get().load(imageUrl);
WikivoyageUtils.setupNetworkPolicy(app.getSettings(), rc);
rc.into(image, new Callback() {
@Override
public void onSuccess() {
picasso.setResultLoaded(imageUrl, true);
AndroidUiHelper.updateVisibility(image, true);
}
@Override
public void onError(Exception e) {
picasso.setResultLoaded(imageUrl, false);
}
});
}
private void setupWebView(final View view) {
webView = view.findViewById(R.id.content);
webView.setScrollbarFadingEnabled(true);
webView.setVerticalScrollBarEnabled(false);
webView.setBackgroundColor(Color.TRANSPARENT);
webView.setLayerType(WebView.LAYER_TYPE_HARDWARE, null);
webView.getSettings().setTextZoom((int) (getResources().getConfiguration().fontScale * 100f));
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageCommitVisible(WebView webView, String url) {
super.onPageCommitVisible(webView, url);
setupDependentViews(view);
}
});
loadWebviewData();
}
public void updateContent(String content) {
contentHtml = content;
loadWebviewData();
}
private void loadWebviewData() {
String content = contentHtml;
if (content != null) {
content = isNightMode(false) ? getColoredContent(content) : content;
String encoded = Base64.encodeToString(content.getBytes(), Base64.NO_PADDING);
webView.loadData(encoded, "text/html", "base64");
}
}
private void setupDependentViews(final View view) {
TextViewEx readBtn = view.findViewById(R.id.btn_edit);
readBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentActivity activity = getActivity();
if (activity != null) {
GpxEditDescriptionDialogFragment.showInstance(activity, contentHtml, GpxReadDescriptionDialogFragment.this);
}
}
});
AndroidUiHelper.setVisibility(View.VISIBLE,
readBtn, view.findViewById(R.id.divider), view.findViewById(R.id.bottom_empty_space));
int backgroundColor = isNightMode(false) ?
R.color.activity_background_color_dark : R.color.activity_background_color_light;
view.findViewById(R.id.root).setBackgroundResource(backgroundColor);
}
private String getColoredContent(String content) {
return "<body style=\"color:white;\">\n" + content + "</body>\n";
}
public static void showInstance(@NonNull FragmentActivity activity, @NonNull String title, @NonNull String imageUrl, @NonNull String description) {
FragmentManager fragmentManager = activity.getSupportFragmentManager();
if (!fragmentManager.isStateSaved()) {
Bundle args = new Bundle();
args.putString(TITLE_KEY, title);
args.putString(IMAGE_URL_KEY, imageUrl);
args.putString(CONTENT_KEY, description);
GpxReadDescriptionDialogFragment fragment = new GpxReadDescriptionDialogFragment();
fragment.setArguments(args);
fragment.show(fragmentManager, GpxReadDescriptionDialogFragment.TAG);
}
}
}

View file

@ -0,0 +1,339 @@
package net.osmand.plus.track;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.myplaces.SegmentActionsListener;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected;
import static net.osmand.plus.track.OptionsCard.APPEARANCE_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.DIRECTIONS_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.EDIT_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX;
public class OverviewCard extends BaseCard {
private RecyclerView rvOverview;
private View showButton;
private View appearanceButton;
private View editButton;
private View directionsButton;
private final TrackDisplayHelper displayHelper;
private final GPXFile gpxFile;
private final GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
private final SegmentActionsListener listener;
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
@NonNull SegmentActionsListener listener) {
super(mapActivity);
this.displayHelper = displayHelper;
this.gpxFile = displayHelper.getGpx();
this.listener = listener;
}
@Override
public int getCardLayoutId() {
return R.layout.gpx_overview_fragment;
}
@Override
protected void updateContent() {
int iconColorDef = R.color.icon_color_active_light;
int iconColorPres = R.color.active_buttons_and_links_text_dark;
boolean fileAvailable = gpxFile.path != null && !gpxFile.showCurrentTrack;
showButton = view.findViewById(R.id.show_button);
appearanceButton = view.findViewById(R.id.appearance_button);
editButton = view.findViewById(R.id.edit_button);
directionsButton = view.findViewById(R.id.directions_button);
rvOverview = view.findViewById(R.id.recycler_overview);
initShowButton(iconColorDef, iconColorPres);
initAppearanceButton(iconColorDef, iconColorPres);
if (fileAvailable) {
initEditButton(iconColorDef, iconColorPres);
initDirectionsButton(iconColorDef, iconColorPres);
}
initStatBlocks();
}
void initStatBlocks() {
GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0);
GPXTrackAnalysis analysis = gpxItem.analysis;
boolean joinSegments = displayHelper.isJoinSegments();
float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
StatBlock sDistance = new StatBlock(app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app),
R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED);
StatBlock sAscent = new StatBlock(app.getString(R.string.altitude_ascent), asc,
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null);
StatBlock sDescent = new StatBlock(app.getString(R.string.altitude_descent), desc,
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE);
StatBlock sAvSpeed = new StatBlock(app.getString(R.string.average_speed), avg,
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null);
StatBlock sMaxSpeed = new StatBlock(app.getString(R.string.max_speed), max,
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null);
StatBlock sTimeSpan = new StatBlock(app.getString(R.string.shared_string_time_span),
Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()),
R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null);
LinearLayoutManager llManager = new LinearLayoutManager(app);
llManager.setOrientation(LinearLayoutManager.HORIZONTAL);
rvOverview.setLayoutManager(llManager);
rvOverview.setItemAnimator(new DefaultItemAnimator());
List<StatBlock> items = Arrays.asList(sDistance, sAscent, sDescent, sAvSpeed, sMaxSpeed, sTimeSpan);
final StatBlockAdapter siAdapter = new StatBlockAdapter(items);
rvOverview.setAdapter(siAdapter);
rvOverview.addItemDecoration(new HorizontalDividerDecoration(app));
}
private void initShowButton(final int iconColorDef, final int iconColorPres) {
final AppCompatImageView image = showButton.findViewById(R.id.image);
final AppCompatImageView filled = showButton.findViewById(R.id.filled);
final int iconShowResId = R.drawable.ic_action_view;
final int iconHideResId = R.drawable.ic_action_hide;
final boolean[] gpxFileSelected = {isGpxFileSelected(app, gpxFile)};
filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref);
filled.setAlpha(gpxFileSelected[0] ? 1f : 0.1f);
setImageDrawable(image, gpxFileSelected[0] ? iconShowResId : iconHideResId,
gpxFileSelected[0] ? iconColorPres : iconColorDef);
showButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
gpxFileSelected[0] = !gpxFileSelected[0];
filled.setAlpha(gpxFileSelected[0] ? 1f : 0.1f);
setImageDrawable(image, gpxFileSelected[0] ? iconShowResId : iconHideResId,
gpxFileSelected[0] ? iconColorPres : iconColorDef);
CardListener listener = getListener();
if (listener != null) {
listener.onCardButtonPressed(OverviewCard.this, SHOW_ON_MAP_BUTTON_INDEX);
}
}
});
}
private void initAppearanceButton(int iconColorDef, int iconColorPres) {
initButton(appearanceButton, APPEARANCE_BUTTON_INDEX, R.drawable.ic_action_appearance, iconColorDef, iconColorPres);
}
private void initEditButton(int iconColorDef, int iconColorPres) {
initButton(editButton, EDIT_BUTTON_INDEX, R.drawable.ic_action_edit_dark, iconColorDef, iconColorPres);
}
private void initDirectionsButton(int iconColorDef, int iconColorPres) {
initButton(directionsButton, DIRECTIONS_BUTTON_INDEX, R.drawable.ic_action_gdirections_dark, iconColorDef, iconColorPres);
}
private void initButton(View item, final int buttonIndex, int iconResId, int iconColorDef, int iconColorPres) {
final AppCompatImageView image = item.findViewById(R.id.image);
final AppCompatImageView filled = item.findViewById(R.id.filled);
filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref);
filled.setAlpha(0.1f);
setImageDrawable(image, iconResId, iconColorDef);
setOnTouchItem(item, image, filled, iconResId, iconColorDef, iconColorPres);
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CardListener listener = getListener();
if (listener != null) {
listener.onCardButtonPressed(OverviewCard.this, buttonIndex);
}
}
});
}
private void setImageDrawable(ImageView iv, @DrawableRes int resId, @ColorRes int color) {
Drawable icon = app.getUIUtilities().getIcon(resId, color);
iv.setImageDrawable(icon);
}
private void setOnTouchItem(View item, final ImageView image, final ImageView filled, @DrawableRes final int resId, @ColorRes final int colorDef, @ColorRes final int colorPres) {
item.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
filled.setAlpha(1f);
setImageDrawable(image, resId, colorPres);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
filled.setAlpha(0.1f);
setImageDrawable(image, resId, colorDef);
break;
}
}
return false;
}
});
}
private class StatBlockAdapter extends RecyclerView.Adapter<StatBlockViewHolder> {
private final List<StatBlock> statBlocks;
public StatBlockAdapter(List<StatBlock> StatBlocks) {
this.statBlocks = StatBlocks;
}
@Override
public int getItemCount() {
return statBlocks.size();
}
@NonNull
@Override
public StatBlockViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_gpx_stat_block, parent, false);
return new StatBlockViewHolder(itemView);
}
@Override
public void onBindViewHolder(StatBlockViewHolder holder, int position) {
final StatBlock item = statBlocks.get(position);
holder.valueText.setText(item.value);
holder.titleText.setText(item.title);
holder.valueText.setTextColor(app.getResources().getColor(R.color.active_color_primary_light));
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0);
if (gpxItem != null && gpxItem.analysis != null) {
ArrayList<GPXDataSetType> list = new ArrayList<>();
if (item.firstType != null) {
list.add(item.firstType);
}
if (item.secondType != null) {
list.add(item.secondType);
}
if (list.size() > 0) {
gpxItem.chartTypes = list.toArray(new GPXDataSetType[0]);
}
gpxItem.locationOnMap = gpxItem.locationStart;
listener.openAnalyzeOnMap(gpxItem);
}
}
});
setImageDrawable(holder.imageView, item.imageResId, item.imageColorId);
}
}
private static class StatBlockViewHolder extends RecyclerView.ViewHolder {
private final TextViewEx valueText;
private final TextView titleText;
private final AppCompatImageView imageView;
StatBlockViewHolder(View view) {
super(view);
valueText = view.findViewById(R.id.value);
titleText = view.findViewById(R.id.title);
imageView = view.findViewById(R.id.image);
}
}
private static class HorizontalDividerDecoration extends ItemDecoration {
private final Drawable divider;
private final int marginV;
private final int marginH;
public HorizontalDividerDecoration(Context context) {
int[] ATTRS = new int[] {android.R.attr.listDivider};
final TypedArray ta = context.obtainStyledAttributes(ATTRS);
divider = ta.getDrawable(0);
// DrawableCompat.setTint(divider, context.getResources().getColor(R.color.divider_color_light)); //todo change drawable color
ta.recycle();
marginV = context.getResources().getDimensionPixelSize(R.dimen.map_small_button_margin);
marginH = context.getResources().getDimensionPixelSize(R.dimen.content_padding);
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
drawHorizontal(c, parent);
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
for (int i = 0; i < parent.getChildCount(); i++) {
final View child = parent.getChildAt(i);
final int left = child.getRight() - divider.getIntrinsicWidth() + marginH;
final int right = left + divider.getIntrinsicHeight();
final int top = child.getTop() + marginV;
final int bottom = child.getBottom() - marginV;
divider.setBounds(left, top, right, bottom);
divider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
outRect.set(marginH - divider.getIntrinsicWidth(), marginV, marginH + divider.getIntrinsicWidth(), marginV);
}
}
private static class StatBlock {
private final String title;
private final String value;
private final int imageResId;
private final int imageColorId;
private final GPXDataSetType firstType;
private final GPXDataSetType secondType;
public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
GPXDataSetType firstType, GPXDataSetType secondType) {
this.title = title;
this.value = value;
this.imageResId = imageResId;
this.imageColorId = imageColorId;
this.firstType = firstType;
this.secondType = secondType;
}
}
}

View file

@ -23,16 +23,14 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.FileUtils.RenameCallback;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Track;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
@ -42,18 +40,20 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.UpdateLocationViewCache;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityActions;
import net.osmand.plus.base.ContextMenuFragment;
import net.osmand.plus.base.ContextMenuScrollFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.OpenGpxDetailsTask;
import net.osmand.plus.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
@ -61,7 +61,6 @@ import net.osmand.plus.measurementtool.GpxData;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo;
import net.osmand.plus.myplaces.GPXTabItemType;
import net.osmand.plus.myplaces.MoveGpxFileBottomSheet;
import net.osmand.plus.myplaces.MoveGpxFileBottomSheet.OnTrackFileMoveListener;
import net.osmand.plus.myplaces.SegmentActionsListener;
@ -73,6 +72,7 @@ import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.plus.widgets.IconPopupMenu;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
@ -96,7 +96,7 @@ import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX;
public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener,
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener {
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, OsmAndLocationListener, OsmAndCompassListener {
public static final String TAG = TrackMenuFragment.class.getName();
private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class);
@ -109,15 +109,23 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
private TextView headerTitle;
private ImageView headerIcon;
private BottomNavigationView bottomNav;
private TrackMenuType menuType = TrackMenuType.TRACK;
private TrackMenuType menuType = TrackMenuType.OVERVIEW;
private SegmentsCard segmentsCard;
private OptionsCard optionsCard;
private DescriptionCard descriptionCard;
private OverviewCard overviewCard;
private TrackChartPoints trackChartPoints;
private int menuTitleHeight;
private String gpxTitle;
private UpdateLocationViewCache updateLocationViewCache;
private Location lastLocation = null;
private Float heading;
private boolean locationUpdateStarted;
public enum TrackMenuType {
OVERVIEW(R.id.action_overview, R.string.shared_string_overview),
TRACK(R.id.action_track, R.string.shared_string_gpx_tracks),
POINTS(R.id.action_points, R.string.shared_string_gpx_points),
OPTIONS(R.id.action_options, R.string.shared_string_options);
@ -160,6 +168,11 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
}
@Override
public int getInitialMenuState() {
return MenuState.HEADER_ONLY;
}
public TrackDisplayHelper getDisplayHelper() {
return displayHelper;
}
@ -184,6 +197,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
}
displayHelper.setGpx(selectedGpxFile.getGpxFile());
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
gpxTitle = GpxUiHelper.getGpxTitle(fileName);
}
}
@ -199,9 +214,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
routeMenuTopShadowAll = view.findViewById(R.id.route_menu_top_shadow_all);
headerTitle = view.findViewById(R.id.title);
headerIcon = view.findViewById(R.id.icon_view);
updateLocationViewCache = app.getUIUtilities().getUpdateLocationViewCache();
if (isPortrait()) {
updateCardsLayout();
AndroidUiHelper.updateVisibility(getTopShadow(), true);
} else {
int widthNoShadow = getLandscapeNoShadowWidth();
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -218,14 +234,32 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
return view;
}
private void setHeaderTitle(String text, boolean iconVisibility) {
headerTitle.setText(text);
AndroidUiHelper.updateVisibility(headerIcon, iconVisibility);
}
private void updateHeader() {
if (menuType == TrackMenuType.OPTIONS) {
headerTitle.setText(menuType.titleId);
AndroidUiHelper.updateVisibility(headerIcon, false);
ViewGroup headerContainer = (ViewGroup) routeMenuTopShadowAll;
if (menuType == TrackMenuType.OVERVIEW) {
setHeaderTitle(gpxTitle, true);
if (overviewCard != null && overviewCard.getView() != null) {
ViewGroup parent = ((ViewGroup) overviewCard.getView().getParent());
if (parent != null) {
parent.removeView(overviewCard.getView());
}
headerContainer.addView(overviewCard.getView());
} else {
overviewCard = new OverviewCard(getMapActivity(), displayHelper, this);
overviewCard.setListener(this);
headerContainer.addView(overviewCard.build(getMapActivity()));
}
} else {
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
headerTitle.setText(GpxUiHelper.getGpxTitle(fileName));
AndroidUiHelper.updateVisibility(headerIcon, true);
if (overviewCard != null && overviewCard.getView() != null) {
headerContainer.removeView(overviewCard.getView());
}
boolean isOptions = menuType == TrackMenuType.OPTIONS;
setHeaderTitle(isOptions ? app.getString(menuType.titleId) : gpxTitle, !isOptions);
}
}
@ -258,6 +292,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
optionsCard.setListener(this);
cardsContainer.addView(optionsCard.build(mapActivity));
}
} else if (menuType == TrackMenuType.OVERVIEW) {
if (descriptionCard != null && descriptionCard.getView() != null) {
ViewGroup parent = ((ViewGroup) descriptionCard.getView().getParent());
if (parent != null) {
cardsContainer.removeView(descriptionCard.getView());
}
cardsContainer.addView(descriptionCard.getView());
} else {
descriptionCard = new DescriptionCard(getMapActivity(), displayHelper.getGpx());
cardsContainer.addView(descriptionCard.build(mapActivity));
}
}
}
}
@ -306,6 +351,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null && trackChartPoints != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints);
}
updateHeader();
startLocationUpdate();
}
@Override
@ -315,6 +362,67 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(null);
}
stopLocationUpdate();
}
@Override
public void updateLocation(Location location) {
if (!MapUtils.areLatLonEqual(lastLocation, location)) {
lastLocation = location;
updateLocationUi();
}
}
@Override
public void updateCompassValue(float value) {
// 99 in next line used to one-time initialize arrows (with reference vs. fixed-north direction)
// on non-compass devices
float lastHeading = heading != null ? heading : 99;
heading = value;
if (Math.abs(MapUtils.degreesDiff(lastHeading, heading)) > 5) {
updateLocationUi();
} else {
heading = lastHeading;
}
}
private void updateLocationUi() {
app.runInUIThread(new Runnable() {
@Override
public void run() {
updateDistanceDirection();
}
});
}
private void updateDistanceDirection() {
MapActivity mapActivity = getMapActivity();
View view = overviewCard.getView();
if (mapActivity != null && view != null) {
MapContextMenu menu = mapActivity.getContextMenu();
TextView distanceText = (TextView) view.findViewById(R.id.distance);
ImageView direction = (ImageView) view.findViewById(R.id.direction);
app.getUIUtilities().updateLocationView(updateLocationViewCache, direction, distanceText, menu.getLatLon());
}
}
private void startLocationUpdate() {
OsmandApplication app = getMyApplication();
if (app != null && !locationUpdateStarted) {
locationUpdateStarted = true;
app.getLocationProvider().addCompassListener(this);
app.getLocationProvider().addLocationListener(this);
updateLocationUi();
}
}
private void stopLocationUpdate() {
OsmandApplication app = getMyApplication();
if (app != null && locationUpdateStarted) {
locationUpdateStarted = false;
app.getLocationProvider().removeLocationListener(this);
app.getLocationProvider().removeCompassListener(this);
}
}
@Override
@ -415,7 +523,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity == null) {
return;
}
if (card instanceof OptionsCard) {
if (card instanceof OptionsCard || card instanceof OverviewCard) {
final GPXFile gpxFile = getGpx();
if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) {
boolean gpxFileSelected = !isGpxFileSelected(app, gpxFile);
@ -547,27 +655,12 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
}
private void updateCardsLayout() {
View mainView = getMainView();
if (mainView != null) {
View topShadow = getTopShadow();
FrameLayout bottomContainer = getBottomContainer();
if (getCurrentMenuState() == MenuState.HEADER_ONLY) {
topShadow.setVisibility(View.INVISIBLE);
bottomContainer.setBackgroundDrawable(null);
} else {
topShadow.setVisibility(View.VISIBLE);
AndroidUtils.setBackground(mainView.getContext(), bottomContainer, isNightMode(), R.color.list_background_color_light, R.color.list_background_color_dark);
}
}
}
private void setupButtons(View view) {
ColorStateList navColorStateList = AndroidUtils.createBottomNavColorStateList(getContext(), isNightMode());
BottomNavigationView bottomNav = view.findViewById(R.id.bottom_navigation);
bottomNav.setItemIconTintList(navColorStateList);
bottomNav.setItemTextColor(navColorStateList);
bottomNav.setSelectedItemId(R.id.action_track);
bottomNav.setSelectedItemId(R.id.action_overview);
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
@ -592,6 +685,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (optionsCard != null) {
optionsCard.updateContent();
}
if (descriptionCard != null) {
descriptionCard.updateContent();
}
setupCards();
}
@ -630,46 +726,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
@Override
public void openAnalyzeOnMap(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets, GPXTabItemType tabType) {
WptPt wpt = null;
gpxItem.chartTypes = null;
if (dataSets != null && dataSets.size() > 0) {
gpxItem.chartTypes = new GPXDataSetType[dataSets.size()];
for (int i = 0; i < dataSets.size(); i++) {
OrderedLineDataSet orderedDataSet = (OrderedLineDataSet) dataSets.get(i);
gpxItem.chartTypes[i] = orderedDataSet.getDataSetType();
}
if (gpxItem.chartHighlightPos != -1) {
TrkSegment segment = null;
for (Track t : gpxItem.group.getGpx().tracks) {
for (TrkSegment s : t.segments) {
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
segment = s;
break;
}
}
if (segment != null) {
break;
}
}
if (segment != null) {
OrderedLineDataSet dataSet = (OrderedLineDataSet) dataSets.get(0);
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
for (WptPt p : segment.points) {
if (p.distance >= distance) {
wpt = p;
break;
}
}
}
}
}
if (wpt != null) {
gpxItem.locationOnMap = wpt;
} else {
gpxItem.locationOnMap = gpxItem.locationStart;
}
public void openAnalyzeOnMap(GpxDisplayItem gpxItem) {
TrackDetailsMenu trackDetailsMenu = getMapActivity().getTrackDetailsMenu();
trackDetailsMenu.setGpxItem(gpxItem);
trackDetailsMenu.show();
@ -788,7 +845,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
Bundle args = new Bundle();
args.putString(TRACK_FILE_NAME, path);
args.putBoolean(CURRENT_RECORDING, showCurrentTrack);
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HALF_SCREEN);
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY);
TrackMenuFragment fragment = new TrackMenuFragment();
fragment.setArguments(args);

View file

@ -2,6 +2,9 @@ package net.osmand.plus.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import net.osmand.plus.R;
import studio.carbonylgroup.textfieldboxes.TextFieldBoxes;
@ -19,4 +22,11 @@ public class OsmandTextFieldBoxes extends TextFieldBoxes {
super(context, attrs, defStyleAttr);
}
public void makeCompactPadding() {
floatingLabel.setVisibility(View.GONE);
labelSpace.setVisibility(View.GONE);
labelSpaceBelow.setVisibility(View.GONE);
int paddingH = getResources().getDimensionPixelSize(R.dimen.route_info_card_details_margin);
inputLayout.setPadding(0, paddingH, 0, paddingH);
}
}

View file

@ -130,7 +130,7 @@ public class TravelObfHelper implements TravelHelper {
@Nullable
private TravelArticle cacheTravelArticles(File file, Amenity amenity, String lang, boolean readPoints) {
TravelArticle article = null;
Map<String, TravelArticle> articles = readArticles(file, amenity, readPoints);
Map<String, TravelArticle> articles = readArticles(file, amenity, false);
if (!Algorithms.isEmpty(articles)) {
TravelArticleIdentifier newArticleId = articles.values().iterator().next().generateIdentifier();
cachedArticles.put(newArticleId, articles);
@ -536,8 +536,7 @@ public class TravelObfHelper implements TravelHelper {
@Override
public boolean publish(Amenity amenity) {
if (Algorithms.stringsEqual(articleId.routeId, Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID, null)))
&& Algorithms.stringsEqual(articleId.routeSource, Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_SOURCE, null))) || isDbArticle) {
if (Algorithms.stringsEqual(articleId.routeId, Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID, null))) || isDbArticle) {
amenities.add(amenity);
done = true;
}
@ -552,7 +551,7 @@ public class TravelObfHelper implements TravelHelper {
if (!Double.isNaN(articleId.lat)) {
req.setBBoxRadius(articleId.lat, articleId.lon, ARTICLE_SEARCH_RADIUS);
if (!Algorithms.isEmpty(articleId.routeId)) {
if (!Algorithms.isEmpty(articleId.title)) {
reader.searchPoiByName(req);
} else {
reader.searchPoi(req);