add block statistics;
show current recording status; many fixes; the basis is prepared for the implementation of the functionality
This commit is contained in:
parent
1c8fcefcc0
commit
4ec4279136
13 changed files with 750 additions and 188 deletions
6
OsmAnd/res/drawable-mdpi/btn_background_active_dark.xml
Normal file
6
OsmAnd/res/drawable-mdpi/btn_background_active_dark.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/active_buttons_and_links_bg_pressed_dark" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/inactive_buttons_and_links_bg_dark" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/inactive_buttons_and_links_bg_light" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<stroke android:width="1dp" android:color="@color/active_buttons_and_links_bg_pressed_dark" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<stroke android:width="1dp" android:color="@color/active_buttons_and_links_bg_pressed_light" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<stroke android:width="1dp" android:color="@color/inactive_buttons_and_links_bg_dark" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<stroke android:width="1dp" android:color="@color/inactive_buttons_and_links_bg_light" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
6
OsmAnd/res/drawable/btn_background_active_light.xml
Normal file
6
OsmAnd/res/drawable/btn_background_active_light.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/active_buttons_and_links_bg_pressed_light" />
|
||||||
|
<corners android:radius="3dp" />
|
||||||
|
</shape>
|
|
@ -1,10 +1,14 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@id/button_container"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/button_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
@ -15,18 +19,20 @@
|
||||||
android:paddingEnd="@dimen/content_padding_small"
|
android:paddingEnd="@dimen/content_padding_small"
|
||||||
android:paddingRight="@dimen/content_padding_small"
|
android:paddingRight="@dimen/content_padding_small"
|
||||||
android:paddingBottom="@dimen/text_margin_small"
|
android:paddingBottom="@dimen/text_margin_small"
|
||||||
tools:background="@drawable/dlg_btn_secondary_dark">
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:duplicateParentState="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<net.osmand.plus.widgets.TextViewEx
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:duplicateParentState="true"
|
||||||
android:letterSpacing="@dimen/description_letter_spacing"
|
android:letterSpacing="@dimen/description_letter_spacing"
|
||||||
android:textSize="@dimen/default_desc_text_size"
|
android:textSize="@dimen/default_desc_text_size"
|
||||||
osmand:typeface="@string/font_roboto_medium"
|
osmand:typeface="@string/font_roboto_medium"
|
||||||
|
@ -37,6 +43,7 @@
|
||||||
android:id="@+id/desc"
|
android:id="@+id/desc"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:duplicateParentState="true"
|
||||||
android:letterSpacing="@dimen/description_letter_spacing"
|
android:letterSpacing="@dimen/description_letter_spacing"
|
||||||
android:textColor="@color/text_color_secondary_light"
|
android:textColor="@color/text_color_secondary_light"
|
||||||
android:textSize="@dimen/default_desc_text_size"
|
android:textSize="@dimen/default_desc_text_size"
|
||||||
|
@ -53,7 +60,10 @@
|
||||||
android:layout_height="@dimen/map_widget_icon"
|
android:layout_height="@dimen/map_widget_icon"
|
||||||
android:layout_marginStart="@dimen/context_menu_padding_margin_large"
|
android:layout_marginStart="@dimen/context_menu_padding_margin_large"
|
||||||
android:layout_marginLeft="@dimen/context_menu_padding_margin_large"
|
android:layout_marginLeft="@dimen/context_menu_padding_margin_large"
|
||||||
|
android:duplicateParentState="true"
|
||||||
tools:srcCompat="@drawable/ic_action_appearance"
|
tools:srcCompat="@drawable/ic_action_appearance"
|
||||||
tools:tint="@color/icon_color_secondary_light" />
|
tools:tint="@color/icon_color_secondary_light" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
|
@ -30,14 +30,17 @@
|
||||||
osmand:typeface="@string/font_roboto_medium" />
|
osmand:typeface="@string/font_roboto_medium" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/status_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
android:gravity="end|center_vertical"
|
android:gravity="end|center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<net.osmand.plus.widgets.TextViewEx
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
android:id="@+id/status"
|
android:id="@+id/text_status"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:letterSpacing="@dimen/description_letter_spacing"
|
android:letterSpacing="@dimen/description_letter_spacing"
|
||||||
|
@ -74,12 +77,13 @@
|
||||||
android:id="@+id/show_track_on_map"
|
android:id="@+id/show_track_on_map"
|
||||||
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button"
|
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/context_menu_buttons_bottom_height"
|
||||||
android:layout_marginStart="@dimen/content_padding"
|
android:layout_marginStart="@dimen/content_padding"
|
||||||
android:layout_marginLeft="@dimen/content_padding"
|
android:layout_marginLeft="@dimen/content_padding"
|
||||||
android:layout_marginTop="@dimen/content_padding_half"
|
android:layout_marginTop="@dimen/content_padding_half"
|
||||||
android:layout_marginEnd="@dimen/content_padding"
|
android:layout_marginEnd="@dimen/content_padding"
|
||||||
android:layout_marginRight="@dimen/content_padding" />
|
android:layout_marginRight="@dimen/content_padding"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -28,6 +28,7 @@ import com.google.android.material.slider.Slider;
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.ValueHolder;
|
import net.osmand.ValueHolder;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
import net.osmand.plus.NavigationService;
|
import net.osmand.plus.NavigationService;
|
||||||
import net.osmand.plus.OsmAndFormatter;
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
import net.osmand.plus.OsmAndLocationProvider;
|
import net.osmand.plus.OsmAndLocationProvider;
|
||||||
|
@ -182,6 +183,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
private TextInfoWidget createMonitoringControl(final MapActivity map) {
|
private TextInfoWidget createMonitoringControl(final MapActivity map) {
|
||||||
monitoringControl = new TextInfoWidget(map) {
|
monitoringControl = new TextInfoWidget(map) {
|
||||||
long lastUpdateTime;
|
long lastUpdateTime;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateInfo(DrawSettings drawSettings) {
|
public boolean updateInfo(DrawSettings drawSettings) {
|
||||||
if (isSaving) {
|
if (isSaving) {
|
||||||
|
@ -318,8 +320,17 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void controlDialog(final Activity activity, final boolean showTrackSelection) {
|
public void controlDialog(final Activity activity, final boolean showTrackSelection) {
|
||||||
|
|
||||||
|
SavingTrackHelper helper = app.getSavingTrackHelper();
|
||||||
|
SelectedGpxFile selectedGpxFile = helper.getCurrentTrack();
|
||||||
|
boolean hasDataToSave = helper.hasDataToSave();
|
||||||
|
boolean wasTrackMonitored = settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
|
||||||
|
OsmAndLocationProvider locationProvider = app.getLocationProvider();
|
||||||
|
Location lastKnownLocation = locationProvider.getLastKnownLocation();
|
||||||
FragmentActivity fragmentActivity = (FragmentActivity) activity;
|
FragmentActivity fragmentActivity = (FragmentActivity) activity;
|
||||||
TripRecordingActiveBottomSheet.showInstance(fragmentActivity.getSupportFragmentManager());
|
TripRecordingActiveBottomSheet.showInstance(fragmentActivity.getSupportFragmentManager(),
|
||||||
|
selectedGpxFile, wasTrackMonitored, hasDataToSave, lastKnownLocation == null);
|
||||||
|
|
||||||
/*final boolean wasTrackMonitored = settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
|
/*final boolean wasTrackMonitored = settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
|
||||||
final boolean nightMode;
|
final boolean nightMode;
|
||||||
if (activity instanceof MapActivity) {
|
if (activity instanceof MapActivity) {
|
||||||
|
@ -418,7 +429,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
bld.show();
|
bld.show();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveCurrentTrack() {
|
public void saveCurrentTrack() {
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
package net.osmand.plus.monitoring;
|
package net.osmand.plus.monitoring;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -22,8 +26,12 @@ import androidx.appcompat.widget.AppCompatImageView;
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import net.osmand.plus.GpxSelectionHelper;
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.Location;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
|
import net.osmand.plus.OsmAndLocationProvider;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
import net.osmand.plus.UiUtilities;
|
import net.osmand.plus.UiUtilities;
|
||||||
|
@ -31,7 +39,9 @@ import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||||
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
|
||||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.helpers.FontCache;
|
||||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||||
|
import net.osmand.plus.track.GpxBlockStatisticsBuilder;
|
||||||
import net.osmand.plus.track.TrackAppearanceFragment;
|
import net.osmand.plus.track.TrackAppearanceFragment;
|
||||||
import net.osmand.plus.widgets.TextViewEx;
|
import net.osmand.plus.widgets.TextViewEx;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
@ -44,179 +54,205 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private OsmandSettings settings;
|
private OsmandSettings settings;
|
||||||
|
private SelectedGpxFile selectedGpxFile;
|
||||||
|
private GpxBlockStatisticsBuilder blockStatisticsBuilder;
|
||||||
|
private boolean wasTrackMonitored = false;
|
||||||
|
private boolean hasDataToSave = false;
|
||||||
|
private boolean searchingGPS = false;
|
||||||
|
|
||||||
|
private View statusContainer;
|
||||||
|
|
||||||
|
private final Handler handler = new Handler();
|
||||||
|
private Runnable updatingGPS;
|
||||||
|
|
||||||
|
public void setSelectedGpxFile(SelectedGpxFile selectedGpxFile) {
|
||||||
|
this.selectedGpxFile = selectedGpxFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWasTrackMonitored(boolean wasTrackMonitored) {
|
||||||
|
this.wasTrackMonitored = wasTrackMonitored;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasDataToSave(boolean hasDataToSave) {
|
||||||
|
this.hasDataToSave = hasDataToSave;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchingGPS(boolean searchingGPS) {
|
||||||
|
this.searchingGPS = searchingGPS;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createMenuItems(Bundle savedInstanceState) {
|
public void createMenuItems(Bundle savedInstanceState) {
|
||||||
app = requiredMyApplication();
|
app = requiredMyApplication();
|
||||||
settings = app.getSettings();
|
settings = app.getSettings();
|
||||||
Context context = requireContext();
|
LayoutInflater inflater = UiUtilities.getInflater(getContext(), nightMode);
|
||||||
|
|
||||||
LayoutInflater inflater = UiUtilities.getInflater(context, nightMode);
|
|
||||||
View itemView = inflater.inflate(R.layout.trip_recording_active_fragment, null, false);
|
View itemView = inflater.inflate(R.layout.trip_recording_active_fragment, null, false);
|
||||||
items.add(new BottomSheetItemWithDescription.Builder()
|
items.add(new BottomSheetItemWithDescription.Builder()
|
||||||
.setCustomView(itemView)
|
.setCustomView(itemView)
|
||||||
.create());
|
.create());
|
||||||
|
|
||||||
TextView statusTitle = itemView.findViewById(R.id.status);
|
|
||||||
statusTitle.setText(ItemType.SEARCHING_GPS.titleId);
|
|
||||||
statusTitle.setTextColor(ContextCompat.getColor(app, getSecondaryTextColorId()));
|
|
||||||
ImageView statusIcon = itemView.findViewById(R.id.icon_status);
|
|
||||||
Drawable statusDrawable = UiUtilities.tintDrawable(
|
|
||||||
AppCompatResources.getDrawable(app, ItemType.SEARCHING_GPS.iconId),
|
|
||||||
ContextCompat.getColor(app, nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light)
|
|
||||||
);
|
|
||||||
statusIcon.setImageDrawable(statusDrawable);
|
|
||||||
|
|
||||||
View buttonClear = itemView.findViewById(R.id.button_clear);
|
View buttonClear = itemView.findViewById(R.id.button_clear);
|
||||||
View buttonStart = itemView.findViewById(R.id.button_start);
|
View buttonStart = itemView.findViewById(R.id.button_start);
|
||||||
View buttonSave = itemView.findViewById(R.id.button_save);
|
View buttonSave = itemView.findViewById(R.id.button_save);
|
||||||
View buttonPause = itemView.findViewById(R.id.button_pause);
|
final View buttonPause = itemView.findViewById(R.id.button_pause);
|
||||||
View buttonStop = itemView.findViewById(R.id.button_stop);
|
View buttonStop = itemView.findViewById(R.id.button_stop);
|
||||||
|
|
||||||
createButton(buttonClear, ItemType.CLEAR_DATA, true, null);
|
createItem(buttonClear, ItemType.CLEAR_DATA, hasDataToSave, null);
|
||||||
createButton(buttonStart, ItemType.START_SEGMENT, true, null);
|
createItem(buttonStart, ItemType.START_SEGMENT, wasTrackMonitored, null);
|
||||||
createButton(buttonSave, ItemType.SAVE, true, "17 min. ago");
|
createItem(buttonSave, ItemType.SAVE, hasDataToSave, "...");
|
||||||
createButton(buttonPause, ItemType.PAUSE, true, null);
|
createItem(buttonPause, wasTrackMonitored ? ItemType.PAUSE : ItemType.RESUME, true, null);
|
||||||
createButton(buttonStop, ItemType.STOP, true, null);
|
createItem(buttonStop, ItemType.STOP, true, null);
|
||||||
|
|
||||||
LinearLayout showTrackOnMapView = itemView.findViewById(R.id.show_track_on_map);
|
statusContainer = itemView.findViewById(R.id.status_container);
|
||||||
TextView showTrackOnMapTitle = showTrackOnMapView.findViewById(R.id.title);
|
updateStatus();
|
||||||
showTrackOnMapTitle.setText(R.string.show_track_on_map);
|
|
||||||
|
|
||||||
ImageView trackAppearanceIcon = showTrackOnMapView.findViewById(R.id.icon_after_divider);
|
// todo example, need to check
|
||||||
|
buttonPause.findViewById(R.id.button_container).setOnClickListener(new View.OnClickListener() {
|
||||||
int color = settings.CURRENT_TRACK_COLOR.get();
|
|
||||||
String width = settings.CURRENT_TRACK_WIDTH.get();
|
|
||||||
boolean showArrows = settings.CURRENT_TRACK_SHOW_ARROWS.get();
|
|
||||||
Drawable drawable = TrackAppearanceFragment.getTrackIcon(app, width, showArrows, color);
|
|
||||||
|
|
||||||
trackAppearanceIcon.setImageDrawable(drawable);
|
|
||||||
trackAppearanceIcon.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
MapActivity mapActivity = getMapActivity();
|
boolean wasTrackMonitored = !settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
|
||||||
if (mapActivity != null) {
|
createItem(buttonPause, wasTrackMonitored ? ItemType.PAUSE : ItemType.RESUME, true, null);
|
||||||
hide();
|
TripRecordingActiveBottomSheet.this.wasTrackMonitored = wasTrackMonitored;
|
||||||
GpxSelectionHelper.SelectedGpxFile selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
|
settings.SAVE_GLOBAL_TRACK_TO_GPX.set(wasTrackMonitored);
|
||||||
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile, TripRecordingActiveBottomSheet.this);
|
updateStatus();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button);
|
RecyclerView statBlocks = itemView.findViewById(R.id.block_statistics);
|
||||||
|
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile, null);
|
||||||
|
blockStatisticsBuilder.setBlocksView(statBlocks);
|
||||||
|
blockStatisticsBuilder.initStatBlocks(null, ContextCompat.getColor(app, getActiveTextColorId(nightMode)), nightMode);
|
||||||
|
|
||||||
|
LinearLayout showTrackOnMapView = itemView.findViewById(R.id.show_track_on_map);
|
||||||
|
final LinearLayout basicItemBody = showTrackOnMapView.findViewById(R.id.basic_item_body);
|
||||||
|
|
||||||
|
TextView showTrackTitle = basicItemBody.findViewById(R.id.title);
|
||||||
|
showTrackTitle.setText(ItemType.SHOW_TRACK.getTitleId());
|
||||||
|
showTrackTitle.setTextColor(ContextCompat.getColor(app, getActiveIconColorId(nightMode)));
|
||||||
|
showTrackTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.default_desc_text_size));
|
||||||
|
Typeface typeface = FontCache.getFont(app, app.getResources().getString(R.string.font_roboto_medium));
|
||||||
|
showTrackTitle.setTypeface(typeface);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
float letterSpacing = AndroidUtils.getFloatValueFromRes(app, R.dimen.description_letter_spacing);
|
||||||
|
showTrackTitle.setLetterSpacing(letterSpacing);
|
||||||
|
}
|
||||||
|
final SwitchCompat showTrackOnMapButton = basicItemBody.findViewById(R.id.switch_button);
|
||||||
showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null);
|
showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null);
|
||||||
View basicItem = itemView.findViewById(R.id.basic_item_body);
|
UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT);
|
||||||
basicItem.setOnClickListener(new View.OnClickListener() {
|
|
||||||
|
final LinearLayout additionalButton = showTrackOnMapView.findViewById(R.id.additional_button);
|
||||||
|
View divider = additionalButton.getChildAt(0);
|
||||||
|
AndroidUiHelper.setVisibility(View.GONE, divider);
|
||||||
|
int marginS = app.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_small);
|
||||||
|
UiUtilities.setMargins(additionalButton, marginS, 0, 0, 0);
|
||||||
|
String width = settings.CURRENT_TRACK_WIDTH.get();
|
||||||
|
boolean showArrows = settings.CURRENT_TRACK_SHOW_ARROWS.get();
|
||||||
|
int color = settings.CURRENT_TRACK_COLOR.get();
|
||||||
|
Drawable appearanceDrawable = TrackAppearanceFragment.getTrackIcon(app, width, showArrows, color);
|
||||||
|
AppCompatImageView appearanceIcon = additionalButton.findViewById(R.id.icon_after_divider);
|
||||||
|
int marginTrackIconH = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
|
||||||
|
UiUtilities.setMargins(appearanceIcon, marginTrackIconH, 0, marginTrackIconH, 0);
|
||||||
|
appearanceIcon.setImageDrawable(appearanceDrawable);
|
||||||
|
additionalButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (showTrackOnMapButton.isChecked()) {
|
||||||
|
MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
hide();
|
||||||
|
SelectedGpxFile selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
|
||||||
|
TrackAppearanceFragment.showInstance(mapActivity, selectedGpxFile, TripRecordingActiveBottomSheet.this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
createItem(additionalButton, ItemType.APPEARANCE, showTrackOnMapButton.isChecked(), null);
|
||||||
|
setShowOnMapBackgroundInactive(basicItemBody, app, showTrackOnMapButton.isChecked(), nightMode);
|
||||||
|
basicItemBody.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
boolean checked = !showTrackOnMapButton.isChecked();
|
boolean checked = !showTrackOnMapButton.isChecked();
|
||||||
showTrackOnMapButton.setChecked(checked);
|
showTrackOnMapButton.setChecked(checked);
|
||||||
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), checked, false);
|
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), checked, false);
|
||||||
|
setShowOnMapBackgroundInactive(basicItemBody, app, checked, nightMode);
|
||||||
|
createItem(additionalButton, ItemType.APPEARANCE, checked, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createButton(View view, ItemType type, boolean enabled, @Nullable String description) {
|
private void updateStatus() {
|
||||||
|
TextView statusTitle = statusContainer.findViewById(R.id.text_status);
|
||||||
Context ctx = view.getContext();
|
AppCompatImageView statusIcon = statusContainer.findViewById(R.id.icon_status);
|
||||||
|
ItemType status = searchingGPS ? ItemType.SEARCHING_GPS : !wasTrackMonitored ? ItemType.ON_PAUSE : ItemType.RECORDING;
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
|
statusTitle.setText(status.getTitleId());
|
||||||
view.setBackground(AppCompatResources.getDrawable(ctx, nightMode ? R.drawable.dlg_btn_secondary_dark : R.drawable.dlg_btn_secondary_light));
|
int colorText = status.equals(ItemType.SEARCHING_GPS) ? getSecondaryTextColorId(nightMode) : getOsmandIconColorId(nightMode);
|
||||||
} else {
|
statusTitle.setTextColor(ContextCompat.getColor(app, colorText));
|
||||||
view.setBackgroundDrawable(AppCompatResources.getDrawable(ctx, nightMode ? R.drawable.dlg_btn_secondary_dark : R.drawable.dlg_btn_secondary_light));
|
int colorDrawable = ContextCompat.getColor(app,
|
||||||
|
status.equals(ItemType.SEARCHING_GPS) ? getSecondaryIconColorId(nightMode) : getOsmandIconColorId(nightMode));
|
||||||
|
Drawable statusDrawable = UiUtilities.tintDrawable(AppCompatResources.getDrawable(app, status.getIconId()), colorDrawable);
|
||||||
|
statusIcon.setImageDrawable(statusDrawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextViewEx title = view.findViewById(R.id.title);
|
private void createItem(View view, ItemType type, boolean enabled, @Nullable String description) {
|
||||||
TextViewEx desc = view.findViewById(R.id.desc);
|
view.setTag(type);
|
||||||
|
LinearLayout button = view.findViewById(R.id.button_container);
|
||||||
|
|
||||||
AppCompatImageView icon = view.findViewById(R.id.icon);
|
AppCompatImageView icon = view.findViewById(R.id.icon);
|
||||||
|
if (icon != null) {
|
||||||
|
type.setTintedIcon(icon, app, enabled, false, nightMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView title = view.findViewById(R.id.title);
|
||||||
|
if (title != null) {
|
||||||
title.setText(type.getTitleId());
|
title.setText(type.getTitleId());
|
||||||
title.setTextColor(ContextCompat.getColor(ctx, type == ItemType.CLEAR_DATA ? R.color.color_osm_edit_delete
|
type.setTextColor(title, app, enabled, false, nightMode);
|
||||||
: enabled ? getActiveTextColorId() : getSecondaryTextColorId()));
|
}
|
||||||
|
|
||||||
Drawable tintDrawable = UiUtilities.tintDrawable(
|
setItemBackgroundInactive(button != null ? button : (LinearLayout) view, app, nightMode);
|
||||||
AppCompatResources.getDrawable(ctx, type.iconId),
|
type.changeOnTouch(button != null ? button : (LinearLayout) view, icon, title, app, enabled, nightMode);
|
||||||
ContextCompat.getColor(ctx, type == ItemType.CLEAR_DATA ? R.color.color_osm_edit_delete
|
|
||||||
: enabled ? getActiveIconColorId() : getSecondaryIconColorId())
|
|
||||||
);
|
|
||||||
icon.setBackgroundDrawable(tintDrawable);
|
|
||||||
|
|
||||||
|
TextViewEx desc = view.findViewById(R.id.desc);
|
||||||
|
if (desc != null) {
|
||||||
boolean isShowDesc = !Algorithms.isBlank(description);
|
boolean isShowDesc = !Algorithms.isBlank(description);
|
||||||
int marginSingle = app.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
|
int marginDesc = isShowDesc ? 0 : app.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
|
||||||
AndroidUiHelper.updateVisibility(desc, isShowDesc);
|
AndroidUiHelper.updateVisibility(desc, isShowDesc);
|
||||||
UiUtilities.setMargins(title, 0, isShowDesc ? 0 : marginSingle, 0, isShowDesc ? 0 : marginSingle);
|
UiUtilities.setMargins(title, 0, marginDesc, 0, marginDesc);
|
||||||
desc.setText(description);
|
desc.setText(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ItemType {
|
|
||||||
SEARCHING_GPS(R.string.searching_gps, R.drawable.ic_action_gps_info),
|
|
||||||
RECORDING(R.string.recording_default_name, R.drawable.ic_action_track_recordable),
|
|
||||||
ON_PAUSE(R.string.on_pause, R.drawable.ic_pause),
|
|
||||||
CLEAR_DATA(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark),
|
|
||||||
START_SEGMENT(R.string.gpx_start_new_segment, R.drawable.ic_action_new_segment),
|
|
||||||
SAVE(R.string.shared_string_save, R.drawable.ic_action_save_to_file),
|
|
||||||
PAUSE(R.string.shared_string_pause, R.drawable.ic_pause),
|
|
||||||
STOP(R.string.shared_string_control_stop, R.drawable.ic_action_rec_stop);
|
|
||||||
|
|
||||||
@StringRes
|
|
||||||
private int titleId;
|
|
||||||
@DrawableRes
|
|
||||||
private int iconId;
|
|
||||||
|
|
||||||
ItemType(@StringRes int titleId, @DrawableRes int iconId) {
|
|
||||||
this.titleId = titleId;
|
|
||||||
this.iconId = iconId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTitleId() {
|
|
||||||
return titleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIconId() {
|
|
||||||
return iconId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorRes
|
|
||||||
protected int getActiveTextColorId() {
|
|
||||||
return nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorRes
|
|
||||||
protected int getSecondaryTextColorId() {
|
|
||||||
return nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorRes
|
|
||||||
protected int getActiveIconColorId() {
|
|
||||||
return nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorRes
|
|
||||||
protected int getSecondaryIconColorId() {
|
|
||||||
return nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ColorRes
|
|
||||||
protected int getOsmandIconColorId() {
|
|
||||||
return nightMode ? R.color.icon_color_osmand_dark : R.color.icon_color_osmand_light;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getDismissButtonHeight() {
|
public void onResume() {
|
||||||
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
|
super.onResume();
|
||||||
|
blockStatisticsBuilder.runUpdatingStatBlocks();
|
||||||
|
runUpdatingGPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getDismissButtonTextId() {
|
public void onPause() {
|
||||||
return R.string.shared_string_close;
|
super.onPause();
|
||||||
|
blockStatisticsBuilder.stopUpdatingStatBlocks();
|
||||||
|
stopUpdatingGPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stopUpdatingGPS() {
|
||||||
|
handler.removeCallbacks(updatingGPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runUpdatingGPS() {
|
||||||
|
updatingGPS = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean useVerticalButtons() {
|
public void run() {
|
||||||
return true;
|
int interval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
|
||||||
|
OsmAndLocationProvider locationProvider = app.getLocationProvider();
|
||||||
|
Location lastKnownLocation = locationProvider.getLastKnownLocation();
|
||||||
|
searchingGPS = lastKnownLocation == null;
|
||||||
|
updateStatus();
|
||||||
|
handler.postDelayed(this, Math.max(1000, interval));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.post(updatingGPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -235,9 +271,165 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showInstance(@NonNull FragmentManager fragmentManager) {
|
private static void setItemBackgroundActive(LinearLayout view, Context context, boolean nightMode) {
|
||||||
|
Drawable background = AppCompatResources.getDrawable(context,
|
||||||
|
nightMode ? R.drawable.btn_background_active_dark : R.drawable.btn_background_active_light);
|
||||||
|
view.setBackgroundDrawable(background);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setItemBackgroundInactive(LinearLayout view, Context context, boolean nightMode) {
|
||||||
|
Drawable background = AppCompatResources.getDrawable(context,
|
||||||
|
nightMode ? R.drawable.btn_background_inactive_dark : R.drawable.btn_background_inactive_light);
|
||||||
|
view.setBackgroundDrawable(background);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setShowOnMapBackgroundActive(LinearLayout view, Context context, boolean checked, boolean nightMode) {
|
||||||
|
Drawable background = AppCompatResources.getDrawable(context,
|
||||||
|
nightMode ? checked ? R.drawable.btn_background_active_dark : R.drawable.btn_background_stroked_active_dark
|
||||||
|
: checked ? R.drawable.btn_background_active_light : R.drawable.btn_background_stroked_active_light);
|
||||||
|
view.setBackgroundDrawable(background);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setShowOnMapBackgroundInactive(LinearLayout view, Context context, boolean checked, boolean nightMode) {
|
||||||
|
Drawable background = AppCompatResources.getDrawable(context,
|
||||||
|
nightMode ? checked ? R.drawable.btn_background_inactive_dark : R.drawable.btn_background_stroked_inactive_dark
|
||||||
|
: checked ? R.drawable.btn_background_inactive_light : R.drawable.btn_background_stroked_inactive_light);
|
||||||
|
view.setBackgroundDrawable(background);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ItemType {
|
||||||
|
SHOW_TRACK(R.string.shared_string_show_on_map, null),
|
||||||
|
APPEARANCE(null, null),
|
||||||
|
SEARCHING_GPS(R.string.searching_gps, R.drawable.ic_action_gps_info),
|
||||||
|
RECORDING(R.string.recording_default_name, R.drawable.ic_action_track_recordable),
|
||||||
|
ON_PAUSE(R.string.on_pause, R.drawable.ic_pause),
|
||||||
|
CLEAR_DATA(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark),
|
||||||
|
START_SEGMENT(R.string.gpx_start_new_segment, R.drawable.ic_action_new_segment),
|
||||||
|
SAVE(R.string.shared_string_save, R.drawable.ic_action_save_to_file),
|
||||||
|
PAUSE(R.string.shared_string_pause, R.drawable.ic_pause),
|
||||||
|
RESUME(R.string.shared_string_resume, R.drawable.ic_play_dark),
|
||||||
|
STOP(R.string.shared_string_control_stop, R.drawable.ic_action_rec_stop);
|
||||||
|
|
||||||
|
@StringRes
|
||||||
|
private final Integer titleId;
|
||||||
|
@DrawableRes
|
||||||
|
private final Integer iconId;
|
||||||
|
|
||||||
|
ItemType(@Nullable @StringRes Integer titleId, @Nullable @DrawableRes Integer iconId) {
|
||||||
|
this.titleId = titleId;
|
||||||
|
this.iconId = iconId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTitleId() {
|
||||||
|
return titleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getIconId() {
|
||||||
|
return iconId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextColor(TextView tv, Context context, boolean enabled, boolean pressed, boolean nightMode) {
|
||||||
|
if (tv != null) {
|
||||||
|
tv.setTextColor(ContextCompat.getColor(context,
|
||||||
|
enabled ? pressed ? getPressedColorId(nightMode)
|
||||||
|
: equals(ItemType.CLEAR_DATA) ? R.color.color_osm_edit_delete
|
||||||
|
: getActiveTextColorId(nightMode) : getSecondaryTextColorId(nightMode)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTintedIcon(AppCompatImageView iv, Context context, boolean enabled, boolean pressed, boolean nightMode) {
|
||||||
|
if (iv != null) {
|
||||||
|
int iconColor = ContextCompat.getColor(context,
|
||||||
|
enabled ? pressed ? getPressedColorId(nightMode)
|
||||||
|
: equals(ItemType.CLEAR_DATA) ? R.color.color_osm_edit_delete
|
||||||
|
: getActiveIconColorId(nightMode) : getSecondaryIconColorId(nightMode));
|
||||||
|
Drawable icon = UiUtilities.createTintedDrawable(context, iconId, iconColor);
|
||||||
|
iv.setImageDrawable(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private void changeOnTouch(final LinearLayout button, @Nullable final AppCompatImageView iv, @Nullable final TextView tv,
|
||||||
|
final Context context, final boolean enabled, final boolean nightMode) {
|
||||||
|
button.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
if (enabled) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN: {
|
||||||
|
setItemBackgroundActive(button, context, nightMode);
|
||||||
|
setTintedIcon(iv, context, enabled, true, nightMode);
|
||||||
|
setTextColor(tv, context, enabled, true, nightMode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_CANCEL: {
|
||||||
|
setItemBackgroundInactive(button, context, nightMode);
|
||||||
|
setTintedIcon(iv, context, enabled, false, nightMode);
|
||||||
|
setTextColor(tv, context, enabled, false, nightMode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
private static int getActiveTextColorId(boolean nightMode) {
|
||||||
|
return nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
private static int getSecondaryTextColorId(boolean nightMode) {
|
||||||
|
return nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
private static int getActiveIconColorId(boolean nightMode) {
|
||||||
|
return nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
private static int getSecondaryIconColorId(boolean nightMode) {
|
||||||
|
return nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
private static int getOsmandIconColorId(boolean nightMode) {
|
||||||
|
return nightMode ? R.color.icon_color_osmand_dark : R.color.icon_color_osmand_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorRes
|
||||||
|
private static int getPressedColorId(boolean nightMode) {
|
||||||
|
return nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getDismissButtonHeight() {
|
||||||
|
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getDismissButtonTextId() {
|
||||||
|
return R.string.shared_string_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useVerticalButtons() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showInstance(@NonNull FragmentManager fragmentManager, SelectedGpxFile selectedGpxFile,
|
||||||
|
boolean wasTrackMonitored, boolean hasDataToSave, boolean searchingGPS) {
|
||||||
if (!fragmentManager.isStateSaved()) {
|
if (!fragmentManager.isStateSaved()) {
|
||||||
TripRecordingActiveBottomSheet fragment = new TripRecordingActiveBottomSheet();
|
TripRecordingActiveBottomSheet fragment = new TripRecordingActiveBottomSheet();
|
||||||
|
fragment.setSelectedGpxFile(selectedGpxFile);
|
||||||
|
fragment.setWasTrackMonitored(wasTrackMonitored);
|
||||||
|
fragment.setHasDataToSave(hasDataToSave);
|
||||||
|
fragment.setSearchingGPS(searchingGPS);
|
||||||
fragment.show(fragmentManager, TAG);
|
fragment.show(fragmentManager, TAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
297
OsmAnd/src/net/osmand/plus/track/GpxBlockStatisticsBuilder.java
Normal file
297
OsmAnd/src/net/osmand/plus/track/GpxBlockStatisticsBuilder.java
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
package net.osmand.plus.track;
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.ColorRes;
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
|
import net.osmand.plus.OsmAndFormatter;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
|
||||||
|
import net.osmand.plus.myplaces.SegmentActionsListener;
|
||||||
|
import net.osmand.plus.widgets.TextViewEx;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
|
||||||
|
public class GpxBlockStatisticsBuilder {
|
||||||
|
|
||||||
|
private final OsmandApplication app;
|
||||||
|
private RecyclerView blocksView;
|
||||||
|
private final SelectedGpxFile selectedGpxFile;
|
||||||
|
private final TrackDisplayHelper displayHelper;
|
||||||
|
private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT};
|
||||||
|
|
||||||
|
private BlockStatisticsAdapter bsAdapter;
|
||||||
|
private final List<StatBlock> items = new ArrayList<>();
|
||||||
|
|
||||||
|
private final Handler handler = new Handler();
|
||||||
|
private Runnable updatingStats;
|
||||||
|
|
||||||
|
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile, TrackDisplayHelper displayHelper) {
|
||||||
|
this.app = app;
|
||||||
|
this.selectedGpxFile = selectedGpxFile;
|
||||||
|
this.displayHelper = displayHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlocksView(RecyclerView blocksView) {
|
||||||
|
this.blocksView = blocksView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GPXTrackAnalysis getAnalysis() {
|
||||||
|
return selectedGpxFile.getTrackAnalysis(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initStatBlocks(@Nullable SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
|
||||||
|
initItems();
|
||||||
|
if (Algorithms.isEmpty(items)) {
|
||||||
|
AndroidUiHelper.updateVisibility(blocksView, false);
|
||||||
|
} else {
|
||||||
|
bsAdapter = new BlockStatisticsAdapter(actionsListener, activeColor, nightMode);
|
||||||
|
bsAdapter.setItems(items);
|
||||||
|
blocksView.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false));
|
||||||
|
blocksView.setAdapter(bsAdapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopUpdatingStatBlocks() {
|
||||||
|
handler.removeCallbacks(updatingStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runUpdatingStatBlocks() {
|
||||||
|
updatingStats = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Log.d("BlockStatisticsBuilder", "run: working");
|
||||||
|
if (bsAdapter != null) {
|
||||||
|
initItems();
|
||||||
|
bsAdapter.setItems(items);
|
||||||
|
}
|
||||||
|
int interval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
|
||||||
|
handler.postDelayed(this, Math.max(1000, interval));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.post(updatingStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initItems() {
|
||||||
|
GPXTrackAnalysis analysis = getAnalysis();
|
||||||
|
float totalDistance = analysis.totalDistance;
|
||||||
|
float timeSpan = analysis.timeSpan;
|
||||||
|
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
|
||||||
|
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||||
|
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
|
||||||
|
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
|
||||||
|
|
||||||
|
items.clear();
|
||||||
|
prepareData(analysis, 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, ItemType.ITEM_DISTANCE);
|
||||||
|
prepareData(analysis, app.getString(R.string.altitude_ascent), asc,
|
||||||
|
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ItemType.ITEM_ALTITUDE);
|
||||||
|
prepareData(analysis, app.getString(R.string.altitude_descent), desc,
|
||||||
|
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ItemType.ITEM_ALTITUDE);
|
||||||
|
prepareData(analysis, app.getString(R.string.average_speed), avg,
|
||||||
|
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
|
||||||
|
prepareData(analysis, app.getString(R.string.max_speed), max,
|
||||||
|
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
|
||||||
|
prepareData(analysis, 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, ItemType.ITEM_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prepareData(GPXTrackAnalysis analysis, 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) {
|
||||||
|
items.add(statBlock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ITEM_ALTITUDE: {
|
||||||
|
if (analysis.hasElevationData) {
|
||||||
|
items.add(statBlock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ITEM_SPEED: {
|
||||||
|
if (analysis.isSpeedSpecified()) {
|
||||||
|
items.add(statBlock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ITEM_TIME: {
|
||||||
|
if (analysis.hasSpeedData) {
|
||||||
|
items.add(statBlock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
protected int getResolvedColor(@ColorRes int colorId) {
|
||||||
|
return ContextCompat.getColor(app, colorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StatBlock {
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
private final String value;
|
||||||
|
private final int imageResId;
|
||||||
|
private final int imageColorId;
|
||||||
|
private final GPXDataSetType firstType;
|
||||||
|
private final GPXDataSetType secondType;
|
||||||
|
private final ItemType itemType;
|
||||||
|
|
||||||
|
public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
|
||||||
|
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 enum ItemType {
|
||||||
|
ITEM_DISTANCE,
|
||||||
|
ITEM_ALTITUDE,
|
||||||
|
ITEM_SPEED,
|
||||||
|
ITEM_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BlockStatisticsAdapter extends RecyclerView.Adapter<BlockStatisticsViewHolder> {
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
private final int activeColor;
|
||||||
|
private final List<StatBlock> statBlocks = new ArrayList<>();
|
||||||
|
private final boolean nightMode;
|
||||||
|
private final SegmentActionsListener actionsListener;
|
||||||
|
|
||||||
|
public BlockStatisticsAdapter(@Nullable SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
|
||||||
|
this.actionsListener = actionsListener;
|
||||||
|
this.activeColor = activeColor;
|
||||||
|
this.nightMode = nightMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return statBlocks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public BlockStatisticsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View itemView = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_gpx_stat_block, parent, false);
|
||||||
|
return new BlockStatisticsViewHolder(itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final BlockStatisticsViewHolder holder, int position) {
|
||||||
|
final StatBlock item = statBlocks.get(position);
|
||||||
|
holder.valueText.setText(item.value);
|
||||||
|
holder.titleText.setText(item.title);
|
||||||
|
if (handler.hasCallbacks(updatingStats)) {
|
||||||
|
holder.titleText.setWidth(app.getResources().getDimensionPixelSize(R.dimen.map_route_buttons_width));
|
||||||
|
}
|
||||||
|
holder.valueText.setTextColor(activeColor);
|
||||||
|
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
|
||||||
|
if (actionsListener != null && displayHelper != null) {
|
||||||
|
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(filterTypes);
|
||||||
|
GpxDisplayGroup group = null;
|
||||||
|
for (GpxDisplayGroup g : groups) {
|
||||||
|
if (g.isGeneralTrack()) {
|
||||||
|
group = g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (group == null && !groups.isEmpty()) {
|
||||||
|
group = groups.get(0);
|
||||||
|
}
|
||||||
|
if (group != null) {
|
||||||
|
GpxDisplayItem displayItem = group.getModifiableList().get(0);
|
||||||
|
if (displayItem != null && displayItem.analysis != null) {
|
||||||
|
ArrayList<GPXDataSetType> list = new ArrayList<>();
|
||||||
|
if (displayItem.analysis.hasElevationData || displayItem.analysis.isSpeedSpecified() || displayItem.analysis.hasSpeedData) {
|
||||||
|
if (item.firstType != null) {
|
||||||
|
list.add(item.firstType);
|
||||||
|
}
|
||||||
|
if (item.secondType != null) {
|
||||||
|
list.add(item.secondType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
displayItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
|
||||||
|
displayItem.locationOnMap = displayItem.locationStart;
|
||||||
|
actionsListener.openAnalyzeOnMap(displayItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setImageDrawable(holder.imageView, item.imageResId, item.imageColorId);
|
||||||
|
AndroidUtils.setBackgroundColor(app, holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark);
|
||||||
|
AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<StatBlock> statBlocks) {
|
||||||
|
this.statBlocks.clear();
|
||||||
|
this.statBlocks.addAll(statBlocks);
|
||||||
|
notifyItemRangeChanged(0, getItemCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BlockStatisticsViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private final TextViewEx valueText;
|
||||||
|
private final TextView titleText;
|
||||||
|
private final AppCompatImageView imageView;
|
||||||
|
private final View divider;
|
||||||
|
|
||||||
|
public BlockStatisticsViewHolder(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue