Merge branch 'master' of github.com:osmandapp/Osmand
This commit is contained in:
commit
28596321c6
61 changed files with 2248 additions and 1078 deletions
157
GPX.md
157
GPX.md
|
@ -1,157 +0,0 @@
|
|||
The OsmAnd's GPX file format conforms to the GPX 1.1 specification with additional data written as extensions. There are several sections of such data:
|
||||
|
||||
## Track appearance
|
||||
The following parameters are used to customize the appearance of a track on the map. They are used inside the "gpx" tag and apply to all tracks contained in the gpx.
|
||||
#### Parameters
|
||||
* **show_arrows** [*true, false*] - show / hide arrows along the path line.
|
||||
* **width** [*thin, medium, bold, 1-24*] - width of the track line on the map. The thin, medium, and bold are style depended values (should be defined as currentTrackWidth attribute).
|
||||
* **color** [*#AARRGGBB, #RRGGBB*] - color of a track line on the map. Hex value.
|
||||
* **split_type** [*no_split, distance, time*] - split type for a track.
|
||||
* **split_interval** [*double*] - split interval for a track. Distance (meters), time (seconds).
|
||||
|
||||
#### Example:
|
||||
```xml
|
||||
<gpx version="1.1" creator="OsmAndRouterV2" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
|
||||
...
|
||||
<extensions>
|
||||
<show_arrows>true</show_arrows>
|
||||
<color>#4e4eff</color>
|
||||
<split_type>distance</split_type>
|
||||
<split_interval>2000.0</split_interval>
|
||||
<width>bold</width>
|
||||
</extensions>
|
||||
</gpx>
|
||||
```
|
||||
## Details of a track point (trkpt)
|
||||
Written to a gpx file while recording a track.
|
||||
* **speed** (meters per second)
|
||||
* **heading** (0-359 degrees)
|
||||
|
||||
#### Example:
|
||||
```xml
|
||||
<trkpt lat="52.397799" lon="4.575998">
|
||||
<ele>203</ele>
|
||||
<time>2019-05-08T10:36:43Z</time>
|
||||
<hdop>3</hdop>
|
||||
<extensions>
|
||||
<heading>273</heading>
|
||||
<speed>5.02</speed>
|
||||
</extensions>
|
||||
</trkpt>
|
||||
```
|
||||
|
||||
## Calculated route(s)
|
||||
This data contains all details of a route built with **OsmAnd** (route segments, turns, road names, road types, restrictions, etc.). The route can be completely restored as if just built, even in the absence of the respective offline maps.
|
||||
|
||||
A gpx file may contain several routes. Each of them is contained in a specific segment under **trkseg** / **extensions**. A gpx file is saved in this form when exporting a constructed route or when saving a track that consists of several separate segments via the **Plan a route** functionality.
|
||||
**Plan a route** also adds one (or several, in accordance with the number of contained separate segments / tracks) **rte** blocks to the gpx file, containing route key points (**rtept**).
|
||||
#### Gpx structure:
|
||||
```xml
|
||||
<trk>
|
||||
<trkseg>
|
||||
<!-- List of segment points. The order of the points corresponds to the order and length of the route segments (<route><segment length="x" ... />). -->
|
||||
<!-- The value of the "length" attribute corresponds to the number of points in this segment of the route. -->
|
||||
<trkpt ... ></trkpt>
|
||||
<extensions>
|
||||
<!-- List of route segments -->
|
||||
<route>
|
||||
<segment ... />
|
||||
</route>
|
||||
<!-- Properties of segments included in the route. -->
|
||||
<!-- This data is taken from offline maps during the initial construction of a route. -->
|
||||
<types>
|
||||
<type ... />
|
||||
</types>
|
||||
</extensions>
|
||||
</trkseg>
|
||||
</trk>
|
||||
|
||||
<!-- List of intermediate route points. If there are multiple routes, the order of the rte list matches the order of the route segments. -->
|
||||
<rte>
|
||||
<rtept ... />
|
||||
<!-- For routes built with the "Plan route", the parameters of key points are saved. -->
|
||||
<extensions>
|
||||
<!-- Route profile type for next segment (car, bicycle, pedestrian, etc.). -->
|
||||
<profile>...</profile>
|
||||
<!-- The index of the point in the gpx segment that corresponds to the first point of the calculated route for this segment. -->
|
||||
<trkpt_idx>...</trkpt_idx>
|
||||
</extensions>
|
||||
</rtept>
|
||||
</rte>
|
||||
```
|
||||
|
||||
#### Example:
|
||||
```xml
|
||||
<gpx version="1.1" creator="OsmAndRouterV2" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
|
||||
<metadata>
|
||||
<name>Fri 06 Nov 2020</name>
|
||||
</metadata>
|
||||
<trk>
|
||||
<name>Fri 06 Nov 2020</name>
|
||||
<trkseg>
|
||||
<trkpt lat="52.3639849" lon="4.8900533">
|
||||
<ele>0.801</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="52.3636917" lon="4.8922849">
|
||||
<ele>0.998</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="52.3636885" lon="4.892309">
|
||||
<ele>1</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="52.3636426" lon="4.8922902">
|
||||
<ele>0.963</ele>
|
||||
</trkpt>
|
||||
<trkpt lat="52.363564" lon="4.8922607">
|
||||
<ele>0.899</ele>
|
||||
</trkpt>
|
||||
|
||||
....
|
||||
|
||||
<extensions>
|
||||
<route>
|
||||
<segment id="7372058" length="3" segmentTime="178.44" speed="1.11" turnType="C" types="0,1,2,3,4,5,6" names="57" />
|
||||
<segment id="334164679" length="5" segmentTime="86.11" speed="1.11" turnType="TR" turnAngle="91.88" types="7,8,0,9,10,11,12,13,6" pointTypes=";;14,15;16,17,18;" names="58" />
|
||||
<segment id="334603581" length="6" segmentTime="75.5" speed="1.11" types="19,20,21,7,8,0,22,9,10,11,12,13,23,6" pointTypes=";14;16,24;16,24;14;" names="58" />
|
||||
<segment id="446707354" length="3" segmentTime="8.32" speed="1.11" turnType="TSLL" turnAngle="-25.44" types="19,25,21,7,8,22,9,1,11,12,13,6" names="58" />
|
||||
...
|
||||
</route>
|
||||
<types>
|
||||
<type t="lit" v="yes" />
|
||||
<type t="oneway" v="yes" />
|
||||
<type t="highway" v="unclassified" />
|
||||
<type t="surface" v="paving_stones" />
|
||||
<type t="maxspeed" v="30" />
|
||||
...
|
||||
</types>
|
||||
</extensions>
|
||||
</trkseg>
|
||||
</trk>
|
||||
|
||||
<rte>
|
||||
<rtept lat="52.3639945" lon="4.8900532">
|
||||
<extensions>
|
||||
<profile>pedestrian</profile>
|
||||
<trkpt_idx>0</trkpt_idx>
|
||||
</extensions>
|
||||
</rtept>
|
||||
<rtept lat="52.3612797" lon="4.8911677">
|
||||
<extensions>
|
||||
<profile>pedestrian</profile>
|
||||
<trkpt_idx>24</trkpt_idx>
|
||||
</extensions>
|
||||
</rtept>
|
||||
<rtept lat="52.356996" lon="4.8912071">
|
||||
<extensions>
|
||||
<profile>pedestrian</profile>
|
||||
<trkpt_idx>89</trkpt_idx>
|
||||
</extensions>
|
||||
</rtept>
|
||||
<rtept lat="52.3542374" lon="4.8947024">
|
||||
<extensions>
|
||||
<profile>pedestrian</profile>
|
||||
<trkpt_idx>121</trkpt_idx>
|
||||
</extensions>
|
||||
</rtept>
|
||||
</rte>
|
||||
</gpx>
|
||||
```
|
|
@ -274,6 +274,10 @@ public class Amenity extends MapObject {
|
|||
return null;
|
||||
}
|
||||
|
||||
public String getTagContent(String tag) {
|
||||
return getTagContent(tag, null);
|
||||
}
|
||||
|
||||
public String getTagContent(String tag, String lang) {
|
||||
if (lang != null) {
|
||||
String translateName = getAdditionalInfo(tag + ":" + lang);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<string name="items_modified">items modified</string>
|
||||
<string name="osmand_unlimited">OsmAnd Unlimited</string>
|
||||
<string name="markers">Markers</string>
|
||||
<string name="opr_base_url">https://test.openplacereviews.org/</string>
|
||||
<string name="opr_base_url">https://openplacereviews.org/</string>
|
||||
<string name="dev_opr_base_url">https://test.openplacereviews.org/</string>
|
||||
<string name="osm_oauth_developer_key">v8G8r9NLJZGMV4he5lwbQlz620FNVARKjI9Bm5UJ</string>
|
||||
<string name="osm_oauth_developer_secret">jDvM95Ne1Bq2BDTmIfB6b3ZMxvdK87WGfp6DC07J</string>
|
||||
|
|
48
OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml
Normal file
48
OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?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:minHeight="@dimen/bottom_sheet_selected_item_title_height"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/measurement_tool_menu_title_padding_top"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding_small">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Some title" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/route_info_buttons_padding_left_right"
|
||||
android:layout_marginBottom="@dimen/route_info_buttons_padding_left_right"
|
||||
android:minHeight="0dp"
|
||||
android:visibility="visible" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingMultiplier="@dimen/bottom_sheet_text_spacing_multiplier"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Some description" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,80 +1,83 @@
|
|||
<?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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="@dimen/bottom_sheet_selected_item_title_height"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding">
|
||||
xmlns:app="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:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="@dimen/bottom_sheet_selected_item_title_height">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/basic_item_body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
<LinearLayout
|
||||
android:id="@+id/basic_item_body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingTop="@dimen/content_padding_small"
|
||||
android:paddingBottom="@dimen/content_padding"
|
||||
android:textAppearance="@style/TextAppearance.ListItemTitle"
|
||||
tools:text="Some title" />
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingTop="@dimen/content_padding_small"
|
||||
android:paddingBottom="@dimen/content_padding"
|
||||
android:textAppearance="@style/TextAppearance.ListItemTitle"
|
||||
tools:text="Some title" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/switch_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_content_margin"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_content_margin"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_content_margin"
|
||||
tools:checked="true" />
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/switch_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_content_margin"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
tools:checked="true" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/additional_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
<LinearLayout
|
||||
android:id="@+id/additional_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/content_padding_half"
|
||||
android:layout_marginBottom="@dimen/content_padding_half"
|
||||
android:background="?attr/divider_color_basic" />
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/content_padding_half"
|
||||
android:layout_marginBottom="@dimen/content_padding_half"
|
||||
android:background="?attr/divider_color_basic" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon_after_divider"
|
||||
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||
android:layout_width="@dimen/favorites_icon_right_margin"
|
||||
android:layout_height="@dimen/favorites_icon_right_margin"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
app:srcCompat="@drawable/ic_action_track_line_bold_color" />
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon_after_divider"
|
||||
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||
android:layout_width="@dimen/favorites_icon_right_margin"
|
||||
android:layout_height="@dimen/favorites_icon_right_margin"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
app:srcCompat="@drawable/ic_action_track_line_bold_color" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
30
OsmAnd/res/layout/context_menu_controls.xml
Normal file
30
OsmAnd/res/layout/context_menu_controls.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?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:id="@+id/map_controls_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<include
|
||||
layout="@layout/map_ruler"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|bottom"
|
||||
android:layout_marginStart="@dimen/fab_margin_right"
|
||||
android:layout_marginLeft="@dimen/fab_margin_right"
|
||||
android:layout_marginEnd="@dimen/fab_margin_right"
|
||||
android:layout_marginRight="@dimen/fab_margin_right" />
|
||||
|
||||
<include
|
||||
layout="@layout/map_hud_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_marginStart="@dimen/fab_margin_right"
|
||||
android:layout_marginLeft="@dimen/fab_margin_right"
|
||||
android:layout_marginEnd="@dimen/fab_margin_right"
|
||||
android:layout_marginRight="@dimen/fab_margin_right" />
|
||||
|
||||
</FrameLayout>
|
|
@ -42,25 +42,31 @@
|
|||
android:textSize="@dimen/dialog_header_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/btn_save"
|
||||
<FrameLayout
|
||||
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" />
|
||||
android:background="@drawable/btn_border_active">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/btn_save"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
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" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -69,17 +75,26 @@
|
|||
android:layout_height="1dp"
|
||||
android:background="?attr/divider_color" />
|
||||
|
||||
<net.osmand.plus.widgets.EditTextEx
|
||||
android:id="@+id/description"
|
||||
<ScrollView
|
||||
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." />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<net.osmand.plus.widgets.EditTextEx
|
||||
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/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding_half"
|
||||
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." />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
|
@ -56,32 +56,40 @@
|
|||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/divider_color"
|
||||
android:background="?attr/ctx_menu_info_divider"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/btn_edit"
|
||||
<FrameLayout
|
||||
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" />
|
||||
android:background="@drawable/rounded_background_3dp">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/btn_edit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
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>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bottom_empty_space"
|
||||
|
|
|
@ -99,34 +99,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/map_controls_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<include
|
||||
layout="@layout/map_ruler"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|bottom"
|
||||
android:layout_marginStart="@dimen/fab_margin_right"
|
||||
android:layout_marginLeft="@dimen/fab_margin_right"
|
||||
android:layout_marginEnd="@dimen/fab_margin_right"
|
||||
android:layout_marginRight="@dimen/fab_margin_right" />
|
||||
|
||||
<include
|
||||
layout="@layout/map_hud_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_marginStart="@dimen/fab_margin_right"
|
||||
android:layout_marginLeft="@dimen/fab_margin_right"
|
||||
android:layout_marginEnd="@dimen/fab_margin_right"
|
||||
android:layout_marginRight="@dimen/fab_margin_right" />
|
||||
|
||||
</FrameLayout>
|
||||
<include layout="@layout/context_menu_controls" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/control_buttons"
|
||||
|
|
|
@ -40,69 +40,119 @@
|
|||
tools:visibility="visible"
|
||||
tools:src="@drawable/img_help_announcement_time_day"/>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
<LinearLayout
|
||||
android:id="@id/description_container"
|
||||
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."/>
|
||||
android:orientation="vertical">
|
||||
|
||||
<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:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
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:background="@drawable/rounded_background_3dp">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/btn_read_full"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
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: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" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
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:background="@drawable/rounded_background_3dp">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/btn_edit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
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>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/btn_add"
|
||||
android:layout_width="wrap_content"
|
||||
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">
|
||||
android:layout_marginStart="@dimen/card_padding"
|
||||
android:layout_marginLeft="@dimen/card_padding"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:background="@drawable/rounded_background_3dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<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:background="?attr/selectableItemBackgroundBorderless"
|
||||
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"
|
||||
android:drawablePadding="@dimen/dialog_button_height"
|
||||
osmand:drawableStartCompat="@drawable/ic_action_add"
|
||||
osmand:drawableLeftCompat="@drawable/ic_action_add"
|
||||
osmand:drawableTint="?attr/wikivoyage_active_color"
|
||||
android:text="@string/shared_string_edit"
|
||||
android:text="@string/add_description"
|
||||
android:textColor="?attr/wikivoyage_active_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</FrameLayout>
|
||||
|
@ -110,6 +160,7 @@
|
|||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
|
||||
android:background="?attr/activity_background_basic">
|
||||
|
||||
<include
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_overview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:layout_marginBottom="@dimen/content_padding_small_half"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
|
@ -48,55 +48,60 @@
|
|||
|
||||
<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_height="@dimen/setting_list_item_small_height"
|
||||
android:layout_marginStart="@dimen/card_padding"
|
||||
android:layout_marginLeft="@dimen/card_padding"
|
||||
android:layout_marginTop="@dimen/content_padding_half"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/card_padding"
|
||||
android:layout_marginRight="@dimen/card_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:baselineAligned="false"
|
||||
android:minHeight="@dimen/context_menu_controller_height"
|
||||
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_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:layout_marginEnd="@dimen/list_item_button_padding"
|
||||
android:layout_marginRight="@dimen/list_item_button_padding"
|
||||
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_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:layout_marginEnd="@dimen/list_item_button_padding"
|
||||
android:layout_marginRight="@dimen/list_item_button_padding"
|
||||
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_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:layout_marginEnd="@dimen/list_item_button_padding"
|
||||
android:layout_marginRight="@dimen/list_item_button_padding"
|
||||
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_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:layout_marginEnd="@dimen/list_item_button_padding"
|
||||
android:layout_marginRight="@dimen/list_item_button_padding"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<?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">
|
||||
android:minHeight="@dimen/context_menu_controller_height"
|
||||
android:minWidth="@dimen/context_menu_top_right_button_min_width"
|
||||
android:layout_width="@dimen/fab_recycler_view_padding_bottom"
|
||||
android:layout_height="@dimen/setting_list_item_small_height">
|
||||
|
||||
<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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:alpha="0.1"
|
||||
tools:srcCompat="@drawable/bg_topbar_shield_exit_ref" />
|
||||
|
||||
|
|
|
@ -3,42 +3,62 @@
|
|||
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">
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/value"
|
||||
android:layout_width="match_parent"
|
||||
<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="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
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" />
|
||||
tools:text="@string/distance" />
|
||||
|
||||
</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" />
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/map_small_button_margin"
|
||||
android:layout_marginBottom="@dimen/map_small_button_margin"
|
||||
tools:background="@color/divider_color_light" />
|
||||
|
||||
</LinearLayout>
|
|
@ -90,34 +90,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/map_controls_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<include
|
||||
layout="@layout/map_ruler"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|bottom"
|
||||
android:layout_marginStart="@dimen/fab_margin_right"
|
||||
android:layout_marginLeft="@dimen/fab_margin_right"
|
||||
android:layout_marginEnd="@dimen/fab_margin_right"
|
||||
android:layout_marginRight="@dimen/fab_margin_right" />
|
||||
|
||||
<include
|
||||
layout="@layout/map_hud_controls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_marginStart="@dimen/fab_margin_right"
|
||||
android:layout_marginLeft="@dimen/fab_margin_right"
|
||||
android:layout_marginEnd="@dimen/fab_margin_right"
|
||||
android:layout_marginRight="@dimen/fab_margin_right" />
|
||||
|
||||
</FrameLayout>
|
||||
<include layout="@layout/context_menu_controls" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/control_buttons"
|
||||
|
|
|
@ -91,6 +91,13 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/header_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/list_background_color"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bottom_container"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -191,6 +198,8 @@
|
|||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/context_menu_controls" />
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottom_navigation"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,114 +1,115 @@
|
|||
<?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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_small"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding_small"
|
||||
android:text="@string/monitoring_settings"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_small"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding_small"
|
||||
android:text="@string/monitoring_settings"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<include
|
||||
android:id="@+id/show_track_on_map"
|
||||
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button" />
|
||||
<include
|
||||
android:id="@+id/show_track_on_map"
|
||||
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dashboard_divider" />
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dashboard_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/bottom_sheet_content_margin"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding">
|
||||
<LinearLayout
|
||||
android:id="@+id/interval_view_container"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/bottom_sheet_content_margin"
|
||||
android:paddingBottom="@dimen/bottom_sheet_content_margin"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/interval_value"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="Interval value" />
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/interval_value"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="Interval value" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/up_down_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:srcCompat="@drawable/ic_action_arrow_down" />
|
||||
</LinearLayout>
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/up_down_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
app:srcCompat="@drawable/ic_action_arrow_down" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/always_ask_and_range_slider_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding">
|
||||
<LinearLayout
|
||||
android:id="@+id/always_ask_and_range_slider_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding">
|
||||
|
||||
<com.google.android.material.slider.RangeSlider
|
||||
android:id="@+id/interval_slider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/save_track_interval_globally"
|
||||
android:stepSize="1"
|
||||
app:haloRadius="@dimen/content_padding_small"
|
||||
app:labelBehavior="gone"
|
||||
app:thumbColor="@color/profile_icon_color_blue_light"
|
||||
app:thumbRadius="@dimen/content_padding_small_half"
|
||||
app:trackColorActive="@color/profile_icon_color_blue_light"
|
||||
app:trackColorInactive="#4D007EB3"
|
||||
app:tickColorInactive="#007EB3"
|
||||
app:trackHeight="@dimen/slider_track_height"
|
||||
tools:visibility="visible" />
|
||||
<com.google.android.material.slider.RangeSlider
|
||||
android:id="@+id/interval_slider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/save_track_interval_globally"
|
||||
android:stepSize="1"
|
||||
app:haloRadius="@dimen/content_padding_small"
|
||||
app:labelBehavior="gone"
|
||||
app:thumbColor="@color/profile_icon_color_blue_light"
|
||||
app:thumbRadius="@dimen/content_padding_small_half"
|
||||
app:trackColorActive="@color/profile_icon_color_blue_light"
|
||||
app:trackColorInactive="#4D007EB3"
|
||||
app:tickColorInactive="#007EB3"
|
||||
app:trackHeight="@dimen/slider_track_height"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/confirm_every_run"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:minHeight="@dimen/context_menu_buttons_bottom_height"
|
||||
android:paddingLeft="@dimen/content_padding_small"
|
||||
android:paddingRight="@dimen/content_padding_small"
|
||||
android:text="@string/confirm_every_run"
|
||||
android:textColor="?attr/color_dialog_buttons"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/confirm_every_run"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:minHeight="@dimen/context_menu_buttons_bottom_height"
|
||||
android:paddingLeft="@dimen/content_padding_small"
|
||||
android:paddingRight="@dimen/content_padding_small"
|
||||
android:text="@string/confirm_every_run"
|
||||
android:textColor="?attr/color_dialog_buttons"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/second_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/bottom_sheet_content_margin_small"
|
||||
android:background="?attr/dashboard_divider" />
|
||||
<View
|
||||
android:id="@+id/second_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dashboard_divider" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
282
OsmAnd/res/layout/wikivoyage_travel_gpx_card.xml
Normal file
282
OsmAnd/res/layout/wikivoyage_travel_gpx_card.xml
Normal file
|
@ -0,0 +1,282 @@
|
|||
<?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">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/background_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/wikivoyage_card_bg_color">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/content_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/default_title_line_height"
|
||||
android:layout_marginBottom="@dimen/measurement_tool_menu_title_padding_bottom"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/active_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="London" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/distance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:textColor="@null"
|
||||
tools:text="5.3 km" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/distance_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_marginStart="@dimen/content_padding_half"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
osmand:srcCompat="@drawable/ic_action_distance_16"
|
||||
android:contentDescription="@string/distance"/>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="?attr/wikivoyage_card_divider_color" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/diff_ele_down"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:textColor="@null"
|
||||
tools:text="145 m" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/down_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_marginStart="@dimen/content_padding_half"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
osmand:srcCompat="@drawable/ic_action_arrow_down_16"
|
||||
android:tint="@color/icon_color_default_light"
|
||||
android:contentDescription="@string/distance" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="?attr/wikivoyage_card_divider_color" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/diff_ele_up"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:textColor="@null"
|
||||
tools:text="15 m" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/up_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_marginStart="@dimen/content_padding_half"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
osmand:srcCompat="@drawable/ic_action_arrow_up_16"
|
||||
android:tint="@color/icon_color_default_light"
|
||||
android:contentDescription="@string/distance" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingBottom="@dimen/content_padding_small">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/user_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/btn_border_bg_light"
|
||||
android:gravity="center_vertical"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingTop="@dimen/subHeaderPadding"
|
||||
android:paddingBottom="@dimen/subHeaderPadding"
|
||||
android:paddingLeft="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingRight="@dimen/bottom_sheet_content_padding_small"
|
||||
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:textColor="?attr/active_color_basic"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
android:drawablePadding="@dimen/content_padding_small_half"
|
||||
android:drawableStart="@drawable/ic_action_user_account_16"
|
||||
android:drawableLeft="@drawable/ic_action_user_account_16"
|
||||
tools:drawableTint="?attr/wikivoyage_active_color"
|
||||
tools:text="Lorem Ipsum" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:visibility="invisible"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/wikivoyage_card_divider_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/content_padding_small_half"
|
||||
android:paddingBottom="@dimen/content_padding_small_half">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_content_padding_small"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_content_padding_small"
|
||||
android:background="@drawable/rounded_background_3dp">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/left_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:drawablePadding="@dimen/content_padding_small"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
android:paddingLeft="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingRight="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:textColor="?attr/wikivoyage_active_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:drawableLeft="@drawable/ic_action_read_article"
|
||||
tools:drawableTint="?attr/wikivoyage_active_color"
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:text="Read"
|
||||
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
|
||||
tools:drawableStart="@drawable/ic_action_read_article" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_content_padding_small"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_content_padding_small"
|
||||
android:background="@drawable/rounded_background_3dp">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/right_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:drawablePadding="@dimen/content_padding_small"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
android:paddingLeft="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingRight="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:textColor="?attr/wikivoyage_active_color"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:drawableRight="@drawable/ic_action_read_later_fill"
|
||||
tools:drawableTint="?attr/wikivoyage_active_color"
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:text="Delete"
|
||||
tools:drawableEnd="@drawable/ic_action_read_later_fill"
|
||||
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
|
||||
android:paddingStart="@dimen/bottom_sheet_content_padding_small" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/wikivoyage_card_divider_color" />
|
||||
|
||||
<include
|
||||
android:id="@+id/shadow"
|
||||
layout="@layout/card_bottom_divider"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<include
|
||||
android:id="@+id/list_item_divider"
|
||||
layout="@layout/list_item_divider"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
|
@ -4002,4 +4002,10 @@
|
|||
<string name="announcement_time_off_route">Abweichung von der Route</string>
|
||||
<string name="announcement_time_arrive">Ankunft am Ziel</string>
|
||||
<string name="announcement_time_approach">Annährung ans Ziel</string>
|
||||
<string name="context_menu_read_full">Vollständig lesen</string>
|
||||
<string name="delete_online_routing_engine">Dieses Online-Routingmodul löschen\?</string>
|
||||
<string name="context_menu_edit_descr">Beschreibung bearbeiten</string>
|
||||
<string name="delete_waypoints">Wegpunkte löschen</string>
|
||||
<string name="copy_to_map_favorites">In Favoriten kopieren</string>
|
||||
<string name="copy_to_map_markers">In Kartenmarkierungen kopieren</string>
|
||||
</resources>
|
|
@ -4000,4 +4000,10 @@
|
|||
<string name="announcement_time_intervals">Interspacoj distancaj kaj tempaj</string>
|
||||
<string name="announcement_time_descr">Tempo de anonco de diversaj voĉaj sciigoj dependas de ilia specoj, nuna naviga kaj implicita naviga rapido.</string>
|
||||
<string name="announcement_time_title">Tempo de anonco</string>
|
||||
<string name="copy_to_map_favorites">Kopii al ŝatataj</string>
|
||||
<string name="delete_online_routing_engine">Ĉu forigi tiun ĉi enretan navigilon\?</string>
|
||||
<string name="context_menu_read_full">Legi pli</string>
|
||||
<string name="context_menu_edit_descr">Redakti priskribon</string>
|
||||
<string name="delete_waypoints">Forigi navigadpunktojn</string>
|
||||
<string name="copy_to_map_markers">Kopii al map‑markoj</string>
|
||||
</resources>
|
|
@ -543,7 +543,7 @@
|
|||
<string name="left_side_navigation">Circolazione a sinistra</string>
|
||||
<string name="left_side_navigation_descr">Per i paesi in cui si guida nella parte sinistra della strada.</string>
|
||||
<string name="unknown_from_location">Posizione di partenza non ancora determinata.</string>
|
||||
<string name="confirm_interrupt_download">Annulla il download del file\?</string>
|
||||
<string name="confirm_interrupt_download">Annulla il download\?</string>
|
||||
<string name="basemap_was_selected_to_download">La mappa di base necessaria per il funzionamento è in coda per il download.</string>
|
||||
<string name="map_online_plugin_is_not_installed">Abilita il plugin \'Mappe Online\' per scegliere altre sorgenti di mappe</string>
|
||||
<string name="map_online_data">Mappe online e a tasselli</string>
|
||||
|
@ -929,7 +929,7 @@
|
|||
<string name="favourites_list_activity">Seleziona Preferito</string>
|
||||
<string name="local_openstreetmap_act_title">Modifiche OSM</string>
|
||||
<string name="download_using_mobile_internet">Non connesso al Wi-Fi. Usare la connessione a Internet attuale per il download\?</string>
|
||||
<string name="cancel_route">Cancellare il percorso\?</string>
|
||||
<string name="cancel_route">Ignora il percorso\?</string>
|
||||
<string name="cancel_navigation">Interrompere la navigazione</string>
|
||||
<string name="clear_destination">Cancella la destinazione</string>
|
||||
<string name="other_location">Altra</string>
|
||||
|
@ -1399,7 +1399,7 @@
|
|||
<string name="shared_string_ellipsis">…</string>
|
||||
<string name="shared_string_ok">Ok</string>
|
||||
<string name="shared_string_cancel">Annulla</string>
|
||||
<string name="shared_string_dismiss">Annulla</string>
|
||||
<string name="shared_string_dismiss">Ignora</string>
|
||||
<string name="shared_string_yes">Sì</string>
|
||||
<string name="shared_string_no">No</string>
|
||||
<string name="shared_string_on">Acceso</string>
|
||||
|
@ -1989,7 +1989,7 @@
|
|||
<string name="first_usage_greeting">Ottieni indicazioni e scopri nuovi luoghi senza una connessione a Internet</string>
|
||||
<string name="search_another_country">Scegli un\'altra regione</string>
|
||||
<string name="skip_map_downloading_desc">Non hai mappe offline installate. Si può scegliere una mappa dalla lista o scaricarle in seguito andando su \'Menù - %1$s\'.</string>
|
||||
<string name="osm_live_payment_desc">Il costo della sottoscrizione verrà addebitato ogni mese. Puoi scegliere di annullare la sottoscrizione su Google Play in ogni momento.</string>
|
||||
<string name="osm_live_payment_desc">La sottoscrizione viene addebitata ogni mese. Puoi annullarla su Google Play in ogni momento.</string>
|
||||
<string name="donation_to_osm">Donazione per la comunità di OpenStreetMap</string>
|
||||
<string name="donation_to_osm_desc">Parte della tua donazione verrà inviata agli utenti che fanno modifiche su OpenStreetMap. Il costo della sottoscrizione rimane inalterato.</string>
|
||||
<string name="osm_live_subscription_desc">La sottoscrizione attiva aggiornamenti orari, quotidiani e settimanali e la possibilità di scaricare senza limiti tutte le mappe del mondo.</string>
|
||||
|
@ -3134,7 +3134,7 @@
|
|||
<string name="coordinates_format_info">Il formato selezionato sarà applicato per tutta l\'app.</string>
|
||||
<string name="pref_selected_by_default_for_profiles">Questa impostazione è selezionata di default per i profili: %s</string>
|
||||
<string name="change_default_settings">Cambia impostazioni</string>
|
||||
<string name="discard_changes">Annulla cambiamenti</string>
|
||||
<string name="discard_changes">Annulla modifiche</string>
|
||||
<string name="apply_to_current_profile">Applica solo a \"%1$s\"</string>
|
||||
<string name="apply_to_all_profiles">Applica a tutti i profili</string>
|
||||
<string name="start_up_message_pref">Messaggio di avvio</string>
|
||||
|
@ -3704,7 +3704,7 @@
|
|||
<string name="use_volume_buttons_as_zoom_descr">Abilita per controllare il livello di zoom della mappa con i pulsanti del volume del dispositivo.</string>
|
||||
<string name="use_volume_buttons_as_zoom">Pulsanti volume come zoom</string>
|
||||
<string name="please_provide_point_name_error">Per favore indica un nome per il punto</string>
|
||||
<string name="quick_action_remove_next_destination_descr">Il punto di destinazione corrente sul percorso verrà eliminato. Se sarà la Destinazione, la navigazione verrà interrotta.</string>
|
||||
<string name="quick_action_remove_next_destination_descr">Elimina la destinazione successiva nel percorso. Se questa è la destinazione finale, la navigazione si fermerà.</string>
|
||||
<string name="search_download_wikipedia_maps">Scarica mappe Wikipedia</string>
|
||||
<string name="plugin_wikipedia_description">Ottieni informazioni sui punti di interesse da Wikipedia. È la tua guida tascabile offline - basta abilitare il plugin Wikipedia e goderti gli articoli sugli oggetti intorno a te.</string>
|
||||
<string name="app_mode_enduro_motorcycle">Moto da enduro</string>
|
||||
|
|
|
@ -3993,4 +3993,12 @@
|
|||
<string name="routing_engine_vehicle_type_cycling_mountain">רכיבת הרים</string>
|
||||
<string name="routing_engine_vehicle_type_cycling_road">רכיבת כביש</string>
|
||||
<string name="routing_engine_vehicle_type_cycling_regular">רכיבה רגילה</string>
|
||||
<string name="routing_engine_vehicle_type_hiking">טיול שטח</string>
|
||||
<string name="routing_engine_vehicle_type_hgv">משאית כבדה</string>
|
||||
<string name="delete_online_routing_engine">למחוק את מנוע הניווט המקוון הזה\?</string>
|
||||
<string name="context_menu_read_full">להציג במלואו</string>
|
||||
<string name="context_menu_edit_descr">עריכת תיאור</string>
|
||||
<string name="delete_waypoints">מחיקת נקודות דרך</string>
|
||||
<string name="copy_to_map_markers">העתקה לסמני המפה</string>
|
||||
<string name="copy_to_map_favorites">העתקה למועדפים</string>
|
||||
</resources>
|
|
@ -2790,7 +2790,7 @@
|
|||
<string name="poi_crop_rice">Вирощується культура: рис</string>
|
||||
<string name="poi_nuclear_explosion_type_cratering_burst">Вид вибуху: неглибокого закладення</string>
|
||||
<string name="poi_provided_for_adult_yes">Послуги надаються дорослим: так</string>
|
||||
<string name="poi_xmas_note">Різдво: нотатка</string>
|
||||
<string name="poi_xmas_note">Різдво: примітка</string>
|
||||
<string name="poi_cuisine_wings">Крильця</string>
|
||||
<string name="poi_cuisine_jamaican">Ямайська</string>
|
||||
<string name="poi_outdoor_seating_pedestrian_zone">Місця на відкритому повітрі: пішохідна зона</string>
|
||||
|
@ -3019,7 +3019,7 @@
|
|||
<string name="poi_drink_wine_yes">Вино: так</string>
|
||||
<string name="poi_vending_drinks_food">Напої і закуски</string>
|
||||
<string name="poi_wetland_saltmarsh">Болото, періодично затоплюване морською водою</string>
|
||||
<string name="poi_note">Нотатка</string>
|
||||
<string name="poi_note">Примітка</string>
|
||||
<string name="poi_crop_flowers">Вирощується культура: квіти</string>
|
||||
<string name="poi_water_heater_no">Водонагрівач: відсутній</string>
|
||||
<string name="poi_free_flying_site_orientation_e">Орієнтація майданчика для вільного польоту: схід (E)</string>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
<string name="switch_to_raster_map_to_see">Для поточної місцевості відсутні векторні автономні мапи. Завантажте їх у \'Налаштуваннях\' (\'Керування файлами мап\') або перемкніться на втулок \'Мережеві мапи\'.</string>
|
||||
<string name="send_files_to_osm">Відправити GPX файли в OSM?</string>
|
||||
<string name="gpx_visibility_txt">Видимість</string>
|
||||
<string name="gpx_tags_txt">Теги</string>
|
||||
<string name="gpx_tags_txt">Мітки</string>
|
||||
<string name="validate_gpx_upload_name_pwd">Для вивантаження GPX-файлів вкажіть ваше ім\'я користувача і пароль в OSM.</string>
|
||||
<string name="default_buttons_support">Підтримка</string>
|
||||
<string name="support_new_features">Підтримати розробку нових функцій</string>
|
||||
|
@ -121,13 +121,13 @@
|
|||
<string name="offline_edition_descr">Якщо ввімкнено редагування в автономному режимі, тоді зміни буде збережено спочатку локально та завантажено за запитом, інакше зміни буде завантажено негайно.</string>
|
||||
<string name="update_poi_does_not_change_indexes">Зміни POI всередині застосунку не впливають на завантажені файли мап - вони зберігаються в окремий файл на Вашому пристрої.</string>
|
||||
<string name="local_openstreetmap_uploading">Вивантаження…</string>
|
||||
<string name="local_openstreetmap_were_uploaded">{0} POI/нотатки вивантажено</string>
|
||||
<string name="local_openstreetmap_were_uploaded">{0} POI/примітки вивантажено</string>
|
||||
<string name="local_openstreetmap_uploadall">Вивантажити усе</string>
|
||||
<string name="local_openstreetmap_upload">Вивантажити правки в OSM</string>
|
||||
<string name="local_openstreetmap_delete">Видалити редагування</string>
|
||||
<string name="local_openstreetmap_descr_title">Асинхронне редагування OSM:</string>
|
||||
<string name="local_openstreetmap_settings">OSM-POI/Нотатки, збережено на пристрої</string>
|
||||
<string name="local_openstreetmap_settings_descr">Перегляд і керування OSM-POI/нотатками, збереженими у базі даних на пристрої.</string>
|
||||
<string name="local_openstreetmap_settings">OSM-POI/примітки, збережено на пристрої</string>
|
||||
<string name="local_openstreetmap_settings_descr">Перегляд і керування OSM-POI/примітками, збереженими у базі даних пристрою.</string>
|
||||
<string name="live_monitoring_interval_descr">Вкажіть інтервал надсилання даних.</string>
|
||||
<string name="live_monitoring_interval">Інтервал надсилання даних</string>
|
||||
<string name="live_monitoring_url_descr">Вкажіть веб-адресу з наступними параметрами: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
|
||||
|
@ -435,7 +435,7 @@
|
|||
<string name="layer_yandex_traffic">Яндекс Пробки</string>
|
||||
<string name="layer_route">Маршрут</string>
|
||||
<string name="shared_string_favorites">Закладки</string>
|
||||
<string name="layer_osm_bugs">Нотатки OSM (мережеві)</string>
|
||||
<string name="layer_osm_bugs">Примітки OSM (мережеві)</string>
|
||||
<string name="layer_poi">POI-накладення…</string>
|
||||
<string name="layer_map">Джерело мапи…</string>
|
||||
<string name="menu_layers">Шари мапи</string>
|
||||
|
@ -597,7 +597,7 @@
|
|||
<string name="update_tile">Оновити мапу</string>
|
||||
<string name="reload_tile">Оновити частину мапи</string>
|
||||
<string name="mark_point">Точка</string>
|
||||
<string name="shared_string_add_to_favorites">Додати в закладки</string>
|
||||
<string name="shared_string_add_to_favorites">Додати до закладок</string>
|
||||
<string name="use_english_names_descr">Вибір між місцевими та англійськими назвами.</string>
|
||||
<string name="use_english_names">Використовувати англійські назви на мапах</string>
|
||||
<string name="app_settings">Налаштування програми</string>
|
||||
|
@ -657,7 +657,7 @@
|
|||
<string name="shared_string_apply">Застосувати</string>
|
||||
<string name="shared_string_add">Додати</string>
|
||||
<string name="shared_string_no">Ні</string>
|
||||
<string name="add_favorite_dialog_top_text">Введіть ім’я Закладки</string>
|
||||
<string name="add_favorite_dialog_top_text">Введіть назву Закладки</string>
|
||||
<string name="add_favorite_dialog_default_favourite_name">Закладка</string>
|
||||
<string name="add_favorite_dialog_favourite_added_template">Точку Закладки \'\'{0}\'\' додано.</string>
|
||||
<string name="favourites_context_menu_edit">Редагувати Закладку</string>
|
||||
|
@ -683,7 +683,7 @@
|
|||
<string name="poi_dialog_opening_hours">Відкрити</string>
|
||||
<string name="poi_dialog_comment">Коментар</string>
|
||||
<string name="poi_dialog_comment_default">Зміна POI</string>
|
||||
<string name="poi_dialog_other_tags_message">Наступні теги POI не можуть бути змінені</string>
|
||||
<string name="poi_dialog_other_tags_message">Всі інші мітки POI не буде змінено</string>
|
||||
<string name="default_buttons_commit">Зберегти</string>
|
||||
<string name="shared_string_clear">Очистити</string>
|
||||
<string name="filter_current_poiButton">Фільтр</string>
|
||||
|
@ -776,7 +776,7 @@
|
|||
<string name="recording_photo_description">Світлина %1$s %2$s</string>
|
||||
<string name="av_def_action_picture">Зробити світлину</string>
|
||||
<string name="recording_context_menu_precord">Зробити світлину</string>
|
||||
<string name="dropbox_plugin_description">Взаємозберігайте треки та звуко/відео-нотатки з Вашим обліковим записом Dropbox.</string>
|
||||
<string name="dropbox_plugin_description">Синхронізуйте треки та звуко/відеопримітки з вашим обліковим записом Dropbox.</string>
|
||||
<string name="dropbox_plugin_name">Втулок Dropbox</string>
|
||||
<string name="intermediate_points_change_order">Змінити порядок</string>
|
||||
<string name="srtm_paid_version_msg">Будь ласка, зверніть увагу на оплату втулка \"Горизонталі\" для підтримки подальшого розвитку.</string>
|
||||
|
@ -795,7 +795,7 @@
|
|||
<string name="recording_unavailable">недоступно</string>
|
||||
<string name="shared_string_control_stop">Зупинити</string>
|
||||
<string name="shared_string_control_start">Почати</string>
|
||||
<string name="map_widget_av_notes">Звуко/відео-нотатки</string>
|
||||
<string name="map_widget_av_notes">Звуко/відеопримітки</string>
|
||||
<string name="osmand_srtm_short_description_80_chars">Втулок OsmAnd для показу горизонталей в автономному режимі</string>
|
||||
<string name="av_use_external_camera">Використовувати програму Камера</string>
|
||||
<string name="av_settings_descr">Налаштування аудіо/відео запису.</string>
|
||||
|
@ -805,8 +805,8 @@
|
|||
<string name="recording_default_name">Запис</string>
|
||||
<string name="av_def_action_choose">За запитом\?</string>
|
||||
<string name="recording_is_recorded">Аудіо/відео зараз записується. Для зупинки натисніть на AV-віджет.</string>
|
||||
<string name="recording_context_menu_arecord">Створити аудіо-нотатку</string>
|
||||
<string name="recording_context_menu_vrecord">Створити відео-нотатку</string>
|
||||
<string name="recording_context_menu_arecord">Створити аудіопримітку</string>
|
||||
<string name="recording_context_menu_vrecord">Створити відеопримітку</string>
|
||||
<string name="recording_context_menu_delete">Вилучити запис</string>
|
||||
<string name="recording_context_menu_play">Грати</string>
|
||||
<string name="map_widget_intermediate_distance">Проміжний пункт призначення</string>
|
||||
|
@ -820,9 +820,9 @@
|
|||
\n
|
||||
\nВсесвітні дані (між 70° на півночі і 70° на півдні) базуються на вимірюваннях SRTM (Shuttle Radar Topography Mission) і ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), даних інструменту відмальовуванню Terra, флагманського супутника системи спостереження Землі від NASA. ASTER — це підсумок спільної роботи NASA, міністерства економіки Японії, міністерства торгівлі і промисловості Японії (METI), агенції космічних систем Японії (J-spacesystems).</string>
|
||||
<string name="map_widget_distancemeasurement">Вимірювання відстаней</string>
|
||||
<string name="map_widget_audionotes">Звуко-нотатки</string>
|
||||
<string name="audionotes_plugin_description">Зробіть звуко/світлино/відео нотатки під час подорожі, використовуючи або кнопку мапи, або контекстне меню розташування.</string>
|
||||
<string name="audionotes_plugin_name">Звуко/відео-нотатки</string>
|
||||
<string name="map_widget_audionotes">Аудіопримітки</string>
|
||||
<string name="audionotes_plugin_description">Робіть звуко/світлино/відео примітки під час подорожі використовуючи кнопку мапи або контекстне меню розташування.</string>
|
||||
<string name="audionotes_plugin_name">Звуко/відеопримітки</string>
|
||||
<string name="index_srtm_parts">частин</string>
|
||||
<string name="index_srtm_ele">Горизонталі</string>
|
||||
<string name="srtm_plugin_description">Цей втулок показує як шар горизонталей, так і шар рельєфу поверх усталених мап OsmAnd. Ця функціональність стане в пригоді спортсменам, туристам, мандрівникам та будь-кому, хто цікавиться структурою рельєфу місцевості. (Зверніть увагу, що дані про горизонталі є окремими від даних про рельєф; додаткові завантаження доступні після задіювання втулку.)
|
||||
|
@ -843,7 +843,7 @@
|
|||
<string name="safe_mode_description">Запустити програму в безпечному режимі (використовує повільніші Android-функції замість власних).</string>
|
||||
<string name="safe_mode">Безпечний режим</string>
|
||||
<string name="native_library_not_running">Програму запущено в безпечному режимі (вимкніть його в \'Налаштуваннях\').</string>
|
||||
<string name="audionotes_location_not_defined">Виберіть \"Використати місцеперебування...\" для прив\'язки нотатки до поточного розташування.</string>
|
||||
<string name="audionotes_location_not_defined">Виберіть \"Використати місцеперебування...\" для прив\'язки примітки до поточного розташування.</string>
|
||||
<string name="background_service_is_enabled_question">Службу OsmAnd у тлі досі запущено. Зупинити її роботу також\?</string>
|
||||
<string name="close_changeset">Закрити набір змін</string>
|
||||
<string name="zxing_barcode_scanner_not_found">Програма \'ZXing Barcode Scanner\' не встановлена. Шукати в Google Play?</string>
|
||||
|
@ -1370,8 +1370,8 @@
|
|||
<string name="navigate_point_northing">Північної широти</string>
|
||||
<string name="shared_string_dismiss">Відхилити</string>
|
||||
<string name="shared_string_audio">Аудіо</string>
|
||||
<string name="share_note">Поділитись нотаткою</string>
|
||||
<string name="notes">A/V нотатки</string>
|
||||
<string name="share_note">Поділитись приміткою</string>
|
||||
<string name="notes">A/V примітки</string>
|
||||
<string name="online_map">Мережева мапа</string>
|
||||
<string name="roads_only">Тільки дороги</string>
|
||||
<string name="free">Вільно %1$s</string>
|
||||
|
@ -1382,7 +1382,7 @@
|
|||
<string name="nautical_maps_missing">Завантажте спеціальну безмережеву мапу, щоб відобразити морські подробиці.</string>
|
||||
<string name="edit_group">Редагувати групу</string>
|
||||
<string name="parking_place">Місце для стоянки</string>
|
||||
<string name="remove_the_tag">ВИЛУЧИТИ ТЕҐ</string>
|
||||
<string name="remove_the_tag">ВИЛУЧИТИ МІТКУ</string>
|
||||
<string name="gps_status">Стан GPS</string>
|
||||
<string name="version_settings_descr">Завантажити нічні збірки.</string>
|
||||
<string name="version_settings">Збірки</string>
|
||||
|
@ -1624,19 +1624,19 @@
|
|||
<string name="osm_save_offline">Зберегти локально</string>
|
||||
<string name="osm_edit_modified_poi">OSM POI відредаговано</string>
|
||||
<string name="osm_edit_deleted_poi">OSM POI видалено</string>
|
||||
<string name="context_menu_item_open_note">Відкрити OSM-нотатку</string>
|
||||
<string name="osm_edit_reopened_note">Відкрити заново OSM-нотатку</string>
|
||||
<string name="osm_edit_commented_note">До OSM-нотатки додано коментар</string>
|
||||
<string name="osm_edit_created_note">Створено OSM-нотатку</string>
|
||||
<string name="osn_bug_name">OSM-нотатка</string>
|
||||
<string name="osn_add_dialog_title">Створити нотатку</string>
|
||||
<string name="context_menu_item_open_note">Відкрити примітку OSM</string>
|
||||
<string name="osm_edit_reopened_note">Повторно відкрити примітку OSM</string>
|
||||
<string name="osm_edit_commented_note">До примітки OSM додано коментар</string>
|
||||
<string name="osm_edit_created_note">Створено примітку OSM</string>
|
||||
<string name="osn_bug_name">Примітка OSM</string>
|
||||
<string name="osn_add_dialog_title">Створити примітку</string>
|
||||
<string name="osn_comment_dialog_title">Додати коментар</string>
|
||||
<string name="osn_reopen_dialog_title">Перевідкрити нотатку</string>
|
||||
<string name="osn_close_dialog_title">Закрити нотатку</string>
|
||||
<string name="osn_add_dialog_success">Нотатку створено</string>
|
||||
<string name="osn_add_dialog_error">Не вдалося створити нотатку.</string>
|
||||
<string name="osn_close_dialog_success">Нотатку закрито</string>
|
||||
<string name="osn_close_dialog_error">Не вдалося закрити нотатку.</string>
|
||||
<string name="osn_reopen_dialog_title">Перевідкрити примітку</string>
|
||||
<string name="osn_close_dialog_title">Закрити примітку</string>
|
||||
<string name="osn_add_dialog_success">Примітку створено</string>
|
||||
<string name="osn_add_dialog_error">Не вдалося створити примітку.</string>
|
||||
<string name="osn_close_dialog_success">Примітку закрито</string>
|
||||
<string name="osn_close_dialog_error">Не вдалося закрити примітку.</string>
|
||||
<string name="shared_string_commit">Підтвердити</string>
|
||||
<string name="context_menu_item_delete_waypoint">Вилучити GPX точку?</string>
|
||||
<string name="context_menu_item_edit_waypoint">Редагувати GPX точку</string>
|
||||
|
@ -1947,8 +1947,8 @@
|
|||
<string name="osm_live_header">Передплата дозволяє щогодини отримувати оновлення для мап по всьому світу.
|
||||
\nЧастина від передплати переводиться спільноті OSM та виплачується кожному землеписцю за його внесок.
|
||||
\nЯкщо Вам подобається OsmAnd та OSM, і хочете підтримати і бути підтриманими ними, це ідеальний спосіб зробити це.</string>
|
||||
<string name="upload_osm_note_description">Надішліть Вашу OSM-нотатку таємно, або скориставшись обліковим записом на OSM.org.</string>
|
||||
<string name="upload_osm_note">Надіслати нотатку в OSM</string>
|
||||
<string name="upload_osm_note_description">Надішліть примітку OSM знеособлено чи скориставшись профілем OpenStreetMap.org.</string>
|
||||
<string name="upload_osm_note">Надіслати примітку в OSM</string>
|
||||
<string name="file_name_containes_illegal_char">Неприпустимі знаки в назві файлу</string>
|
||||
<string name="follow_us">Слідкуйте за нами</string>
|
||||
<string name="access_direction_audio_feedback">Звукові напрямки</string>
|
||||
|
@ -2162,19 +2162,19 @@
|
|||
<string name="quick_action_map_underlay_action">Додати підкладку</string>
|
||||
<string name="quick_action_map_source">Змінити джерело мапи</string>
|
||||
<string name="quick_action_btn_tutorial_descr">Довге натискання з перетягуванням кнопки змінює її розташування на екрані.</string>
|
||||
<string name="quick_action_add_osm_bug">Додати нотатку OSM</string>
|
||||
<string name="quick_action_add_osm_bug">Додати примітку OSM</string>
|
||||
<string name="rendering_value_fine_name">Дуже тонкий</string>
|
||||
<string name="navigate_point_olc">Відкритий код розташування (OLC)</string>
|
||||
<string name="quick_action_take_audio_note">Нова аудіонотатка</string>
|
||||
<string name="quick_action_take_video_note">Нова відеонотатка</string>
|
||||
<string name="quick_action_take_photo_note">Нова фотонотатка</string>
|
||||
<string name="quick_action_take_audio_note">Нова аудіопримітка</string>
|
||||
<string name="quick_action_take_video_note">Нова відеопримітка</string>
|
||||
<string name="quick_action_take_photo_note">Нова фотопримітка</string>
|
||||
<string name="quick_favorites_name_preset">Найменування</string>
|
||||
<string name="quick_action_add_marker_descr">Кнопка для додавання позначки мапи посередині екрану.</string>
|
||||
<string name="quick_action_add_gpx_descr">Натискання на цю кнопку додасть маршрутну точку GPX посередині екрану.</string>
|
||||
<string name="quick_action_take_audio_note_descr">Натискання цієї кнопки додає аудіонотатку посередині екрану.</string>
|
||||
<string name="quick_action_take_video_note_descr">Натискання цієї кнопки додає відеонотатку посередині екрану.</string>
|
||||
<string name="quick_action_take_photo_note_descr">Натискання цієї кнопки додає фотонотатку посередині екрану.</string>
|
||||
<string name="quick_action_add_osm_bug_descr">Натискання цієї кнопки додає OSM-нотатку посередині екрану.</string>
|
||||
<string name="quick_action_take_audio_note_descr">Натискання цієї кнопки додає аудіопримітку посередині екрана.</string>
|
||||
<string name="quick_action_take_video_note_descr">Натискання цієї кнопки додає відеопримітку посередині екрана.</string>
|
||||
<string name="quick_action_take_photo_note_descr">Натискання цієї кнопки додає фотопримітку посередині екрана.</string>
|
||||
<string name="quick_action_add_osm_bug_descr">Натискання цієї кнопки додає примітку OSM посередині екрану.</string>
|
||||
<string name="quick_action_add_poi_descr">Натискання цієї кнопки додає POI посередині екрану.</string>
|
||||
<string name="quick_action_navigation_voice_descr">Перемикач, щоб вимкнути або увімкнути голосові підказки під час навігації.</string>
|
||||
<string name="quick_action_add_parking_descr">Кнопка для додавання місця паркування посередині екрана.</string>
|
||||
|
@ -2212,10 +2212,10 @@
|
|||
<string name="nothing_found">Нічого не знайдено</string>
|
||||
<string name="private_access_routing_req">Місце призначення розташовано в області з приватним доступом. Дозволити доступ до приватних доріг у цій подорожі\?</string>
|
||||
<string name="nothing_found_descr">Змініть пошуковий запит або ж розширте пошуковий радіус.</string>
|
||||
<string name="quick_action_showhide_osmbugs_title">Показати/приховати OSM-нотатки</string>
|
||||
<string name="quick_action_osmbugs_show">Показати OSM-нотатки</string>
|
||||
<string name="quick_action_osmbugs_hide">Приховати OSM-нотатки</string>
|
||||
<string name="quick_action_showhide_osmbugs_descr">Натискання на кнопку дії покаже чи приховає OSM-нотатки на мапі.</string>
|
||||
<string name="quick_action_showhide_osmbugs_title">Показати/приховати примітки OSM</string>
|
||||
<string name="quick_action_osmbugs_show">Показати примітки OSM</string>
|
||||
<string name="quick_action_osmbugs_hide">Приховати примітки OSM</string>
|
||||
<string name="quick_action_showhide_osmbugs_descr">Натискання на кнопку дії покаже чи приховає примітки OSM на мапі.</string>
|
||||
<string name="sorted_by_distance">Відсортоване за відстанню</string>
|
||||
<string name="search_favorites">Пошук у закладках</string>
|
||||
<string name="hillshade_menu_download_descr">Завантажте шар мапи «Пагорби», щоб показати вертикальне затінення.</string>
|
||||
|
@ -2526,9 +2526,9 @@
|
|||
<string name="routing_attr_avoid_ice_roads_fords_description">Уникає льодових доріг і бродів.</string>
|
||||
<string name="make_round_trip_descr">Додати копію початкової точки як місце призначення.</string>
|
||||
<string name="make_round_trip">Зробити кругову подорож</string>
|
||||
<string name="osn_modify_dialog_error">Не вдалося змінити нотатку.</string>
|
||||
<string name="osn_modify_dialog_title">Змінити нотатку</string>
|
||||
<string name="context_menu_item_modify_note">Змінити OSM-нотатку</string>
|
||||
<string name="osn_modify_dialog_error">Не вдалося змінити примітку.</string>
|
||||
<string name="osn_modify_dialog_title">Змінити примітку</string>
|
||||
<string name="context_menu_item_modify_note">Змінити примітку OSM</string>
|
||||
<string name="wrong_input">Неправильний ввід</string>
|
||||
<string name="wrong_format">Неправильний формат</string>
|
||||
<string name="shared_string_road">Дорога</string>
|
||||
|
@ -2576,15 +2576,15 @@
|
|||
<string name="looking_for_tracks_with_waypoints">Пошук треків з шляховими точками</string>
|
||||
<string name="shared_string_more_without_dots">Більше</string>
|
||||
<string name="empty_state_osm_edits">Створити або змінити OSM-об\'єкти</string>
|
||||
<string name="empty_state_osm_edits_descr">Створюйте або змінюйте цікаві точки в OSM, відкривайте або коментуйте OSM-нотатки, а також надсилайте записані GPX-файли.</string>
|
||||
<string name="empty_state_osm_edits_descr">Створюйте або змінюйте OSM POI, відкривайте або коментуйте примітки OSM та надсилайте записані GPX-файли.</string>
|
||||
<string name="shared_string_deleted">Вилучено</string>
|
||||
<string name="shared_string_edited">Відредаговано</string>
|
||||
<string name="shared_string_added">Додано</string>
|
||||
<string name="marker_activated">Позначку %s задіяно.</string>
|
||||
<string name="one_tap_active_descr">Натискання на позначку на мапі перемістить її на перше місце в списку задіяних позначок, не відкриваючи контекстне меню.</string>
|
||||
<string name="one_tap_active">Задіювання одним натисненням</string>
|
||||
<string name="empty_state_av_notes">Робіть нотатки!</string>
|
||||
<string name="empty_state_av_notes_desc">Додайте аудіо, відео або фотонотатку в будь-яку точку на мапі, використовуючи віджет або контекстне меню.</string>
|
||||
<string name="empty_state_av_notes">Робіть примітки!</string>
|
||||
<string name="empty_state_av_notes_desc">Додайте аудіо, відео або фотопримітку в будь-яку точку на мапі використовуючи віджет або контекстне меню.</string>
|
||||
<string name="notes_by_date">Примітки за датою</string>
|
||||
<string name="by_date">За датою</string>
|
||||
<string name="by_type">За типом</string>
|
||||
|
@ -2620,14 +2620,14 @@
|
|||
<string name="last_intermediate_dest_description">Додає проміжну зупинку</string>
|
||||
<string name="first_intermediate_dest_description">Додає першу зупинку</string>
|
||||
<string name="subsequent_dest_description">Пересунути призначення далі і створити його</string>
|
||||
<string name="show_closed_notes">Показати закриті нотатки</string>
|
||||
<string name="show_closed_notes">Показати закриті примітки</string>
|
||||
<string name="switch_osm_notes_visibility_desc">Показати чи приховати примітки OSM на мапі.</string>
|
||||
<string name="gpx_file_desc">GPX — підходить для експорту в JOSM та інші OSM-редактори.</string>
|
||||
<string name="osc_file_desc">OSC — підходить для експорту в OSM.</string>
|
||||
<string name="shared_string_gpx_file">GPX-файл</string>
|
||||
<string name="osc_file">OSC-файл</string>
|
||||
<string name="choose_file_type">Виберіть тип файлу</string>
|
||||
<string name="osm_edits_export_desc">Виберіть вид експорту: OSM-нотатки, POI чи і те і те.</string>
|
||||
<string name="osm_edits_export_desc">Виберіть вид експорту: примітки OSM, POI чи і те і те.</string>
|
||||
<string name="all_data">Усі дані</string>
|
||||
<string name="osm_notes">Примітки OSM</string>
|
||||
<string name="will_open_tomorrow_at">Відкриється завтра о</string>
|
||||
|
@ -2844,7 +2844,7 @@
|
|||
<string name="routeInfo_steepness_name">Крутість</string>
|
||||
<string name="run_full_osmand_header">Запустити OsmAnd\?</string>
|
||||
<string name="shared_string_walk">Пішки</string>
|
||||
<string name="save_poi_value_exceed_length">Довжина тегу \"%s\" має бути менше 255 символів.</string>
|
||||
<string name="save_poi_value_exceed_length">Довжина мітки \"%s\" має бути менше 255 символів.</string>
|
||||
<string name="public_transport_warning_descr_blog">Докладніше про те, як OsmAnd розраховує маршрути, читайте в нашому деннику.</string>
|
||||
<string name="public_transport_warning_title">Навігація громадським транспортом на даний час проходить тестування, можливі помилки та неточності.</string>
|
||||
<string name="add_intermediate">Додати проміжну точку</string>
|
||||
|
@ -3343,9 +3343,9 @@
|
|||
<string name="live_monitoring">Мережеве відстеження</string>
|
||||
<string name="save_track_logging_accuracy">Точність журналювання</string>
|
||||
<string name="tracks_view_descr">Ви можете знайти всі записи в %1$s або в теці OsmAnd за допомогою файлового провідника.</string>
|
||||
<string name="multimedia_notes_view_descr">Ваші нотатки OSM розміщено в %1$s.</string>
|
||||
<string name="video_notes">Відеонотатки</string>
|
||||
<string name="photo_notes">Фотонотатки</string>
|
||||
<string name="multimedia_notes_view_descr">Ваші примітки OSM розміщено в %1$s.</string>
|
||||
<string name="video_notes">Відеопримітки</string>
|
||||
<string name="photo_notes">Фотопримітки</string>
|
||||
<string name="route_recalculation">Перерахунок маршруту</string>
|
||||
<string name="accessibility_announce">Оголошення</string>
|
||||
<string name="login_and_pass">Ім\'я користувача і пароль</string>
|
||||
|
@ -3617,7 +3617,7 @@
|
|||
<string name="quick_action_show_hide_transport">Показати чи приховати громадський транспорт</string>
|
||||
<string name="quick_action_transport_descr">Кнопка показу або приховування громадського транспорту на мапі.</string>
|
||||
<string name="create_edit_poi">Створити чи змінити POI</string>
|
||||
<string name="add_edit_favorite">Додати чи змінити вибране</string>
|
||||
<string name="add_edit_favorite">Додати чи змінити закладку</string>
|
||||
<string name="reset_deafult_order">Відновити усталене впорядкування</string>
|
||||
<string name="back_to_editing">Повернутися до редагування</string>
|
||||
<string name="additional_actions_descr">Ви можете отримати доступ до цих дій, торкнувшись кнопки “%1$s”.</string>
|
||||
|
@ -3999,4 +3999,10 @@
|
|||
<string name="routing_engine_vehicle_type_mtb">Гірський велосипед</string>
|
||||
<string name="message_server_error">Помилка сервера: %1$s</string>
|
||||
<string name="message_name_is_already_exists">Назва вже існує</string>
|
||||
<string name="delete_online_routing_engine">Видалити цей рушій мережної маршрутизації\?</string>
|
||||
<string name="context_menu_read_full">Читати повністю</string>
|
||||
<string name="context_menu_edit_descr">Змінити опис</string>
|
||||
<string name="delete_waypoints">Видалити маршрутні точки</string>
|
||||
<string name="copy_to_map_markers">Копіювати до позначок мапи</string>
|
||||
<string name="copy_to_map_favorites">Копіювати до закладок</string>
|
||||
</resources>
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
-->
|
||||
|
||||
<string name="toast_select_edits_for_upload">Select edits for upload</string>
|
||||
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
|
||||
<string name="uploading_count">Uploading %1$d of %2$d</string>
|
||||
<string name="upload_photo_completed">Upload completed</string>
|
||||
<string name="upload_photo">Uploading</string>
|
||||
<string name="copy_to_map_favorites">Copy to favorites</string>
|
||||
<string name="copy_to_map_markers">Copy to map markers</string>
|
||||
<string name="delete_waypoints">Delete waypoints</string>
|
||||
|
@ -2439,7 +2444,7 @@
|
|||
<string name="average">Average</string>
|
||||
<string name="of">%1$d of %2$d</string>
|
||||
<string name="ascent_descent">Ascent/Descent</string>
|
||||
<string name="moving_time">Moving time</string>
|
||||
<string name="moving_time">Time in motion</string>
|
||||
<string name="max_min">Max/Min</string>
|
||||
<string name="min_max">Min/Max</string>
|
||||
<string name="index_tours">Tours</string>
|
||||
|
|
|
@ -636,7 +636,7 @@ public class UiUtilities {
|
|||
int activeDisableColor = getColorWithAlpha(activeColor, 0.25f);
|
||||
ColorStateList activeCsl = new ColorStateList(states, new int[] {activeColor, activeDisableColor});
|
||||
int inactiveColor = ContextCompat.getColor(ctx, nightMode ? R.color.icon_color_default_dark : R.color.icon_color_secondary_light);
|
||||
ColorStateList inactiveCsl = new ColorStateList(states, new int[] {inactiveColor, inactiveColor});
|
||||
ColorStateList inactiveCsl = new ColorStateList(states, new int[] {activeDisableColor, inactiveColor});
|
||||
slider.setTrackActiveTintList(activeCsl);
|
||||
slider.setTrackInactiveTintList(inactiveCsl);
|
||||
slider.setHaloTintList(activeCsl);
|
||||
|
|
|
@ -70,7 +70,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
|||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OnDismissDialogFragmentListener;
|
||||
import net.osmand.plus.OsmAndConstants;
|
||||
import net.osmand.plus.OsmAndLocationProvider;
|
||||
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
|
||||
import net.osmand.plus.OsmAndLocationSimulation;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
@ -1201,7 +1200,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
|||
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path);
|
||||
}
|
||||
|
||||
TrackAppearanceFragment.showInstance(this, selectedGpxFile);
|
||||
TrackAppearanceFragment.showInstance(this, selectedGpxFile, null);
|
||||
} else if (toShow instanceof QuadRect) {
|
||||
QuadRect qr = (QuadRect) toShow;
|
||||
mapView.fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
|
||||
|
@ -1568,6 +1567,17 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
|||
}
|
||||
}
|
||||
|
||||
public boolean shouldHideTopControls() {
|
||||
boolean hideTopControls = !mapContextMenu.shouldShowTopControls();
|
||||
|
||||
TrackMenuFragment fragment = getTrackMenuFragment();
|
||||
if (fragment != null) {
|
||||
hideTopControls = hideTopControls || !fragment.shouldShowTopControls();
|
||||
}
|
||||
|
||||
return hideTopControls;
|
||||
}
|
||||
|
||||
public OsmandMapTileView getMapView() {
|
||||
return mapView;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
|
||||
public interface ContextMenuFragmentListener {
|
||||
void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated);
|
||||
void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState);
|
||||
void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState);
|
||||
void onContextMenuDismiss(@NonNull ContextMenuFragment fragment);
|
||||
}
|
||||
|
||||
|
@ -815,7 +815,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
|
||||
ContextMenuFragmentListener listener = this.listener;
|
||||
if (listener != null) {
|
||||
listener.onContextMenuStateChanged(this, newMenuState);
|
||||
listener.onContextMenuStateChanged(this, newMenuState, currentMenuState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -946,6 +946,11 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
protected void runLayoutListener() {
|
||||
runLayoutListener(null);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
protected void runLayoutListener(final Runnable runnable) {
|
||||
if (view != null) {
|
||||
ViewTreeObserver vto = view.getViewTreeObserver();
|
||||
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
|
@ -971,7 +976,11 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
|
||||
ContextMenuFragmentListener listener = ContextMenuFragment.this.listener;
|
||||
if (listener != null) {
|
||||
listener.onContextMenuStateChanged(ContextMenuFragment.this, getCurrentMenuState());
|
||||
int menuState = getCurrentMenuState();
|
||||
listener.onContextMenuStateChanged(ContextMenuFragment.this, menuState, menuState);
|
||||
}
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ public abstract class ContextMenuScrollFragment extends ContextMenuFragment impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) {
|
||||
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState) {
|
||||
updateMapControlsVisibility(menuState);
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,18 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
dismissButtonStringRes = stringRes;
|
||||
}
|
||||
|
||||
protected int getDismissButtonHeight(){
|
||||
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small);
|
||||
}
|
||||
|
||||
protected int getRightButtonHeight(){
|
||||
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small);
|
||||
}
|
||||
|
||||
protected int getThirdButtonHeight(){
|
||||
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small);
|
||||
}
|
||||
|
||||
protected DialogButtonType getDismissButtonType() {
|
||||
return DialogButtonType.SECONDARY;
|
||||
}
|
||||
|
@ -360,6 +372,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
|
||||
private void setupDismissButton() {
|
||||
dismissButton = buttonsContainer.findViewById(R.id.dismiss_button);
|
||||
dismissButton.getLayoutParams().height = getDismissButtonHeight();
|
||||
int buttonTextId = getDismissButtonTextId();
|
||||
if (buttonTextId != DEFAULT_VALUE) {
|
||||
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), buttonTextId);
|
||||
|
@ -376,6 +389,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
|
||||
private void setupRightButton() {
|
||||
rightButton = buttonsContainer.findViewById(R.id.right_bottom_button);
|
||||
rightButton.getLayoutParams().height = getRightButtonHeight();
|
||||
int buttonTextId = getRightBottomButtonTextId();
|
||||
if (buttonTextId != DEFAULT_VALUE) {
|
||||
UiUtilities.setupDialogButton(nightMode, rightButton, getRightBottomButtonType(), buttonTextId);
|
||||
|
@ -398,6 +412,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
|||
|
||||
protected void setupThirdButton() {
|
||||
thirdButton = buttonsContainer.findViewById(R.id.third_button);
|
||||
thirdButton.getLayoutParams().height = getThirdButtonHeight();
|
||||
int buttonTextId = getThirdBottomButtonTextId();
|
||||
if (buttonTextId != DEFAULT_VALUE) {
|
||||
UiUtilities.setupDialogButton(nightMode, thirdButton, getThirdBottomButtonType(), buttonTextId);
|
||||
|
|
|
@ -99,7 +99,9 @@ public class RenameFileBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
}
|
||||
|
||||
private void updateFileName(String name) {
|
||||
if (!Algorithms.isEmpty(name) && ILLEGAL_FILE_NAME_CHARACTERS.matcher(name).find()) {
|
||||
if (Algorithms.isBlank(name)) {
|
||||
nameTextBox.setError(getString(R.string.empty_filename));
|
||||
} else if (ILLEGAL_FILE_NAME_CHARACTERS.matcher(name).find()) {
|
||||
nameTextBox.setError(getString(R.string.file_name_containes_illegal_char));
|
||||
} else {
|
||||
selectedFileName = name;
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
package net.osmand.plus.dialogs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
|
||||
import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener;
|
||||
|
||||
public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragment implements UploadPhotosListener {
|
||||
|
||||
public static final String TAG = UploadPhotoProgressBottomSheet.class.getSimpleName();
|
||||
|
||||
private ProgressBar progressBar;
|
||||
private TextView uploadedPhotosTitle;
|
||||
private TextView uploadedPhotosCounter;
|
||||
|
||||
private OnDismissListener onDismissListener;
|
||||
|
||||
private int progress;
|
||||
private int maxProgress;
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
Context context = requireContext();
|
||||
LayoutInflater inflater = UiUtilities.getInflater(context, nightMode);
|
||||
View view = inflater.inflate(R.layout.bottom_sheet_with_progress_bar, null);
|
||||
|
||||
uploadedPhotosTitle = view.findViewById(R.id.title);
|
||||
uploadedPhotosCounter = view.findViewById(R.id.description);
|
||||
progressBar = view.findViewById(R.id.progress_bar);
|
||||
progressBar.setMax(maxProgress);
|
||||
String titleProgress = getString(progress == maxProgress? R.string.upload_photo_completed: R.string.upload_photo);
|
||||
String descriptionProgress;
|
||||
if (progress == maxProgress) {
|
||||
descriptionProgress = getString(R.string.uploaded_count, progress, maxProgress);
|
||||
} else {
|
||||
descriptionProgress = getString(R.string.uploading_count, progress, maxProgress);
|
||||
}
|
||||
|
||||
BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder()
|
||||
.setDescription(descriptionProgress)
|
||||
.setTitle(titleProgress)
|
||||
.setCustomView(view)
|
||||
.create();
|
||||
items.add(descriptionItem);
|
||||
|
||||
updateProgress(progress);
|
||||
|
||||
int padding = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
|
||||
items.add(new DividerSpaceItem(context, padding));
|
||||
}
|
||||
|
||||
public void setMaxProgress(int maxProgress) {
|
||||
this.maxProgress = maxProgress;
|
||||
}
|
||||
|
||||
public void setOnDismissListener(OnDismissListener onDismissListener) {
|
||||
this.onDismissListener = onDismissListener;
|
||||
}
|
||||
|
||||
private void updateProgress(int progress) {
|
||||
progressBar.setProgress(progress);
|
||||
uploadedPhotosCounter.setText((getString(R.string.uploading_count, progress, maxProgress)));
|
||||
uploadedPhotosTitle.setText(progress == maxProgress ? R.string.upload_photo_completed : R.string.upload_photo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uploadPhotosProgressUpdate(int progress) {
|
||||
this.progress = progress;
|
||||
updateProgress(progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uploadPhotosFinished() {
|
||||
updateProgress(maxProgress);
|
||||
if (progress == maxProgress) {
|
||||
uploadedPhotosCounter.setText((getString(R.string.uploaded_count, progress, maxProgress)));
|
||||
setDismissButtonTextId(R.string.shared_string_close);
|
||||
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(@NonNull DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
FragmentActivity activity = getActivity();
|
||||
if (onDismissListener != null && activity != null && !activity.isChangingConfigurations()) {
|
||||
onDismissListener.onDismiss(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) {
|
||||
UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet();
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.setMaxProgress(maxProgress);
|
||||
fragment.setOnDismissListener(listener);
|
||||
fragmentManager.beginTransaction()
|
||||
.add(fragment, UploadPhotoProgressBottomSheet.TAG)
|
||||
.commitAllowingStateLoss();
|
||||
|
||||
return fragment;
|
||||
}
|
||||
}
|
|
@ -22,18 +22,17 @@ import net.osmand.data.FavouritePoint;
|
|||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.data.TransportStop;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.mapmarkers.MapMarker;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
||||
import net.osmand.plus.TargetPointsHelper.TargetPointChangedListener;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment.ContextMenuItemClickListener;
|
||||
import net.osmand.plus.mapcontextmenu.MenuController.ContextMenuToolbarController;
|
||||
import net.osmand.plus.mapcontextmenu.MenuController.MenuState;
|
||||
import net.osmand.plus.mapcontextmenu.MenuController.MenuType;
|
||||
|
@ -47,12 +46,14 @@ import net.osmand.plus.mapcontextmenu.editors.RtePtEditor;
|
|||
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor;
|
||||
import net.osmand.plus.mapcontextmenu.other.MapMultiSelectionMenu;
|
||||
import net.osmand.plus.mapcontextmenu.other.ShareMenu;
|
||||
import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment.ContextMenuItemClickListener;
|
||||
import net.osmand.plus.mapmarkers.MapMarker;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener;
|
||||
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.transport.TransportStopRoute;
|
||||
import net.osmand.plus.views.layers.ContextMenuLayer;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.layers.ContextMenuLayer;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -570,18 +571,21 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL
|
|||
public void updateControlsVisibility(boolean menuVisible) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
int topControlsVisibility = shouldShowTopControls(menuVisible) ? View.VISIBLE : View.GONE;
|
||||
mapActivity.findViewById(R.id.map_center_info).setVisibility(topControlsVisibility);
|
||||
mapActivity.findViewById(R.id.map_left_widgets_panel).setVisibility(topControlsVisibility);
|
||||
mapActivity.findViewById(R.id.map_right_widgets_panel).setVisibility(topControlsVisibility);
|
||||
|
||||
int bottomControlsVisibility = shouldShowBottomControls(menuVisible) ? View.VISIBLE : View.GONE;
|
||||
mapActivity.findViewById(R.id.bottom_controls_container).setVisibility(bottomControlsVisibility);
|
||||
|
||||
mapActivity.refreshMap();
|
||||
boolean topControlsVisible = shouldShowTopControls(menuVisible);
|
||||
boolean bottomControlsVisible = shouldShowBottomControls(menuVisible);
|
||||
updateControlsVisibility(mapActivity, topControlsVisible, bottomControlsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateControlsVisibility(@NonNull MapActivity mapActivity, boolean topControlsVisible, boolean bottomControlsVisible) {
|
||||
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_center_info), topControlsVisible);
|
||||
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_left_widgets_panel), topControlsVisible);
|
||||
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_right_widgets_panel), topControlsVisible);
|
||||
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.bottom_controls_container), bottomControlsVisible);
|
||||
|
||||
mapActivity.refreshMap();
|
||||
}
|
||||
|
||||
public boolean shouldShowTopControls() {
|
||||
return shouldShowTopControls(isVisible());
|
||||
}
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
package net.osmand.plus.mapcontextmenu;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Build;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
|
@ -39,14 +36,12 @@ import androidx.core.content.ContextCompat;
|
|||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.osm.PoiCategory;
|
||||
import net.osmand.osm.PoiType;
|
||||
import net.osmand.osm.io.NetworkUtils;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
|
@ -54,6 +49,7 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.ActivityResultListener;
|
||||
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard;
|
||||
|
@ -79,13 +75,6 @@ import net.osmand.plus.widgets.tools.ClickableSpanTouchListener;
|
|||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -99,8 +88,6 @@ import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCa
|
|||
public class MenuBuilder {
|
||||
|
||||
private static final int PICK_IMAGE = 1231;
|
||||
private static final int MAX_IMAGE_LENGTH = 2048;
|
||||
private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class);
|
||||
public static final float SHADOW_HEIGHT_TOP_DP = 17f;
|
||||
public static final int TITLE_LIMIT = 60;
|
||||
protected static final String[] arrowChars = new String[] {"=>", " - "};
|
||||
|
@ -133,7 +120,6 @@ public class MenuBuilder {
|
|||
private String preferredMapLang;
|
||||
private String preferredMapAppLang;
|
||||
private boolean transliterateNames;
|
||||
private View view;
|
||||
private View photoButton;
|
||||
|
||||
private final OpenDBAPI openDBAPI = new OpenDBAPI();
|
||||
|
@ -270,7 +256,6 @@ public class MenuBuilder {
|
|||
}
|
||||
|
||||
public void build(View view) {
|
||||
this.view = view;
|
||||
firstRow = true;
|
||||
hidden = false;
|
||||
buildTopInternal(view);
|
||||
|
@ -425,7 +410,7 @@ public class MenuBuilder {
|
|||
if (false) {
|
||||
AddPhotosBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager());
|
||||
} else {
|
||||
registerResultListener(view);
|
||||
registerResultListener();
|
||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
||||
final String name = app.getSettings().OPR_USERNAME.get();
|
||||
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||
|
@ -443,6 +428,9 @@ public class MenuBuilder {
|
|||
Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
if (Build.VERSION.SDK_INT > 18) {
|
||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
}
|
||||
mapActivity.startActivityForResult(Intent.createChooser(intent,
|
||||
mapActivity.getString(R.string.select_picture)), PICK_IMAGE);
|
||||
}
|
||||
|
@ -472,132 +460,33 @@ public class MenuBuilder {
|
|||
false, null, false);
|
||||
}
|
||||
|
||||
private void registerResultListener(final View view) {
|
||||
mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new ActivityResultListener.
|
||||
OnActivityResultListener() {
|
||||
private void registerResultListener() {
|
||||
mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new OnActivityResultListener() {
|
||||
@Override
|
||||
public void onResult(int resultCode, Intent resultData) {
|
||||
if (resultData != null) {
|
||||
handleSelectedImage(view, resultData.getData());
|
||||
List<Uri> imagesUri = new ArrayList<>();
|
||||
Uri data = resultData.getData();
|
||||
if (data != null) {
|
||||
imagesUri.add(data);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
ClipData clipData = resultData.getClipData();
|
||||
if (clipData != null) {
|
||||
for (int i = 0; i < clipData.getItemCount(); i++) {
|
||||
Uri uri = resultData.getClipData().getItemAt(i).getUri();
|
||||
if (uri != null) {
|
||||
imagesUri.add(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, getLatLon(), placeId, getAdditionalCardParams(), imageCardListener));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void handleSelectedImage(final View view, final Uri uri) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = app.getContentResolver().openInputStream(uri);
|
||||
if (inputStream != null) {
|
||||
uploadImageToPlace(inputStream);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error(e);
|
||||
String str = app.getString(R.string.cannot_upload_image);
|
||||
showToastMessage(str);
|
||||
} finally {
|
||||
Algorithms.closeStream(inputStream);
|
||||
}
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
private void uploadImageToPlace(InputStream image) {
|
||||
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
|
||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
||||
// all these should be constant
|
||||
String url = baseUrl + "api/ipfs/image";
|
||||
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
|
||||
if (response != null) {
|
||||
int res = 0;
|
||||
try {
|
||||
StringBuilder error = new StringBuilder();
|
||||
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||
String username = app.getSettings().OPR_USERNAME.get();
|
||||
res = openDBAPI.uploadImage(
|
||||
placeId,
|
||||
baseUrl,
|
||||
privateKey,
|
||||
username,
|
||||
response, error);
|
||||
if (res != 200) {
|
||||
showToastMessage(error.toString());
|
||||
} else {
|
||||
//ok, continue
|
||||
}
|
||||
} catch (FailedVerificationException e) {
|
||||
LOG.error(e);
|
||||
checkTokenAndShowScreen();
|
||||
}
|
||||
if (res != 200) {
|
||||
//image was uploaded but not added to blockchain
|
||||
checkTokenAndShowScreen();
|
||||
} else {
|
||||
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
|
||||
showToastMessage(str);
|
||||
//refresh the image
|
||||
execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), imageCardListener));
|
||||
}
|
||||
} else {
|
||||
checkTokenAndShowScreen();
|
||||
}
|
||||
}
|
||||
|
||||
private void showToastMessage(final String str) {
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(mapActivity.getBaseContext(), str, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//This method runs on non main thread
|
||||
private void checkTokenAndShowScreen() {
|
||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
||||
final String name = app.getSettings().OPR_USERNAME.get();
|
||||
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
|
||||
String str = app.getString(R.string.cannot_upload_image);
|
||||
showToastMessage(str);
|
||||
} else {
|
||||
app.runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
OprStartFragment.showInstance(mapActivity.getSupportFragmentManager());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] compressImageToJpeg(InputStream image) {
|
||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(image);
|
||||
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int h = bmp.getHeight();
|
||||
int w = bmp.getWidth();
|
||||
boolean scale = false;
|
||||
while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) {
|
||||
w = w / 2;
|
||||
h = h / 2;
|
||||
scale = true;
|
||||
}
|
||||
if (scale) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(w, h);
|
||||
Bitmap resizedBitmap = Bitmap.createBitmap(
|
||||
bmp, 0, 0, w, h, matrix, false);
|
||||
bmp.recycle();
|
||||
bmp = resizedBitmap;
|
||||
}
|
||||
bmp.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
private void startLoadingImages() {
|
||||
if (onlinePhotoCardsRow == null) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
package net.osmand.plus.mapcontextmenu;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Matrix;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.osm.io.NetworkUtils;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.dialogs.UploadPhotoProgressBottomSheet;
|
||||
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask;
|
||||
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
|
||||
import net.osmand.plus.openplacereviews.OPRConstants;
|
||||
import net.osmand.plus.openplacereviews.OprStartFragment;
|
||||
import net.osmand.plus.osmedit.opr.OpenDBAPI;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(UploadPhotosAsyncTask.class);
|
||||
|
||||
private static final int MAX_IMAGE_LENGTH = 2048;
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final WeakReference<MapActivity> activityRef;
|
||||
private UploadPhotosListener listener;
|
||||
|
||||
private final OpenDBAPI openDBAPI = new OpenDBAPI();
|
||||
private final LatLon latLon;
|
||||
private final List<Uri> data;
|
||||
private final String[] placeId;
|
||||
private final Map<String, String> params;
|
||||
private final GetImageCardsListener imageCardListener;
|
||||
|
||||
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId,
|
||||
Map<String, String> params, GetImageCardsListener imageCardListener) {
|
||||
app = (OsmandApplication) activity.getApplicationContext();
|
||||
activityRef = new WeakReference<>(activity);
|
||||
this.data = data;
|
||||
this.latLon = latLon;
|
||||
this.params = params;
|
||||
this.placeId = placeId;
|
||||
this.imageCardListener = imageCardListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
FragmentActivity activity = activityRef.get();
|
||||
if (AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||
FragmentManager manager = activity.getSupportFragmentManager();
|
||||
listener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
cancel(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... values) {
|
||||
if (listener != null) {
|
||||
listener.uploadPhotosProgressUpdate(values[0]);
|
||||
}
|
||||
}
|
||||
|
||||
protected Void doInBackground(Void... uris) {
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
Uri uri = data.get(i);
|
||||
handleSelectedImage(uri);
|
||||
publishProgress(i + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if (listener != null) {
|
||||
listener.uploadPhotosFinished();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSelectedImage(final Uri uri) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = app.getContentResolver().openInputStream(uri);
|
||||
if (inputStream != null) {
|
||||
uploadImageToPlace(inputStream);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error(e);
|
||||
app.showToastMessage(R.string.cannot_upload_image);
|
||||
} finally {
|
||||
Algorithms.closeStream(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadImageToPlace(InputStream image) {
|
||||
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
|
||||
final String baseUrl = OPRConstants.getBaseUrl(app);
|
||||
// all these should be constant
|
||||
String url = baseUrl + "api/ipfs/image";
|
||||
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
|
||||
if (response != null) {
|
||||
int res = 0;
|
||||
try {
|
||||
StringBuilder error = new StringBuilder();
|
||||
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||
String username = app.getSettings().OPR_USERNAME.get();
|
||||
res = openDBAPI.uploadImage(
|
||||
placeId,
|
||||
baseUrl,
|
||||
privateKey,
|
||||
username,
|
||||
response, error);
|
||||
if (res != 200) {
|
||||
app.showToastMessage(error.toString());
|
||||
} else {
|
||||
//ok, continue
|
||||
}
|
||||
} catch (FailedVerificationException e) {
|
||||
LOG.error(e);
|
||||
checkTokenAndShowScreen();
|
||||
}
|
||||
if (res != 200) {
|
||||
//image was uploaded but not added to blockchain
|
||||
checkTokenAndShowScreen();
|
||||
} else {
|
||||
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
|
||||
app.showToastMessage(str);
|
||||
//refresh the image
|
||||
|
||||
MapActivity activity = activityRef.get();
|
||||
if (activity != null) {
|
||||
MenuBuilder.execute(new GetImageCardsTask(activity, latLon, params, imageCardListener));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
checkTokenAndShowScreen();
|
||||
}
|
||||
}
|
||||
|
||||
//This method runs on non main thread
|
||||
private void checkTokenAndShowScreen() {
|
||||
String baseUrl = OPRConstants.getBaseUrl(app);
|
||||
String name = app.getSettings().OPR_USERNAME.get();
|
||||
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
|
||||
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
|
||||
app.showToastMessage(R.string.cannot_upload_image);
|
||||
} else {
|
||||
app.runInUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MapActivity activity = activityRef.get();
|
||||
if (activity != null) {
|
||||
OprStartFragment.showInstance(activity.getSupportFragmentManager());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] compressImageToJpeg(InputStream image) {
|
||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(image);
|
||||
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int h = bmp.getHeight();
|
||||
int w = bmp.getWidth();
|
||||
boolean scale = false;
|
||||
while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) {
|
||||
w = w / 2;
|
||||
h = h / 2;
|
||||
scale = true;
|
||||
}
|
||||
if (scale) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(w, h);
|
||||
Bitmap resizedBitmap = Bitmap.createBitmap(
|
||||
bmp, 0, 0, w, h, matrix, false);
|
||||
bmp.recycle();
|
||||
bmp = resizedBitmap;
|
||||
}
|
||||
bmp.compress(Bitmap.CompressFormat.JPEG, 90, os);
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
public interface UploadPhotosListener {
|
||||
|
||||
void uploadPhotosProgressUpdate(int progress);
|
||||
|
||||
void uploadPhotosFinished();
|
||||
|
||||
}
|
||||
}
|
|
@ -42,9 +42,8 @@ public class SelectedGpxMenuController extends MenuController {
|
|||
leftTitleButtonController = new TitleButtonController() {
|
||||
@Override
|
||||
public void buttonPressed() {
|
||||
SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile();
|
||||
mapActivity.getContextMenu().hide(false);
|
||||
TrackMenuFragment.showInstance(mapActivity, selectedGpxFile.getGpxFile().path, selectedGpxFile.isShowCurrentTrack());
|
||||
mapContextMenu.hide(false);
|
||||
TrackMenuFragment.showInstance(mapActivity, selectedGpxPoint.getSelectedGpxFile());
|
||||
}
|
||||
};
|
||||
leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track);
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.os.Bundle;
|
|||
import android.text.SpannableString;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.ImageView;
|
||||
|
@ -18,10 +19,12 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.slider.RangeSlider;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.NavigationService;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
@ -49,9 +52,9 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
|
||||
private ImageView upDownBtn;
|
||||
private SwitchCompat confirmEveryRun;
|
||||
private RangeSlider intervalSlider;
|
||||
private TextView intervalValueView;
|
||||
private LinearLayout container;
|
||||
private View divider;
|
||||
private boolean infoExpanded;
|
||||
|
||||
@Override
|
||||
|
@ -87,13 +90,15 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
if (mapActivity != null) {
|
||||
hide();
|
||||
SelectedGpxFile selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
|
||||
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile);
|
||||
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile, TripRecordingBottomSheet.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
divider = itemView.findViewById(R.id.second_divider);
|
||||
LinearLayout expandHideIntervalContainer = itemView.findViewById(R.id.interval_view_container);
|
||||
upDownBtn = itemView.findViewById(R.id.up_down_button);
|
||||
upDownBtn.setOnClickListener(new View.OnClickListener() {
|
||||
expandHideIntervalContainer.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -108,8 +113,11 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
updateIntervalLegend();
|
||||
|
||||
container = itemView.findViewById(R.id.always_ask_and_range_slider_container);
|
||||
intervalSlider = itemView.findViewById(R.id.interval_slider);
|
||||
RangeSlider intervalSlider = itemView.findViewById(R.id.interval_slider);
|
||||
intervalSlider.setValueTo(secondsLength + minutesLength - 1);
|
||||
int currentModeColorRes = app.getSettings().getApplicationMode().getIconColorInfo().getColor(nightMode);
|
||||
int currentModeColor = ContextCompat.getColor(app, currentModeColorRes);
|
||||
UiUtilities.setupSlider(intervalSlider, nightMode, currentModeColor, true);
|
||||
container.setVisibility(View.GONE);
|
||||
intervalSlider.addOnChangeListener(new RangeSlider.OnChangeListener() {
|
||||
|
||||
|
@ -126,6 +134,7 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
updateIntervalLegend();
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < secondsLength + minutesLength; i++) {
|
||||
if (i < secondsLength) {
|
||||
if (settings.SAVE_GLOBAL_TRACK_INTERVAL.get() <= SECONDS[i] * 1000) {
|
||||
|
@ -151,13 +160,15 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
}
|
||||
});
|
||||
|
||||
SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button);
|
||||
final SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button);
|
||||
showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null);
|
||||
showTrackOnMapButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
|
||||
View basicItem = itemView.findViewById(R.id.basic_item_body);
|
||||
basicItem.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), isChecked, false);
|
||||
public void onClick(View v) {
|
||||
boolean checked = !showTrackOnMapButton.isChecked();
|
||||
showTrackOnMapButton.setChecked(checked);
|
||||
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), checked, false);
|
||||
}
|
||||
});
|
||||
UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT);
|
||||
|
@ -217,6 +228,14 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
|
||||
private void toggleInfoView() {
|
||||
infoExpanded = !infoExpanded;
|
||||
ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) divider.getLayoutParams();
|
||||
final int dp8 = AndroidUtils.dpToPx(app, 8f);
|
||||
final int dp16 = AndroidUtils.dpToPx(app, 16f);
|
||||
if (infoExpanded) {
|
||||
AndroidUtils.setMargins(marginParams, 0, dp16, 0, dp8);
|
||||
} else {
|
||||
AndroidUtils.setMargins(marginParams, 0, 0, 0, dp8);
|
||||
}
|
||||
AndroidUiHelper.updateVisibility(container, infoExpanded);
|
||||
updateUpDownBtn();
|
||||
}
|
||||
|
@ -226,6 +245,16 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightButtonHeight(){
|
||||
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDismissButtonHeight(){
|
||||
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightBottomButtonTextId() {
|
||||
return R.string.start_recording;
|
||||
|
|
|
@ -30,6 +30,7 @@ import net.osmand.GPXUtilities.GPXFile;
|
|||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.data.FavouritePoint;
|
||||
import net.osmand.plus.FavouritesDbHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
|
@ -70,19 +71,32 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
|||
public static final String TAG = EditTrackGroupDialogFragment.class.getSimpleName();
|
||||
|
||||
private OsmandApplication app;
|
||||
private GpxSelectionHelper selectedGpxHelper;
|
||||
private MapMarkersHelper mapMarkersHelper;
|
||||
|
||||
private GpxDisplayGroup group;
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
app = requiredMyApplication();
|
||||
if (group == null) {
|
||||
return;
|
||||
}
|
||||
app = requiredMyApplication();
|
||||
selectedGpxHelper = app.getSelectedGpxHelper();
|
||||
mapMarkersHelper = app.getMapMarkersHelper();
|
||||
items.add(new TitleItem(getCategoryName(app, group.getName())));
|
||||
|
||||
GPXFile gpxFile = group.getGpx();
|
||||
|
||||
boolean currentTrack = group.getGpx().showCurrentTrack;
|
||||
|
||||
SelectedGpxFile selectedGpxFile;
|
||||
if (currentTrack) {
|
||||
selectedGpxFile = selectedGpxHelper.getSelectedCurrentRecordingTrack();
|
||||
} else {
|
||||
selectedGpxFile = selectedGpxHelper.getSelectedFileByPath(gpxFile.path);
|
||||
}
|
||||
boolean trackPoints = group.getType() == GpxDisplayItemType.TRACK_POINTS;
|
||||
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(group.getGpx().path);
|
||||
if (trackPoints && selectedGpxFile != null) {
|
||||
items.add(createShowOnMapItem(selectedGpxFile));
|
||||
}
|
||||
|
@ -92,7 +106,9 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
|||
}
|
||||
items.add(new OptionsDividerItem(app));
|
||||
|
||||
// items.add(createCopyToMarkersItem());
|
||||
if (!currentTrack) {
|
||||
items.add(createCopyToMarkersItem(gpxFile));
|
||||
}
|
||||
items.add(createCopyToFavoritesItem());
|
||||
items.add(new OptionsDividerItem(app));
|
||||
|
||||
|
@ -175,27 +191,51 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
|||
.create();
|
||||
}
|
||||
|
||||
private BaseBottomSheetItem createCopyToMarkersItem() {
|
||||
private BaseBottomSheetItem createCopyToMarkersItem(final GPXFile gpxFile) {
|
||||
final MapMarkersGroup markersGroup = getOrCreateMarkersGroup(gpxFile);
|
||||
final Set<String> categories = markersGroup.getWptCategories();
|
||||
final boolean synced = categories != null && categories.contains(group.getName());
|
||||
|
||||
return new SimpleBottomSheetItem.Builder()
|
||||
.setIcon(getContentIcon(R.drawable.ic_action_copy))
|
||||
.setTitle(getString(R.string.copy_to_map_markers))
|
||||
.setLayoutId(R.layout.bottom_sheet_item_simple)
|
||||
.setIcon(getContentIcon(synced ? R.drawable.ic_action_delete_dark : R.drawable.ic_action_copy))
|
||||
.setTitle(getString(synced ? R.string.remove_from_map_markers : R.string.copy_to_map_markers))
|
||||
.setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
|
||||
.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// MapMarkersHelper markersHelper = app.getMapMarkersHelper();
|
||||
// MapMarkersGroup markersGroup = markersHelper.getMarkersGroup(group);
|
||||
// if (markersGroup != null) {
|
||||
// markersHelper.removeMarkersGroup(markersGroup);
|
||||
// } else {
|
||||
// markersHelper.addOrEnableGroup(group);
|
||||
// }
|
||||
updateGroupWptCategory(gpxFile, markersGroup, categories, synced);
|
||||
dismiss();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
private void updateGroupWptCategory(GPXFile gpxFile, MapMarkersGroup markersGroup, Set<String> categories, boolean synced) {
|
||||
SelectedGpxFile selectedGpxFile = selectedGpxHelper.getSelectedFileByPath(gpxFile.path);
|
||||
if (selectedGpxFile == null) {
|
||||
selectedGpxHelper.selectGpxFile(gpxFile, true, false, false, false, false);
|
||||
}
|
||||
Set<String> selectedCategories = new HashSet<>();
|
||||
if (categories != null) {
|
||||
selectedCategories.addAll(categories);
|
||||
}
|
||||
if (synced) {
|
||||
selectedCategories.remove(group.getName());
|
||||
} else {
|
||||
selectedCategories.add(group.getName());
|
||||
}
|
||||
mapMarkersHelper.updateGroupWptCategories(markersGroup, selectedCategories);
|
||||
mapMarkersHelper.runSynchronization(markersGroup);
|
||||
}
|
||||
|
||||
private MapMarkersGroup getOrCreateMarkersGroup(GPXFile gpxFile) {
|
||||
MapMarkersGroup markersGroup = mapMarkersHelper.getMarkersGroup(gpxFile);
|
||||
if (markersGroup == null) {
|
||||
markersGroup = mapMarkersHelper.addOrEnableGroup(gpxFile);
|
||||
}
|
||||
return markersGroup;
|
||||
}
|
||||
|
||||
private BaseBottomSheetItem createCopyToFavoritesItem() {
|
||||
return new SimpleBottomSheetItem.Builder()
|
||||
.setIcon(getContentIcon(R.drawable.ic_action_copy))
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.plus.onlinerouting.ui;
|
|||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
|
@ -79,6 +80,7 @@ public class OnlineRoutingCard extends BaseCard {
|
|||
|
||||
int activeColor = ContextCompat.getColor(app, appMode.getIconColorInfo().getColor(nightMode));
|
||||
textFieldBoxes.setPrimaryColor(activeColor);
|
||||
textFieldBoxes.setGravityFloatingLabel(Gravity.START);
|
||||
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
|
|
|
@ -295,8 +295,12 @@ public class OsmEditsFragment extends OsmAndListFragment implements ProgressDial
|
|||
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
uploadItems(osmEditsSelected.toArray(new OsmPoint[0]));
|
||||
mode.finish();
|
||||
if (Algorithms.isEmpty(osmEditsSelected)) {
|
||||
app.showToastMessage(R.string.toast_select_edits_for_upload);
|
||||
} else {
|
||||
uploadItems(osmEditsSelected.toArray(new OsmPoint[0]));
|
||||
mode.finish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -815,7 +815,7 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) {
|
||||
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState) {
|
||||
LockableViewPager viewPager = this.viewPager;
|
||||
RouteDetailsFragment current = getCurrentFragment();
|
||||
if (viewPager != null && fragment == current) {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.squareup.picasso.Callback;
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.squareup.picasso.RequestCreator;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.PicassoUtils;
|
||||
import net.osmand.plus.R;
|
||||
|
@ -19,6 +19,9 @@ import net.osmand.plus.widgets.TextViewEx;
|
|||
import net.osmand.plus.wikipedia.WikiArticleHelper;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.getMetadataImageLink;
|
||||
|
||||
public class DescriptionCard extends BaseCard {
|
||||
|
@ -37,11 +40,8 @@ public class DescriptionCard extends BaseCard {
|
|||
|
||||
@Override
|
||||
protected void updateContent() {
|
||||
if (gpxFile.metadata == null || gpxFile.metadata.getDescription() == null) {
|
||||
AndroidUiHelper.updateVisibility(view, false);
|
||||
return;
|
||||
} else {
|
||||
AndroidUiHelper.updateVisibility(view, true);
|
||||
if (gpxFile.metadata == null) {
|
||||
gpxFile.metadata = new GPXUtilities.Metadata();
|
||||
}
|
||||
|
||||
final String title = gpxFile.metadata.getArticleTitle();
|
||||
|
@ -50,6 +50,34 @@ public class DescriptionCard extends BaseCard {
|
|||
|
||||
setupImage(imageUrl);
|
||||
|
||||
if (Algorithms.isBlank(descriptionHtml)) {
|
||||
showAddBtn();
|
||||
} else {
|
||||
showDescription(title, imageUrl, descriptionHtml);
|
||||
}
|
||||
}
|
||||
|
||||
private void showAddBtn() {
|
||||
LinearLayout descriptionContainer = view.findViewById(R.id.description_container);
|
||||
FrameLayout addBtn = view.findViewById(R.id.btn_add);
|
||||
|
||||
addBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
GpxEditDescriptionDialogFragment.showInstance(getMapActivity(), "", null);
|
||||
}
|
||||
});
|
||||
AndroidUiHelper.updateVisibility(descriptionContainer, false);
|
||||
AndroidUiHelper.updateVisibility(addBtn, true);
|
||||
}
|
||||
|
||||
private void showDescription(final String title, final String imageUrl, final String descriptionHtml) {
|
||||
LinearLayout descriptionContainer = view.findViewById(R.id.description_container);
|
||||
FrameLayout addBtn = view.findViewById(R.id.btn_add);
|
||||
|
||||
AndroidUiHelper.updateVisibility(descriptionContainer, true);
|
||||
AndroidUiHelper.updateVisibility(addBtn, false);
|
||||
|
||||
TextViewEx tvDescription = view.findViewById(R.id.description);
|
||||
tvDescription.setText(getFirstParagraph(descriptionHtml));
|
||||
|
||||
|
@ -60,6 +88,7 @@ public class DescriptionCard extends BaseCard {
|
|||
GpxReadDescriptionDialogFragment.showInstance(mapActivity, title, imageUrl, descriptionHtml);
|
||||
}
|
||||
});
|
||||
|
||||
TextViewEx editBtn = view.findViewById(R.id.btn_edit);
|
||||
editBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
|
@ -7,12 +9,6 @@ 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;
|
||||
|
@ -22,12 +18,18 @@ 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;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
||||
|
||||
public static final String TAG = GpxEditDescriptionDialogFragment.class.getSimpleName();
|
||||
|
@ -37,6 +39,8 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
|||
|
||||
private EditTextEx editableHtml;
|
||||
|
||||
private String htmlCode;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
|
@ -46,11 +50,16 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
|||
View view = themedInflater.inflate(R.layout.dialog_edit_gpx_description, container, false);
|
||||
|
||||
editableHtml = view.findViewById(R.id.description);
|
||||
editableHtml.requestFocus();
|
||||
|
||||
view.findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
if (shouldClose()) {
|
||||
dismiss();
|
||||
} else {
|
||||
showDismissDialog();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -58,7 +67,7 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
Editable editable = editableHtml.getText();
|
||||
if (!Algorithms.isEmpty(editable) && !saveGpx(editable.toString())) {
|
||||
if (editable != null && !saveGpx(editable.toString())) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
@ -66,15 +75,38 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
|||
|
||||
Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
String html = args.getString(CONTENT_KEY);
|
||||
if (html != null) {
|
||||
editableHtml.setText(html);
|
||||
htmlCode = args.getString(CONTENT_KEY);
|
||||
if (htmlCode != null) {
|
||||
editableHtml.setText(htmlCode);
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private boolean shouldClose() {
|
||||
Editable editable = editableHtml.getText();
|
||||
if (htmlCode == null || editable == null || editable.toString() == null) {
|
||||
return true;
|
||||
}
|
||||
return htmlCode.equals(editable.toString());
|
||||
}
|
||||
|
||||
private void showDismissDialog() {
|
||||
Context themedContext = UiUtilities.getThemedContext(getMapActivity(), isNightMode(false));
|
||||
AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext);
|
||||
dismissDialog.setTitle(getString(R.string.shared_string_dismiss));
|
||||
dismissDialog.setMessage(getString(R.string.exit_without_saving));
|
||||
dismissDialog.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
dismissDialog.show();
|
||||
}
|
||||
|
||||
private boolean saveGpx(final String html) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity == null || mapActivity.getTrackMenuFragment() == null) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package net.osmand.plus.track;
|
|||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -15,14 +16,6 @@ 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;
|
||||
|
@ -39,6 +32,14 @@ import net.osmand.plus.widgets.WebViewEx;
|
|||
import net.osmand.plus.wikivoyage.WikivoyageUtils;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
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;
|
||||
|
||||
public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
||||
|
||||
public static final String TAG = GpxReadDescriptionDialogFragment.class.getSimpleName();
|
||||
|
@ -181,10 +182,16 @@ public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment {
|
|||
|
||||
private void setupWebView(final View view) {
|
||||
webView = view.findViewById(R.id.content);
|
||||
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
else {
|
||||
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -74,7 +74,9 @@ public class OptionsCard extends BaseCard {
|
|||
items.add(createDirectionsItem());
|
||||
}
|
||||
items.add(createDividerItem());
|
||||
items.add(createJoinGapsItem());
|
||||
if (gpxFile.getGeneralTrack() != null) {
|
||||
items.add(createJoinGapsItem());
|
||||
}
|
||||
items.add(createAnalyzeOnMapItem());
|
||||
items.add(createAnalyzeByIntervalsItem());
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
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;
|
||||
|
@ -17,11 +13,10 @@ 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.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
|
@ -29,6 +24,7 @@ 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.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
|
||||
|
@ -38,7 +34,6 @@ 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;
|
||||
|
@ -46,6 +41,7 @@ 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;
|
||||
import static net.osmand.plus.track.OverviewCard.StatBlock.ItemType.*;
|
||||
|
||||
public class OverviewCard extends BaseCard {
|
||||
|
||||
|
@ -57,15 +53,22 @@ public class OverviewCard extends BaseCard {
|
|||
|
||||
private final TrackDisplayHelper displayHelper;
|
||||
private final GPXFile gpxFile;
|
||||
private final GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
|
||||
private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT};
|
||||
private final SegmentActionsListener listener;
|
||||
private boolean gpxFileSelected;
|
||||
private GpxDisplayItem gpxItem;
|
||||
|
||||
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener listener) {
|
||||
super(mapActivity);
|
||||
this.displayHelper = displayHelper;
|
||||
this.gpxFile = displayHelper.getGpx();
|
||||
this.listener = listener;
|
||||
gpxFile = displayHelper.getGpx();
|
||||
gpxFileSelected = isGpxFileSelected(app, gpxFile);
|
||||
List<GpxDisplayGroup> groups = displayHelper.getOriginalGroups(filterTypes);
|
||||
if (!Algorithms.isEmpty(groups)) {
|
||||
gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,7 +78,7 @@ public class OverviewCard extends BaseCard {
|
|||
|
||||
@Override
|
||||
protected void updateContent() {
|
||||
int iconColorDef = R.color.icon_color_active_light;
|
||||
int iconColorDef = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
|
||||
int iconColorPres = R.color.active_buttons_and_links_text_dark;
|
||||
boolean fileAvailable = gpxFile.path != null && !gpxFile.showCurrentTrack;
|
||||
|
||||
|
@ -95,9 +98,7 @@ public class OverviewCard extends BaseCard {
|
|||
}
|
||||
|
||||
void initStatBlocks() {
|
||||
List<GpxDisplayGroup> groups = displayHelper.getOriginalGroups(filterTypes);
|
||||
if (!Algorithms.isEmpty(groups)) {
|
||||
GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(groups).get(0);
|
||||
if (gpxItem != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
boolean joinSegments = displayHelper.isJoinSegments();
|
||||
float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
|
||||
|
@ -106,95 +107,85 @@ public class OverviewCard extends BaseCard {
|
|||
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
|
||||
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
|
||||
List<StatBlock> items = new ArrayList<>();
|
||||
|
||||
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),
|
||||
StatBlock.prepareData(analysis, items, 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, ITEM_DISTANCE);
|
||||
StatBlock.prepareData(analysis, items, app.getString(R.string.altitude_ascent), asc,
|
||||
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ITEM_ALTITUDE);
|
||||
StatBlock.prepareData(analysis, items, app.getString(R.string.altitude_descent), desc,
|
||||
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ITEM_ALTITUDE);
|
||||
StatBlock.prepareData(analysis, items, app.getString(R.string.average_speed), avg,
|
||||
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_SPEED);
|
||||
StatBlock.prepareData(analysis, items, app.getString(R.string.max_speed), max,
|
||||
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_SPEED);
|
||||
StatBlock.prepareData(analysis, items, 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);
|
||||
R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_TIME);
|
||||
|
||||
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));
|
||||
if (Algorithms.isEmpty(items)) {
|
||||
AndroidUiHelper.updateVisibility(rvOverview, false);
|
||||
} else {
|
||||
final StatBlockAdapter sbAdapter = new StatBlockAdapter(items);
|
||||
rvOverview.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false));
|
||||
rvOverview.setAdapter(sbAdapter);
|
||||
}
|
||||
} else {
|
||||
AndroidUiHelper.updateVisibility(rvOverview, false);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@DrawableRes
|
||||
private int getActiveShowHideIcon() {
|
||||
gpxFileSelected = isGpxFileSelected(app, gpxFile);
|
||||
return gpxFileSelected ? R.drawable.ic_action_view : R.drawable.ic_action_hide;
|
||||
}
|
||||
|
||||
private void initAppearanceButton(int iconColorDef, int iconColorPres) {
|
||||
private void initShowButton(final int iconColorDef, final int iconColorPres) {
|
||||
initButton(showButton, SHOW_ON_MAP_BUTTON_INDEX, getActiveShowHideIcon(), iconColorDef, iconColorPres);
|
||||
}
|
||||
|
||||
private void initAppearanceButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) {
|
||||
initButton(appearanceButton, APPEARANCE_BUTTON_INDEX, R.drawable.ic_action_appearance, iconColorDef, iconColorPres);
|
||||
}
|
||||
|
||||
private void initEditButton(int iconColorDef, int iconColorPres) {
|
||||
private void initEditButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) {
|
||||
initButton(editButton, EDIT_BUTTON_INDEX, R.drawable.ic_action_edit_dark, iconColorDef, iconColorPres);
|
||||
}
|
||||
|
||||
private void initDirectionsButton(int iconColorDef, int iconColorPres) {
|
||||
private void initDirectionsButton(@ColorRes int iconColorDef, @ColorRes 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);
|
||||
private void initButton(View item, final int buttonIndex, @DrawableRes Integer iconResId,
|
||||
@ColorRes final int iconColorDef, @ColorRes int iconColorPres) {
|
||||
final AppCompatImageView icon = item.findViewById(R.id.image);
|
||||
final AppCompatImageView filled = item.findViewById(R.id.filled);
|
||||
filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref);
|
||||
filled.setImageResource(nightMode ? R.drawable.bg_plugin_logo_enabled_dark : R.drawable.bg_topbar_shield_exit_ref);
|
||||
filled.setAlpha(0.1f);
|
||||
setImageDrawable(image, iconResId, iconColorDef);
|
||||
setOnTouchItem(item, image, filled, iconResId, iconColorDef, iconColorPres);
|
||||
setImageDrawable(icon, iconResId, iconColorDef);
|
||||
setOnTouchItem(item, icon, 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);
|
||||
if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) {
|
||||
setImageDrawable(icon, getActiveShowHideIcon(), iconColorDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setImageDrawable(ImageView iv, @DrawableRes int resId, @ColorRes int color) {
|
||||
Drawable icon = app.getUIUtilities().getIcon(resId, color);
|
||||
private void setImageDrawable(ImageView iv, @DrawableRes Integer resId, @ColorRes int color) {
|
||||
Drawable icon = resId != null ? app.getUIUtilities().getIcon(resId, color)
|
||||
: UiUtilities.tintDrawable(iv.getDrawable(), getResolvedColor(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) {
|
||||
private void setOnTouchItem(View item, final ImageView image, final ImageView filled, @DrawableRes final Integer resId, @ColorRes final int colorDef, @ColorRes final int colorPres) {
|
||||
item.setOnTouchListener(new View.OnTouchListener() {
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
|
@ -241,26 +232,24 @@ public class OverviewCard extends BaseCard {
|
|||
@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.valueText.setTextColor(getActiveColor());
|
||||
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]);
|
||||
if (gpxItem.analysis.hasElevationData || gpxItem.analysis.isSpeedSpecified() || gpxItem.analysis.hasSpeedData) {
|
||||
if (item.firstType != null) {
|
||||
list.add(item.firstType);
|
||||
}
|
||||
if (item.secondType != null) {
|
||||
list.add(item.secondType);
|
||||
}
|
||||
}
|
||||
gpxItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
|
||||
gpxItem.locationOnMap = gpxItem.locationStart;
|
||||
|
||||
listener.openAnalyzeOnMap(gpxItem);
|
||||
|
@ -268,6 +257,8 @@ public class OverviewCard extends BaseCard {
|
|||
}
|
||||
});
|
||||
setImageDrawable(holder.imageView, item.imageResId, item.imageColorId);
|
||||
AndroidUtils.setBackgroundColor(view.getContext(), holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark);
|
||||
AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,55 +267,18 @@ public class OverviewCard extends BaseCard {
|
|||
private final TextViewEx valueText;
|
||||
private final TextView titleText;
|
||||
private final AppCompatImageView imageView;
|
||||
private final View divider;
|
||||
|
||||
StatBlockViewHolder(View view) {
|
||||
super(view);
|
||||
valueText = view.findViewById(R.id.value);
|
||||
titleText = view.findViewById(R.id.title);
|
||||
imageView = view.findViewById(R.id.image);
|
||||
divider = view.findViewById(R.id.divider);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
protected static class StatBlock {
|
||||
|
||||
private final String title;
|
||||
private final String value;
|
||||
|
@ -332,15 +286,56 @@ public class OverviewCard extends BaseCard {
|
|||
private final int imageColorId;
|
||||
private final GPXDataSetType firstType;
|
||||
private final GPXDataSetType secondType;
|
||||
private final ItemType itemType;
|
||||
|
||||
public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
|
||||
GPXDataSetType firstType, GPXDataSetType secondType) {
|
||||
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
|
||||
this.title = title;
|
||||
this.value = value;
|
||||
this.imageResId = imageResId;
|
||||
this.imageColorId = imageColorId;
|
||||
this.firstType = firstType;
|
||||
this.secondType = secondType;
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
public static void prepareData(GPXTrackAnalysis analysis, List<StatBlock> listItems, String title,
|
||||
String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
|
||||
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
|
||||
StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType);
|
||||
switch (statBlock.itemType) {
|
||||
case ITEM_DISTANCE: {
|
||||
if (analysis.totalDistance != 0f) {
|
||||
listItems.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_ALTITUDE: {
|
||||
if (analysis.hasElevationData) {
|
||||
listItems.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_SPEED: {
|
||||
if (analysis.isSpeedSpecified()) {
|
||||
listItems.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_TIME: {
|
||||
if (analysis.hasSpeedData) {
|
||||
listItems.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ItemType {
|
||||
ITEM_DISTANCE,
|
||||
ITEM_ALTITUDE,
|
||||
ITEM_SPEED,
|
||||
ITEM_TIME;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import androidx.activity.OnBackPressedCallback;
|
|||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
|
@ -37,6 +38,7 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.base.ContextMenuFragment;
|
||||
import net.osmand.plus.base.ContextMenuScrollFragment;
|
||||
import net.osmand.plus.dialogs.GpxAppearanceAdapter;
|
||||
import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem;
|
||||
|
@ -165,16 +167,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
}
|
||||
requireMyActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
public void handleOnBackPressed() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
TripRecordingBottomSheet fragment = mapActivity.getTripRecordingBottomSheet();
|
||||
if (fragment != null) {
|
||||
fragment.show();
|
||||
} else {
|
||||
mapActivity.launchPrevActivityIntent();
|
||||
}
|
||||
dismissImmediate();
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -385,6 +378,14 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContextMenuDismiss(@NonNull ContextMenuFragment fragment) {
|
||||
Fragment target = getTargetFragment();
|
||||
if (target instanceof TripRecordingBottomSheet) {
|
||||
((TripRecordingBottomSheet) target).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAppearanceIcon() {
|
||||
Drawable icon = getTrackIcon(app, trackDrawInfo.getWidth(), trackDrawInfo.isShowArrows(), trackDrawInfo.getColor());
|
||||
trackIcon.setImageDrawable(icon);
|
||||
|
@ -725,11 +726,12 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
return totalScreenHeight - frameTotalHeight;
|
||||
}
|
||||
|
||||
public static boolean showInstance(@NonNull MapActivity mapActivity, @NonNull SelectedGpxFile selectedGpxFile) {
|
||||
public static boolean showInstance(@NonNull MapActivity mapActivity, @NonNull SelectedGpxFile selectedGpxFile, Fragment target) {
|
||||
try {
|
||||
TrackAppearanceFragment fragment = new TrackAppearanceFragment();
|
||||
fragment.setSelectedGpxFile(selectedGpxFile);
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.setSelectedGpxFile(selectedGpxFile);
|
||||
fragment.setTargetFragment(target, 0);
|
||||
|
||||
mapActivity.getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
|
|
|
@ -60,7 +60,6 @@ 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.activities.TrackActivity;
|
||||
import net.osmand.plus.base.ContextMenuFragment;
|
||||
import net.osmand.plus.base.ContextMenuScrollFragment;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
|
@ -139,6 +138,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
private ImageView searchButton;
|
||||
private EditText searchEditText;
|
||||
private TextView toolbarTextView;
|
||||
private ViewGroup headerContainer;
|
||||
private View routeMenuTopShadowAll;
|
||||
private BottomNavigationView bottomNav;
|
||||
|
||||
|
@ -152,6 +152,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
|
||||
private int menuTitleHeight;
|
||||
private int toolbarHeightPx;
|
||||
private boolean mapPositionAdjusted;
|
||||
|
||||
public enum TrackMenuType {
|
||||
OVERVIEW(R.id.action_overview, R.string.shared_string_overview),
|
||||
|
@ -185,13 +186,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
|
||||
@Override
|
||||
public int getToolbarHeight() {
|
||||
return toolbarHeightPx;
|
||||
return isPortrait() ? toolbarHeightPx : 0;
|
||||
}
|
||||
|
||||
public float getMiddleStateKoef() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
public int getMinY() {
|
||||
return getFullScreenTopPosY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSupportedMenuStatesPortrait() {
|
||||
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
|
||||
|
@ -226,11 +231,22 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
FragmentActivity activity = requireMyActivity();
|
||||
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
public void handleOnBackPressed() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
mapActivity.launchPrevActivityIntent();
|
||||
if (getCurrentMenuState() != MenuState.HEADER_ONLY && isPortrait()) {
|
||||
openMenuHeaderOnly();
|
||||
} else {
|
||||
dismiss();
|
||||
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
MapContextMenu contextMenu = mapActivity.getContextMenu();
|
||||
if (contextMenu.isActive() && contextMenu.getPointDescription() != null
|
||||
&& contextMenu.getPointDescription().isGpxPoint()) {
|
||||
contextMenu.show();
|
||||
} else {
|
||||
mapActivity.launchPrevActivityIntent();
|
||||
}
|
||||
}
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -249,6 +265,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
if (view != null) {
|
||||
bottomNav = view.findViewById(R.id.bottom_navigation);
|
||||
routeMenuTopShadowAll = view.findViewById(R.id.route_menu_top_shadow_all);
|
||||
headerContainer = view.findViewById(R.id.header_container);
|
||||
headerTitle = view.findViewById(R.id.title);
|
||||
headerIcon = view.findViewById(R.id.icon_view);
|
||||
toolbarContainer = view.findViewById(R.id.context_menu_toolbar_container);
|
||||
|
@ -269,8 +286,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
setupToolbar();
|
||||
updateHeader();
|
||||
setupButtons(view);
|
||||
enterTrackAppearanceMode();
|
||||
runLayoutListener();
|
||||
updateCardsLayout();
|
||||
calculateLayoutAndUpdateMenuState();
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
@ -281,7 +298,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
}
|
||||
|
||||
private void updateHeader() {
|
||||
ViewGroup headerContainer = (ViewGroup) routeMenuTopShadowAll;
|
||||
if (menuType == TrackMenuType.OVERVIEW) {
|
||||
setHeaderTitle(gpxTitle, true);
|
||||
if (overviewCard != null && overviewCard.getView() != null) {
|
||||
|
@ -428,6 +444,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
}
|
||||
}
|
||||
|
||||
private void updateCardsLayout() {
|
||||
FrameLayout bottomContainer = getBottomContainer();
|
||||
if (menuType == TrackMenuType.OPTIONS) {
|
||||
AndroidUtils.setBackground(app, bottomContainer, isNightMode(),
|
||||
R.color.list_background_color_light, R.color.list_background_color_dark);
|
||||
} else {
|
||||
AndroidUtils.setBackground(app, bottomContainer, isNightMode(),
|
||||
R.color.activity_background_color_light, R.color.activity_background_color_dark);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void calculateLayout(View view, boolean initLayout) {
|
||||
menuTitleHeight = routeMenuTopShadowAll.getHeight()
|
||||
|
@ -455,15 +482,21 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
adjustMapPosition(getHeight());
|
||||
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int currentMenuState, int previousMenuState) {
|
||||
super.onContextMenuStateChanged(fragment, currentMenuState, previousMenuState);
|
||||
|
||||
boolean changed = currentMenuState != previousMenuState;
|
||||
if (changed) {
|
||||
updateControlsVisibility(true);
|
||||
}
|
||||
if (currentMenuState != MenuState.FULL_SCREEN && (changed || !mapPositionAdjusted)) {
|
||||
adjustMapPosition(getMenuStatePosY(currentMenuState));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
exitTrackAppearanceMode();
|
||||
updateStatusBarColor();
|
||||
}
|
||||
|
||||
|
@ -474,6 +507,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
if (mapActivity != null && trackChartPoints != null) {
|
||||
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints);
|
||||
}
|
||||
updateControlsVisibility(true);
|
||||
startLocationUpdate();
|
||||
}
|
||||
|
||||
|
@ -484,6 +518,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
if (mapActivity != null) {
|
||||
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(null);
|
||||
}
|
||||
updateControlsVisibility(false);
|
||||
stopLocationUpdate();
|
||||
}
|
||||
|
||||
|
@ -569,26 +604,25 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
updateContent();
|
||||
}
|
||||
|
||||
private void enterTrackAppearanceMode() {
|
||||
public void updateControlsVisibility(boolean menuVisible) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
|
||||
AndroidUiHelper.setVisibility(mapActivity, portrait ? View.INVISIBLE : View.GONE,
|
||||
R.id.map_left_widgets_panel,
|
||||
R.id.map_right_widgets_panel,
|
||||
R.id.map_center_info);
|
||||
boolean topControlsVisible = shouldShowTopControls(menuVisible);
|
||||
boolean bottomControlsVisible = shouldShowBottomControls(menuVisible);
|
||||
MapContextMenu.updateControlsVisibility(mapActivity, topControlsVisible, bottomControlsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
private void exitTrackAppearanceMode() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
AndroidUiHelper.setVisibility(mapActivity, View.VISIBLE,
|
||||
R.id.map_left_widgets_panel,
|
||||
R.id.map_right_widgets_panel,
|
||||
R.id.map_center_info,
|
||||
R.id.map_search_button);
|
||||
}
|
||||
public boolean shouldShowTopControls() {
|
||||
return shouldShowTopControls(isVisible());
|
||||
}
|
||||
|
||||
public boolean shouldShowTopControls(boolean menuVisible) {
|
||||
return !menuVisible || !isPortrait() || getCurrentMenuState() == MenuState.HEADER_ONLY;
|
||||
}
|
||||
|
||||
public boolean shouldShowBottomControls(boolean menuVisible) {
|
||||
return !menuVisible || !isPortrait();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -652,7 +686,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
app.getSelectedGpxHelper().selectGpxFile(gpxFile, gpxFileSelected, false);
|
||||
mapActivity.refreshMap();
|
||||
} else if (buttonIndex == APPEARANCE_BUTTON_INDEX) {
|
||||
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile);
|
||||
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile, this);
|
||||
} else if (buttonIndex == DIRECTIONS_BUTTON_INDEX) {
|
||||
MapActivityActions mapActions = mapActivity.getMapActions();
|
||||
if (app.getRoutingHelper().isFollowingMode()) {
|
||||
|
@ -760,15 +794,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int applyPosY(int currentY, boolean needCloseMenu, boolean needMapAdjust, int previousMenuState, int newMenuState, int dZoom, boolean animated) {
|
||||
int y = super.applyPosY(currentY, needCloseMenu, needMapAdjust, previousMenuState, newMenuState, dZoom, animated);
|
||||
if (needMapAdjust) {
|
||||
adjustMapPosition(y);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
public void updateToolbar(int y, boolean animated) {
|
||||
final MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
|
@ -799,7 +824,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
|
||||
@Override
|
||||
protected void onHeaderClick() {
|
||||
adjustMapPosition(getViewY());
|
||||
updateMenuState();
|
||||
}
|
||||
|
||||
private void adjustMapPosition(int y) {
|
||||
|
@ -821,6 +846,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
if (r.left != 0 && r.right != 0) {
|
||||
mapActivity.getMapView().fitRectToMap(r.left, r.right, r.top, r.bottom, tileBoxWidthPx, tileBoxHeightPx, 0);
|
||||
}
|
||||
mapPositionAdjusted = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -838,6 +864,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
menuType = type;
|
||||
setupCards();
|
||||
updateHeader();
|
||||
updateCardsLayout();
|
||||
calculateLayoutAndUpdateMenuState();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -846,6 +874,25 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
});
|
||||
}
|
||||
|
||||
private void calculateLayoutAndUpdateMenuState() {
|
||||
runLayoutListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateMenuState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateMenuState() {
|
||||
if (menuType == TrackMenuType.OPTIONS) {
|
||||
openMenuFullScreen();
|
||||
} else if (menuType == TrackMenuType.OVERVIEW) {
|
||||
openMenuHeaderOnly();
|
||||
} else {
|
||||
openMenuHalfScreen();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateContent() {
|
||||
if (segmentsCard != null) {
|
||||
|
@ -1044,14 +1091,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
}
|
||||
|
||||
public static void openTrack(@NonNull Context context, @Nullable File file, Bundle prevIntentParams) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(OPEN_TRACK_MENU, true);
|
||||
if (file == null) {
|
||||
bundle.putBoolean(TrackActivity.CURRENT_RECORDING, true);
|
||||
boolean currentRecording = file == null;
|
||||
String path = file != null ? file.getAbsolutePath() : null;
|
||||
if (context instanceof MapActivity) {
|
||||
TrackMenuFragment.showInstance((MapActivity) context, path, currentRecording);
|
||||
} else {
|
||||
bundle.putString(TrackActivity.TRACK_FILE_NAME, file.getAbsolutePath());
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(TRACK_FILE_NAME, path);
|
||||
bundle.putBoolean(OPEN_TRACK_MENU, true);
|
||||
bundle.putBoolean(CURRENT_RECORDING, currentRecording);
|
||||
MapActivity.launchMapActivityMoveToTop(context, prevIntentParams, null, bundle);
|
||||
}
|
||||
MapActivity.launchMapActivityMoveToTop(context, prevIntentParams, null, bundle);
|
||||
}
|
||||
|
||||
public static void showInstance(@NonNull final MapActivity mapActivity, @Nullable String path, boolean showCurrentTrack) {
|
||||
|
|
|
@ -859,30 +859,30 @@ public class MapControlsLayer extends OsmandMapLayer {
|
|||
}
|
||||
boolean routeFollowingMode = !routePlanningMode && rh.isFollowingMode();
|
||||
boolean trackDialogOpened = mapActivity.getTrackDetailsMenu().isVisible();
|
||||
boolean contextMenuOpened = !mapActivity.getContextMenu().shouldShowTopControls();
|
||||
boolean shouldHideTopControls = mapActivity.shouldHideTopControls();
|
||||
boolean showRouteCalculationControls = routePlanningMode ||
|
||||
((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode);
|
||||
boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu());
|
||||
updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || contextMenuOpened);
|
||||
updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || shouldHideTopControls);
|
||||
//routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_info_dark : R.drawable.ic_action_gdirections_dark);
|
||||
|
||||
updateRoutePlaningButton(rh, routePlanningMode);
|
||||
|
||||
boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode)
|
||||
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
|
||||
&& !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode()
|
||||
&& !isInPlanRouteMode() && !shouldHideTopControls && !isInChoosingRoutesMode()
|
||||
&& !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode();
|
||||
routePlanningBtn.updateVisibility(showBottomMenuButtons);
|
||||
menuControl.updateVisibility(showBottomMenuButtons);
|
||||
|
||||
boolean showZoomButtons = !routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode()
|
||||
boolean showZoomButtons = !routeDialogOpened && !shouldHideTopControls && !isInTrackAppearanceMode()
|
||||
&& (!isInGpxApproximationMode() || !isPotrait())
|
||||
&& !isInFollowTrackMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait);
|
||||
mapZoomIn.updateVisibility(showZoomButtons);
|
||||
mapZoomOut.updateVisibility(showZoomButtons);
|
||||
|
||||
boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode()
|
||||
|| isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode()
|
||||
|| isInPlanRouteMode() || shouldHideTopControls || isInChoosingRoutesMode()
|
||||
|| isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode();
|
||||
compassHud.forceHideCompass = forceHideCompass;
|
||||
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
|
||||
|
@ -892,7 +892,7 @@ public class MapControlsLayer extends OsmandMapLayer {
|
|||
if (layersHud.setIconResId(appMode.getIconRes())) {
|
||||
layersHud.update(app, isNight);
|
||||
}
|
||||
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !contextMenuOpened
|
||||
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls
|
||||
&& !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode()
|
||||
&& !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode();
|
||||
layersHud.updateVisibility(showTopButtons);
|
||||
|
|
|
@ -425,6 +425,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
|
|||
measurementToolLayer.isInMeasurementMode() ||
|
||||
mapMarkersLayer.isInPlanRouteMode() ||
|
||||
gpxLayer.isInTrackAppearanceMode() ||
|
||||
mapControlsLayer.isInTrackMenuMode() ||
|
||||
mapRouteInfoMenu.isVisible() ||
|
||||
MapRouteInfoMenu.chooseRoutesVisible ||
|
||||
MapRouteInfoMenu.waypointsVisible ||
|
||||
|
|
|
@ -974,7 +974,7 @@ public class MapInfoWidgetsFactory {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (map.isTopToolbarActive() || !map.getContextMenu().shouldShowTopControls() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible) {
|
||||
if (map.isTopToolbarActive() || map.shouldHideTopControls() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible) {
|
||||
updateVisibility(false);
|
||||
} else if (showClosestWaypointFirstInAddress && updateWaypoint()) {
|
||||
updateVisibility(true);
|
||||
|
@ -1232,7 +1232,7 @@ public class MapInfoWidgetsFactory {
|
|||
|
||||
@SuppressLint("SetTextI18n")
|
||||
public boolean updateInfo() {
|
||||
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && map.getContextMenu().shouldShowTopControls()
|
||||
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && !map.shouldHideTopControls()
|
||||
&& map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive()
|
||||
&& !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|
||||
&& !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible
|
||||
|
|
|
@ -191,7 +191,7 @@ public class MapMarkersWidgetsFactory {
|
|||
|| map.getMapRouteInfoMenu().isVisible()
|
||||
|| addressTopBar.getVisibility() == View.VISIBLE
|
||||
|| map.isTopToolbarActive()
|
||||
|| !map.getContextMenu().shouldShowTopControls()
|
||||
|| map.shouldHideTopControls()
|
||||
|| map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|
||||
|| map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()) {
|
||||
updateVisibility(false);
|
||||
|
|
|
@ -26,7 +26,30 @@ public class OsmandTextFieldBoxes extends TextFieldBoxes {
|
|||
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);
|
||||
int paddingV = getResources().getDimensionPixelSize(R.dimen.route_info_card_details_margin);
|
||||
inputLayout.setPadding(0, paddingV, 0, paddingV);
|
||||
}
|
||||
|
||||
public void setGravityFloatingLabel(int gravity) {
|
||||
floatingLabel.setGravity(gravity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLabelText(String labelText) {
|
||||
super.setLabelText(labelText);
|
||||
floatingLabel.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (floatingLabel.getLineCount() > 1) {
|
||||
inputLayout.setPadding(
|
||||
inputLayout.getPaddingLeft(),
|
||||
getResources().getDimensionPixelOffset(useDenseSpacing ? R.dimen.dense_editTextLayout_padding_top : R.dimen.editTextLayout_padding_top) +
|
||||
getResources().getDimensionPixelSize(useDenseSpacing ? R.dimen.context_menu_first_line_top_margin : R.dimen.content_padding_small),
|
||||
inputLayout.getPaddingRight(),
|
||||
inputLayout.getPaddingBottom()
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
14
OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelGpx.java
Normal file
14
OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelGpx.java
Normal file
|
@ -0,0 +1,14 @@
|
|||
package net.osmand.plus.wikivoyage.data;
|
||||
|
||||
public class TravelGpx extends TravelArticle {
|
||||
|
||||
public static final String DISTANCE = "distance";
|
||||
public static final String DIFF_ELE_UP = "diff_ele_up";
|
||||
public static final String DIFF_ELE_DOWN = "diff_ele_down";
|
||||
public static final String USER = "user";
|
||||
|
||||
public String user;
|
||||
public float totalDistance = 0;
|
||||
public double diffElevationUp = 0;
|
||||
public double diffElevationDown = 0;
|
||||
}
|
|
@ -150,7 +150,8 @@ public class TravelLocalDataHelper {
|
|||
@Nullable
|
||||
private TravelArticle getArticle(String title, String lang) {
|
||||
for (TravelArticle article : savedArticles) {
|
||||
if (article.title != null && article.title.equals(title) && article.lang != null && article.lang.equals(lang)) {
|
||||
if (Algorithms.stringsEqual(article.title, title)
|
||||
&& Algorithms.stringsEqual(article.lang, lang)) {
|
||||
return article;
|
||||
}
|
||||
}
|
||||
|
@ -503,12 +504,12 @@ public class TravelLocalDataHelper {
|
|||
SQLiteConnection conn = openConnection(false);
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.execSQL("DELETE FROM " + BOOKMARKS_TABLE_NAME +
|
||||
" WHERE " + BOOKMARKS_COL_ARTICLE_TITLE + " = ?" +
|
||||
" AND " + BOOKMARKS_COL_ROUTE_ID + " = ?" +
|
||||
" AND " + BOOKMARKS_COL_LANG + " = ?" +
|
||||
" AND " + BOOKMARKS_COL_TRAVEL_BOOK + " = ?",
|
||||
new Object[]{article.title, article.routeId, article.lang, travelBook});
|
||||
String query = "DELETE FROM " + BOOKMARKS_TABLE_NAME +
|
||||
" WHERE " + BOOKMARKS_COL_ARTICLE_TITLE + " = ?" +
|
||||
" AND " + BOOKMARKS_COL_ROUTE_ID + " = ?" +
|
||||
" AND " + BOOKMARKS_COL_LANG + ((article.lang != null) ? " = '" + article.lang + "'" : " IS NULL") +
|
||||
" AND " + BOOKMARKS_COL_TRAVEL_BOOK + " = ?";
|
||||
conn.execSQL(query, new Object[]{article.title, article.routeId, travelBook});
|
||||
} finally {
|
||||
conn.close();
|
||||
}
|
||||
|
@ -563,7 +564,12 @@ public class TravelLocalDataHelper {
|
|||
|
||||
@NonNull
|
||||
private TravelArticle readSavedArticle(SQLiteCursor cursor) {
|
||||
TravelArticle res = new TravelArticle();
|
||||
TravelArticle res;
|
||||
if (cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_LANG)) == null) {
|
||||
res = new TravelGpx();
|
||||
} else {
|
||||
res = new TravelArticle();
|
||||
}
|
||||
res.title = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_ARTICLE_TITLE));
|
||||
res.lang = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_LANG));
|
||||
res.aggregatedPartOf = cursor.getString(cursor.getColumnIndex(BOOKMARKS_COL_IS_PART_OF));
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.plus.wikivoyage.data;
|
|||
|
||||
import android.os.AsyncTask;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -13,6 +14,7 @@ import net.osmand.IndexConstants;
|
|||
import net.osmand.OsmAndCollator;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapDataObject;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchPoiTypeFilter;
|
||||
import net.osmand.binary.BinaryMapIndexReader.SearchRequest;
|
||||
|
@ -46,8 +48,18 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import gnu.trove.iterator.TIntObjectIterator;
|
||||
|
||||
import static net.osmand.GPXUtilities.Track;
|
||||
import static net.osmand.GPXUtilities.TrkSegment;
|
||||
import static net.osmand.GPXUtilities.WptPt;
|
||||
import static net.osmand.GPXUtilities.writeGpxFile;
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.getGpxTitle;
|
||||
import static net.osmand.plus.wikivoyage.data.TravelGpx.DIFF_ELE_DOWN;
|
||||
import static net.osmand.plus.wikivoyage.data.TravelGpx.DIFF_ELE_UP;
|
||||
import static net.osmand.plus.wikivoyage.data.TravelGpx.DISTANCE;
|
||||
import static net.osmand.plus.wikivoyage.data.TravelGpx.USER;
|
||||
import static net.osmand.util.Algorithms.capitalizeFirstLetter;
|
||||
|
||||
public class TravelObfHelper implements TravelHelper {
|
||||
|
||||
|
@ -55,9 +67,13 @@ public class TravelObfHelper implements TravelHelper {
|
|||
private static final String WORLD_WIKIVOYAGE_FILE_NAME = "World_wikivoyage.travel.obf";
|
||||
public static final String ROUTE_ARTICLE = "route_article";
|
||||
public static final String ROUTE_ARTICLE_POINT = "route_article_point";
|
||||
public static final String ROUTE_TRACK = "route_track";
|
||||
public static final int POPULAR_ARTICLES_SEARCH_RADIUS = 100000;
|
||||
public static final int ARTICLE_SEARCH_RADIUS = 50000;
|
||||
public static final int GPX_TRACKS_SEARCH_RADIUS = 10000;
|
||||
public static final int MAX_POPULAR_ARTICLES_COUNT = 30;
|
||||
public static final String REF_TAG = "ref";
|
||||
public static final String NAME_TAG = "name";
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final Collator collator;
|
||||
|
@ -91,47 +107,69 @@ public class TravelObfHelper implements TravelHelper {
|
|||
public synchronized List<TravelArticle> loadPopularArticles() {
|
||||
String lang = app.getLanguage();
|
||||
List<TravelArticle> popularArticles = new ArrayList<>();
|
||||
for (BinaryMapIndexReader reader : getReaders()) {
|
||||
final List<Pair<File, Amenity>> amenities = new ArrayList<>();
|
||||
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
|
||||
for (final BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
location, POPULAR_ARTICLES_SEARCH_RADIUS, -1, getSearchFilter(false), null);
|
||||
List<Amenity> amenities = reader.searchPoi(req);
|
||||
if (amenities.size() > 0) {
|
||||
Collections.sort(amenities, new Comparator<Amenity>() {
|
||||
@Override
|
||||
public int compare(Amenity a1, Amenity a2) {
|
||||
int d1 = (int) (MapUtils.getDistance(a1.getLocation().getLatitude(), a1.getLocation().getLongitude(),
|
||||
location.getLatitude(), location.getLongitude()));
|
||||
int d2 = (int) (MapUtils.getDistance(a2.getLocation().getLatitude(), a2.getLocation().getLongitude(),
|
||||
location.getLatitude(), location.getLongitude()));
|
||||
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
|
||||
}
|
||||
});
|
||||
for (Amenity amenity : amenities) {
|
||||
if (!Algorithms.isEmpty(amenity.getName(lang))) {
|
||||
TravelArticle article = cacheTravelArticles(reader.getFile(), amenity, lang, false, null);
|
||||
if (article != null) {
|
||||
popularArticles.add(article);
|
||||
if (popularArticles.size() >= MAX_POPULAR_ARTICLES_COUNT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
searchAmenity(amenities, location, reader, POPULAR_ARTICLES_SEARCH_RADIUS, -1, ROUTE_ARTICLE);
|
||||
searchAmenity(amenities, location, reader, GPX_TRACKS_SEARCH_RADIUS, 15, ROUTE_TRACK);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (amenities.size() > 0) {
|
||||
Collections.sort(amenities, new Comparator<Pair<File, Amenity>>() {
|
||||
@Override
|
||||
public int compare(Pair article1, Pair article2) {
|
||||
int d1 = (int) (MapUtils.getDistance(((Amenity) article1.second).getLocation(), location));
|
||||
int d2 = (int) (MapUtils.getDistance(((Amenity) article2.second).getLocation(), location));
|
||||
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
|
||||
}
|
||||
});
|
||||
for (Pair<File, Amenity> amenity : amenities) {
|
||||
if (!Algorithms.isEmpty(amenity.second.getName(lang))) {
|
||||
TravelArticle article = cacheTravelArticles(amenity.first, amenity.second, lang, false, null);
|
||||
if (article != null) {
|
||||
popularArticles.add(article);
|
||||
if (popularArticles.size() >= MAX_POPULAR_ARTICLES_COUNT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
this.popularArticles = popularArticles;
|
||||
return popularArticles;
|
||||
}
|
||||
|
||||
private void searchAmenity(final List<Pair<File, Amenity>> amenitiesList, LatLon location,
|
||||
final BinaryMapIndexReader reader, int searchRadius, int zoom,
|
||||
String searchFilter) throws IOException {
|
||||
reader.searchPoi(BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
location, searchRadius, zoom, getSearchFilter(searchFilter), new ResultMatcher<Amenity>() {
|
||||
@Override
|
||||
public boolean publish(Amenity object) {
|
||||
amenitiesList.add(new Pair<>(reader.getFile(), object));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TravelArticle cacheTravelArticles(File file, Amenity amenity, String lang, boolean readPoints, @Nullable GpxReadCallback callback) {
|
||||
TravelArticle article = null;
|
||||
Map<String, TravelArticle> articles = readArticles(file, amenity);
|
||||
Map<String, TravelArticle> articles;
|
||||
if (ROUTE_TRACK.equals(amenity.getSubType())) {
|
||||
articles = readRoutePoint(file, amenity);
|
||||
} else {
|
||||
articles = readArticles(file, amenity);
|
||||
}
|
||||
if (!Algorithms.isEmpty(articles)) {
|
||||
TravelArticleIdentifier newArticleId = articles.values().iterator().next().generateIdentifier();
|
||||
cachedArticles.put(newArticleId, articles);
|
||||
|
@ -140,12 +178,41 @@ public class TravelObfHelper implements TravelHelper {
|
|||
return article;
|
||||
}
|
||||
|
||||
private Map<String, TravelArticle> readRoutePoint(File file, Amenity amenity) {
|
||||
Map<String, TravelArticle> articles = new HashMap<>();
|
||||
TravelGpx res = new TravelGpx();
|
||||
res.file = file;
|
||||
String title = amenity.getName("en");
|
||||
res.title = createTitle(Algorithms.isEmpty(title) ? amenity.getName() : title);
|
||||
res.lat = amenity.getLocation().getLatitude();
|
||||
res.lon = amenity.getLocation().getLongitude();
|
||||
res.routeId = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID));
|
||||
try {
|
||||
res.totalDistance = Float.parseFloat(Algorithms.emptyIfNull(amenity.getTagContent(DISTANCE)));
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.debug(e.getMessage(), e);
|
||||
}
|
||||
try {
|
||||
res.diffElevationUp = Double.parseDouble(Algorithms.emptyIfNull(amenity.getTagContent(DIFF_ELE_UP)));
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.debug(e.getMessage(), e);
|
||||
}
|
||||
try {
|
||||
res.diffElevationDown = Double.parseDouble(Algorithms.emptyIfNull(amenity.getTagContent(DIFF_ELE_DOWN)));
|
||||
} catch (NumberFormatException e) {
|
||||
LOG.debug(e.getMessage(), e);
|
||||
}
|
||||
res.user = Algorithms.emptyIfNull(amenity.getTagContent(USER));
|
||||
articles.put("en", res);
|
||||
return articles;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private SearchPoiTypeFilter getSearchFilter(final boolean articlePoints) {
|
||||
private SearchPoiTypeFilter getSearchFilter(final String filterSubcategory) {
|
||||
return new SearchPoiTypeFilter() {
|
||||
@Override
|
||||
public boolean accept(PoiCategory type, String subcategory) {
|
||||
return subcategory.equals(articlePoints ? ROUTE_ARTICLE_POINT : ROUTE_ARTICLE);
|
||||
return subcategory.equals(filterSubcategory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -176,9 +243,9 @@ public class TravelObfHelper implements TravelHelper {
|
|||
res.isParentOf = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.IS_PARENT_OF, lang));
|
||||
res.lat = amenity.getLocation().getLatitude();
|
||||
res.lon = amenity.getLocation().getLongitude();
|
||||
res.imageTitle = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.IMAGE_TITLE, null));
|
||||
res.routeId = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID, null));
|
||||
res.routeSource = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_SOURCE, null));
|
||||
res.imageTitle = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.IMAGE_TITLE));
|
||||
res.routeId = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID));
|
||||
res.routeSource = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_SOURCE));
|
||||
res.originalId = 0;
|
||||
res.lang = lang;
|
||||
res.contentsJson = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.CONTENT_JSON, lang));
|
||||
|
@ -186,6 +253,82 @@ public class TravelObfHelper implements TravelHelper {
|
|||
return res;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GPXFile buildTravelGpxFile(@NonNull final TravelGpx article) {
|
||||
String routeId = article.getRouteId();
|
||||
final String ref = routeId.substring(routeId.length() - 3);
|
||||
final List<BinaryMapDataObject> segmentList = new ArrayList<>();
|
||||
|
||||
for (BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
if (article.file != null && !article.file.equals(reader.getFile())) {
|
||||
continue;
|
||||
}
|
||||
BinaryMapIndexReader.SearchRequest<BinaryMapDataObject> sr = BinaryMapIndexReader.buildSearchRequest(
|
||||
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, 15, null,
|
||||
new ResultMatcher<BinaryMapDataObject>() {
|
||||
@Override
|
||||
public boolean publish(BinaryMapDataObject object) {
|
||||
if (object.getPointsLength() > 1) {
|
||||
if (getTagValue(object, REF_TAG).equals(ref)
|
||||
&& createTitle(getTagValue(object, NAME_TAG)).equals(article.title)) {
|
||||
segmentList.add(object);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
reader.searchMapIndex(sr);
|
||||
if (!Algorithms.isEmpty(segmentList)) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
GPXFile gpxFile = null;
|
||||
if (!segmentList.isEmpty()) {
|
||||
Track track = new Track();
|
||||
for (BinaryMapDataObject segment : segmentList) {
|
||||
TrkSegment trkSegment = new TrkSegment();
|
||||
for (int i = 0; i < segment.getPointsLength(); i++) {
|
||||
WptPt point = new WptPt();
|
||||
point.lat = MapUtils.get31LatitudeY(segment.getPoint31YTile(i));
|
||||
point.lon = MapUtils.get31LongitudeX(segment.getPoint31XTile(i));
|
||||
trkSegment.points.add(point);
|
||||
}
|
||||
track.segments.add(trkSegment);
|
||||
}
|
||||
gpxFile = new GPXFile(article.getTitle(), article.getLang(), "");
|
||||
gpxFile.tracks = new ArrayList<>();
|
||||
gpxFile.tracks.add(track);
|
||||
}
|
||||
article.gpxFile = gpxFile;
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
private String getTagValue(BinaryMapDataObject object, String tag) {
|
||||
BinaryMapIndexReader.MapIndex mi = object.getMapIndex();
|
||||
TIntObjectIterator<String> it = object.getObjectNames().iterator();
|
||||
while (it.hasNext()) {
|
||||
it.advance();
|
||||
BinaryMapIndexReader.TagValuePair tp = mi.decodeType(it.key());
|
||||
if (tp.tag.equals(tag)) {
|
||||
return it.value();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String createTitle(String name) {
|
||||
return capitalizeFirstLetter(getGpxTitle(name));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private synchronized List<Amenity> getPointList(@NonNull final TravelArticle article) {
|
||||
final List<Amenity> pointList = new ArrayList<>();
|
||||
|
@ -197,14 +340,14 @@ public class TravelObfHelper implements TravelHelper {
|
|||
}
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(0, 0,
|
||||
Algorithms.emptyIfNull(article.title), 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
|
||||
getSearchFilter(true), new ResultMatcher<Amenity>() {
|
||||
getSearchFilter(ROUTE_ARTICLE_POINT), new ResultMatcher<Amenity>() {
|
||||
|
||||
@Override
|
||||
public boolean publish(Amenity amenity) {
|
||||
String amenityLang = amenity.getTagSuffix(Amenity.LANG_YES + ":");
|
||||
if (Algorithms.stringsEqual(lang, amenityLang)
|
||||
&& Algorithms.stringsEqual(article.routeId,
|
||||
Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID, null)))) {
|
||||
Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID)))) {
|
||||
pointList.add(amenity);
|
||||
}
|
||||
return false;
|
||||
|
@ -246,7 +389,7 @@ public class TravelObfHelper implements TravelHelper {
|
|||
}
|
||||
String category = amenity.getTagSuffix("category_");
|
||||
if (category != null) {
|
||||
wptPt.category = Algorithms.capitalizeFirstLetter(category);
|
||||
wptPt.category = capitalizeFirstLetter(category);
|
||||
}
|
||||
return wptPt;
|
||||
}
|
||||
|
@ -266,7 +409,7 @@ public class TravelObfHelper implements TravelHelper {
|
|||
for (BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
SearchRequest<Amenity> searchRequest = BinaryMapIndexReader.buildSearchPoiRequest(0, 0, searchQuery,
|
||||
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchFilter(false), new ResultMatcher<Amenity>() {
|
||||
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchFilter(ROUTE_ARTICLE), new ResultMatcher<Amenity>() {
|
||||
@Override
|
||||
public boolean publish(Amenity object) {
|
||||
List<String> otherNames = object.getAllNames(false);
|
||||
|
@ -441,7 +584,7 @@ public class TravelObfHelper implements TravelHelper {
|
|||
for (BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
0, 0, title, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchFilter(false),
|
||||
0, 0, title, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, getSearchFilter(ROUTE_ARTICLE),
|
||||
new ResultMatcher<Amenity>() {
|
||||
boolean done = false;
|
||||
|
||||
|
@ -530,12 +673,13 @@ public class TravelObfHelper implements TravelHelper {
|
|||
}
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(0, 0,
|
||||
Algorithms.emptyIfNull(articleId.title), 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE,
|
||||
getSearchFilter(false), new ResultMatcher<Amenity>() {
|
||||
getSearchFilter(ROUTE_ARTICLE), new ResultMatcher<Amenity>() {
|
||||
boolean done = false;
|
||||
|
||||
@Override
|
||||
public boolean publish(Amenity amenity) {
|
||||
if (Algorithms.stringsEqual(articleId.routeId, Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID, null))) || isDbArticle) {
|
||||
if (Algorithms.stringsEqual(articleId.routeId,
|
||||
Algorithms.emptyIfNull(amenity.getTagContent(Amenity.ROUTE_ID))) || isDbArticle) {
|
||||
amenities.add(amenity);
|
||||
done = true;
|
||||
}
|
||||
|
@ -606,7 +750,7 @@ public class TravelObfHelper implements TravelHelper {
|
|||
for (BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
SearchRequest<Amenity> req = BinaryMapIndexReader.buildSearchPoiRequest(
|
||||
x, y, title, left, right, top, bottom, getSearchFilter(false),
|
||||
x, y, title, left, right, top, bottom, getSearchFilter(ROUTE_ARTICLE),
|
||||
new ResultMatcher<Amenity>() {
|
||||
boolean done = false;
|
||||
|
||||
|
@ -693,7 +837,12 @@ public class TravelObfHelper implements TravelHelper {
|
|||
@NonNull
|
||||
@Override
|
||||
public File createGpxFile(@NonNull TravelArticle article) {
|
||||
final GPXFile gpx = article.getGpxFile();
|
||||
final GPXFile gpx;
|
||||
if (article instanceof TravelGpx) {
|
||||
gpx = buildTravelGpxFile((TravelGpx) article);
|
||||
} else {
|
||||
gpx = article.getGpxFile();
|
||||
}
|
||||
File file = app.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
|
||||
writeGpxFile(file, gpx);
|
||||
return file;
|
||||
|
|
|
@ -20,6 +20,8 @@ import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard;
|
|||
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard.StartEditingTravelVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard.DownloadUpdateVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard.TravelGpxVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard.NeededMapsVH;
|
||||
|
||||
|
@ -48,6 +50,9 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
case ArticleTravelCard.TYPE:
|
||||
return new ArticleTravelVH(inflate(parent, R.layout.wikivoyage_article_card));
|
||||
|
||||
case TravelGpxCard.TYPE:
|
||||
return new TravelGpxVH(inflate(parent, R.layout.wikivoyage_travel_gpx_card));
|
||||
|
||||
case TravelDownloadUpdateCard.TYPE:
|
||||
return new DownloadUpdateVH(inflate(parent, R.layout.travel_download_update_card));
|
||||
|
||||
|
@ -74,6 +79,10 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
HeaderTravelCard headerTravelCard = (HeaderTravelCard) item;
|
||||
headerTravelCard.setArticleItemCount(getArticleItemCount());
|
||||
headerTravelCard.bindViewHolder(viewHolder);
|
||||
} else if (viewHolder instanceof ArticleTravelVH && item instanceof TravelGpxCard) {
|
||||
TravelGpxCard travelGpxCard = (TravelGpxCard) item;
|
||||
travelGpxCard.setLastItem(position == getLastArticleItemIndex());
|
||||
travelGpxCard.bindViewHolder(viewHolder);
|
||||
} else if (viewHolder instanceof ArticleTravelVH && item instanceof ArticleTravelCard) {
|
||||
ArticleTravelCard articleTravelCard = (ArticleTravelCard) item;
|
||||
articleTravelCard.setLastItem(position == getLastArticleItemIndex());
|
||||
|
@ -96,7 +105,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
public int getArticleItemCount() {
|
||||
int count = 0;
|
||||
for (BaseTravelCard o : items) {
|
||||
if (o instanceof ArticleTravelCard) {
|
||||
if (o instanceof ArticleTravelCard || o instanceof TravelGpxCard) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +115,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
private int getLastArticleItemIndex() {
|
||||
for (int i = items.size() - 1; i > 0; i--) {
|
||||
BaseTravelCard o = items.get(i);
|
||||
if (o instanceof ArticleTravelCard) {
|
||||
if (o instanceof ArticleTravelCard || o instanceof TravelGpxCard) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import net.osmand.plus.download.DownloadResources;
|
|||
import net.osmand.plus.download.DownloadValidationManager;
|
||||
import net.osmand.plus.download.IndexItem;
|
||||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||
import net.osmand.plus.wikivoyage.data.TravelGpx;
|
||||
import net.osmand.plus.wikivoyage.data.TravelHelper;
|
||||
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.ArticleTravelCard;
|
||||
|
@ -37,6 +38,7 @@ import net.osmand.plus.wikivoyage.explore.travelcards.HeaderTravelCard;
|
|||
import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -178,17 +180,21 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
|
||||
List<TravelArticle> popularArticles = app.getTravelHelper().getPopularArticles();
|
||||
for (TravelArticle article : popularArticles) {
|
||||
items.add(new ArticleTravelCard(app, nightMode, article, activity.getSupportFragmentManager()));
|
||||
if (article instanceof TravelGpx) {
|
||||
items.add(new TravelGpxCard(app, nightMode, (TravelGpx) article, getActivity()));
|
||||
} else {
|
||||
items.add(new ArticleTravelCard(app, nightMode, article, activity.getSupportFragmentManager()));
|
||||
}
|
||||
}
|
||||
items.add(new StartEditingTravelCard(activity, nightMode));
|
||||
adapter.setItems(items);
|
||||
final DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||
if (!downloadThread.getIndexes().isDownloadedFromInternet) {
|
||||
waitForIndexes = true;
|
||||
downloadThread.runReloadIndexFilesSilent();
|
||||
} else {
|
||||
checkDownloadIndexes();
|
||||
}
|
||||
}
|
||||
items.add(new StartEditingTravelCard(activity, nightMode));
|
||||
adapter.setItems(items);
|
||||
final DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||
if (!downloadThread.getIndexes().isDownloadedFromInternet) {
|
||||
waitForIndexes = true;
|
||||
downloadThread.runReloadIndexFilesSilent();
|
||||
} else {
|
||||
checkDownloadIndexes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
@ -16,16 +18,20 @@ 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.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.widgets.tools.CropCircleTransformation;
|
||||
import net.osmand.plus.wikipedia.WikiArticleHelper;
|
||||
import net.osmand.plus.wikivoyage.WikivoyageUtils;
|
||||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||
import net.osmand.plus.wikivoyage.data.TravelGpx;
|
||||
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -33,7 +39,8 @@ import java.util.List;
|
|||
public class SavedArticlesRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private static final int HEADER_TYPE = 0;
|
||||
private static final int ITEM_TYPE = 1;
|
||||
private static final int ARTICLE_TYPE = 1;
|
||||
private static final int GPX_TYPE = 2;
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final OsmandSettings settings;
|
||||
|
@ -45,6 +52,7 @@ public class SavedArticlesRvAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
|||
private final Drawable readIcon;
|
||||
private final Drawable deleteIcon;
|
||||
private PicassoUtils picasso;
|
||||
boolean nightMode;
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
|
@ -54,21 +62,34 @@ public class SavedArticlesRvAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
|||
this.app = app;
|
||||
this.settings = app.getSettings();
|
||||
picasso = PicassoUtils.getPicasso(app);
|
||||
nightMode = !app.getSettings().isLightContent();
|
||||
readIcon = getActiveIcon(R.drawable.ic_action_read_article);
|
||||
deleteIcon = getActiveIcon(R.drawable.ic_action_read_later_fill);
|
||||
}
|
||||
|
||||
int colorId = settings.isLightContent()
|
||||
? R.color.wikivoyage_active_light : R.color.wikivoyage_active_dark;
|
||||
UiUtilities ic = app.getUIUtilities();
|
||||
readIcon = ic.getIcon(R.drawable.ic_action_read_article, colorId);
|
||||
deleteIcon = ic.getIcon(R.drawable.ic_action_read_later_fill, colorId);
|
||||
private Drawable getActiveIcon(@DrawableRes int iconId) {
|
||||
int colorId = nightMode ? R.color.wikivoyage_active_dark : R.color.wikivoyage_active_light;
|
||||
return app.getUIUtilities().getIcon(iconId, colorId);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
boolean header = viewType == HEADER_TYPE;
|
||||
int layoutId = header ? R.layout.wikivoyage_list_header : R.layout.wikivoyage_article_card;
|
||||
View itemView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
|
||||
return header ? new HeaderVH(itemView) : new ItemVH(itemView);
|
||||
switch (viewType) {
|
||||
case HEADER_TYPE:
|
||||
return new HeaderVH(inflate(parent, R.layout.wikivoyage_list_header));
|
||||
case ARTICLE_TYPE:
|
||||
return new ItemVH(inflate(parent, R.layout.wikivoyage_article_card));
|
||||
case GPX_TYPE:
|
||||
return new TravelGpxCard.TravelGpxVH(inflate(parent, R.layout.wikivoyage_travel_gpx_card));
|
||||
default:
|
||||
throw new RuntimeException("Unsupported view type: " + viewType);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private View inflate(@NonNull ViewGroup parent, @LayoutRes int layoutId) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,7 +98,7 @@ public class SavedArticlesRvAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
|||
final HeaderVH holder = (HeaderVH) viewHolder;
|
||||
holder.title.setText((String) getItem(position));
|
||||
holder.description.setText(String.valueOf(items.size() - 1));
|
||||
} else {
|
||||
} else if (viewHolder instanceof ItemVH) {
|
||||
final ItemVH holder = (ItemVH) viewHolder;
|
||||
TravelArticle article = (TravelArticle) getItem(position);
|
||||
final String url = TravelArticle.getImageUrl(article.getImageTitle(), false);
|
||||
|
@ -111,6 +132,52 @@ public class SavedArticlesRvAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
|||
holder.rightButton.setCompoundDrawablesWithIntrinsicBounds(null, null, deleteIcon, null);
|
||||
holder.divider.setVisibility(lastItem ? View.GONE : View.VISIBLE);
|
||||
holder.shadow.setVisibility(lastItem ? View.VISIBLE : View.GONE);
|
||||
} else if (viewHolder instanceof TravelGpxCard.TravelGpxVH) {
|
||||
final TravelGpx article = (TravelGpx) getItem(position);
|
||||
final TravelGpxCard.TravelGpxVH holder = (TravelGpxCard.TravelGpxVH) viewHolder;
|
||||
holder.title.setText(article.getTitle());
|
||||
Drawable icon = getActiveIcon(R.drawable.ic_action_user_account_16);
|
||||
holder.user.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
|
||||
holder.user.setText(WikiArticleHelper.getPartialContent(article.user));
|
||||
AndroidUtils.setBackground(app, holder.user, nightMode, R.drawable.btn_border_bg_light, R.drawable.btn_border_bg_dark);
|
||||
holder.distance.setText(OsmAndFormatter.getFormattedDistance(article.totalDistance, app));
|
||||
holder.diffElevationUp.setText(OsmAndFormatter.getFormattedAlt(article.diffElevationUp, app));
|
||||
holder.diffElevationDown.setText(OsmAndFormatter.getFormattedAlt(article.diffElevationDown, app));
|
||||
holder.leftButton.setText(app.getString(R.string.shared_string_view));
|
||||
View.OnClickListener readClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.openArticle(article);
|
||||
}
|
||||
}
|
||||
};
|
||||
holder.leftButton.setOnClickListener(readClickListener);
|
||||
holder.itemView.setOnClickListener(readClickListener);
|
||||
holder.leftButton.setCompoundDrawablesWithIntrinsicBounds(readIcon, null, null, null);
|
||||
updateSaveButton(holder, article);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSaveButton(final TravelGpxCard.TravelGpxVH holder, final TravelGpx article) {
|
||||
if (article != null) {
|
||||
final TravelLocalDataHelper helper = app.getTravelHelper().getBookmarksHelper();
|
||||
final boolean saved = helper.isArticleSaved(article);
|
||||
Drawable icon = getActiveIcon(saved ? R.drawable.ic_action_read_later_fill : R.drawable.ic_action_read_later);
|
||||
holder.rightButton.setText(saved ? R.string.shared_string_remove : R.string.shared_string_save);
|
||||
holder.rightButton.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null);
|
||||
holder.rightButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (saved) {
|
||||
helper.removeArticleFromSaved(article);
|
||||
} else {
|
||||
app.getTravelHelper().createGpxFile(article);
|
||||
helper.addArticleToSaved(article);
|
||||
}
|
||||
updateSaveButton(holder, article);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,8 +185,10 @@ public class SavedArticlesRvAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
|||
public int getItemViewType(int position) {
|
||||
if (getItem(position) instanceof String) {
|
||||
return HEADER_TYPE;
|
||||
} else if (getItem(position) instanceof TravelGpx) {
|
||||
return GPX_TYPE;
|
||||
}
|
||||
return ITEM_TYPE;
|
||||
return ARTICLE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.view.ViewGroup;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
@ -17,12 +18,15 @@ import net.osmand.PlatformUtil;
|
|||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.track.TrackMenuFragment;
|
||||
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
|
||||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||
import net.osmand.plus.wikivoyage.data.TravelGpx;
|
||||
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -48,9 +52,17 @@ public class SavedArticlesTabFragment extends BaseOsmAndFragment implements Trav
|
|||
adapter.setListener(new SavedArticlesRvAdapter.Listener() {
|
||||
@Override
|
||||
public void openArticle(TravelArticle article) {
|
||||
FragmentManager fm = getFragmentManager();
|
||||
if (fm != null) {
|
||||
WikivoyageArticleDialogFragment.showInstance(app, fm, article.generateIdentifier(), article.getLang());
|
||||
if (article instanceof TravelGpx) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
File file = app.getTravelHelper().createGpxFile(article);
|
||||
TrackMenuFragment.openTrack(getActivity(), file, null);
|
||||
}
|
||||
} else {
|
||||
FragmentManager fm = getFragmentManager();
|
||||
if (fm != null) {
|
||||
WikivoyageArticleDialogFragment.showInstance(app, fm, article.generateIdentifier(), article.getLang());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package net.osmand.plus.wikivoyage.explore.travelcards;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.track.TrackMenuFragment;
|
||||
import net.osmand.plus.wikivoyage.data.TravelGpx;
|
||||
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class TravelGpxCard extends BaseTravelCard {
|
||||
|
||||
public static final int TYPE = 3;
|
||||
|
||||
private final TravelGpx article;
|
||||
private final Drawable readIcon;
|
||||
private final FragmentActivity activity;
|
||||
private boolean isLastItem;
|
||||
|
||||
public TravelGpxCard(@NonNull OsmandApplication app, boolean nightMode, @NonNull TravelGpx article,
|
||||
@NonNull FragmentActivity activity) {
|
||||
super(app, nightMode);
|
||||
this.article = article;
|
||||
readIcon = getActiveIcon(R.drawable.ic_action_read_article);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
if (viewHolder instanceof TravelGpxVH) {
|
||||
final TravelGpxVH holder = (TravelGpxVH) viewHolder;
|
||||
holder.title.setText(article.getTitle());
|
||||
Drawable icon = getActiveIcon(R.drawable.ic_action_user_account_16);
|
||||
holder.user.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
|
||||
holder.user.setText(article.user);
|
||||
AndroidUtils.setBackground(app, holder.user, nightMode, R.drawable.btn_border_bg_light, R.drawable.btn_border_bg_dark);
|
||||
holder.distance.setText(OsmAndFormatter.getFormattedDistance(article.totalDistance, app));
|
||||
holder.diffElevationUp.setText(OsmAndFormatter.getFormattedAlt(article.diffElevationUp, app));
|
||||
holder.diffElevationDown.setText(OsmAndFormatter.getFormattedAlt(article.diffElevationDown, app));
|
||||
holder.leftButton.setText(app.getString(R.string.shared_string_view));
|
||||
View.OnClickListener readClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (activity != null) {
|
||||
File file = app.getTravelHelper().createGpxFile(article);
|
||||
TrackMenuFragment.openTrack(activity, file, null);
|
||||
}
|
||||
}
|
||||
};
|
||||
holder.leftButton.setOnClickListener(readClickListener);
|
||||
holder.itemView.setOnClickListener(readClickListener);
|
||||
holder.leftButton.setCompoundDrawablesWithIntrinsicBounds(readIcon, null, null, null);
|
||||
updateSaveButton(holder);
|
||||
holder.divider.setVisibility(isLastItem ? View.GONE : View.VISIBLE);
|
||||
holder.shadow.setVisibility(isLastItem ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSaveButton(final TravelGpxVH holder) {
|
||||
if (article != null) {
|
||||
final TravelLocalDataHelper helper = app.getTravelHelper().getBookmarksHelper();
|
||||
final boolean saved = helper.isArticleSaved(article);
|
||||
Drawable icon = getActiveIcon(saved ? R.drawable.ic_action_read_later_fill : R.drawable.ic_action_read_later);
|
||||
holder.rightButton.setText(saved ? R.string.shared_string_remove : R.string.shared_string_save);
|
||||
holder.rightButton.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null);
|
||||
holder.rightButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (saved) {
|
||||
helper.removeArticleFromSaved(article);
|
||||
} else {
|
||||
app.getTravelHelper().createGpxFile(article);
|
||||
helper.addArticleToSaved(article);
|
||||
}
|
||||
updateSaveButton(holder);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class TravelGpxVH extends RecyclerView.ViewHolder {
|
||||
|
||||
public final TextView title;
|
||||
public final TextView user;
|
||||
public final TextView distance;
|
||||
public final TextView diffElevationUp;
|
||||
public final TextView diffElevationDown;
|
||||
public final TextView leftButton;
|
||||
public final TextView rightButton;
|
||||
public final View divider;
|
||||
public final View shadow;
|
||||
|
||||
public TravelGpxVH(final View itemView) {
|
||||
super(itemView);
|
||||
title = itemView.findViewById(R.id.title);
|
||||
user = itemView.findViewById(R.id.user_name);
|
||||
distance = itemView.findViewById(R.id.distance);
|
||||
diffElevationUp = itemView.findViewById(R.id.diff_ele_up);
|
||||
diffElevationDown = itemView.findViewById(R.id.diff_ele_down);
|
||||
leftButton = itemView.findViewById(R.id.left_button);
|
||||
rightButton = itemView.findViewById(R.id.right_button);
|
||||
divider = itemView.findViewById(R.id.divider);
|
||||
shadow = itemView.findViewById(R.id.shadow);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLastItem(boolean lastItem) {
|
||||
isLastItem = lastItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardType() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
|
@ -21,4 +21,4 @@
|
|||
# UPDATE 3: Turn on D8 to recover builds with new gradle 6.5 and pluigin 4.1.1
|
||||
#android.enableD8=false
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
android.useAndroidX=true
|
Loading…
Reference in a new issue