Merge pull request #11220 from osmandapp/trip_recording_graphs

Redesign trip recording base dialog (added graphs)
This commit is contained in:
Vitaliy 2021-03-22 21:55:04 +02:00 committed by GitHub
commit 334d7a11e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 512 additions and 202 deletions

View file

@ -52,7 +52,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/average_range"
android:id="@+id/top_line_blocks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -171,7 +171,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/ascent_descent"
android:id="@+id/bottom_line_blocks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -273,6 +273,7 @@
</LinearLayout>
<View
android:id="@+id/details_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />

View file

@ -52,7 +52,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/distance_time_span"
android:id="@+id/top_line_blocks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -171,7 +171,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/start_end_time"
android:id="@+id/bottom_line_blocks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -291,6 +291,7 @@
</LinearLayout>
<View
android:id="@+id/details_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />

View file

@ -52,7 +52,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/average_max"
android:id="@+id/top_line_blocks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -172,7 +172,7 @@
<LinearLayout
android:id="@+id/time_distance"
android:id="@+id/bottom_line_blocks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@ -275,6 +275,7 @@
</LinearLayout>
<View
android:id="@+id/details_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />

View file

@ -4,7 +4,9 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/list_item_divider" />
<include
android:id="@+id/list_item_divider"
layout="@layout/list_item_divider" />
<LinearLayout
android:layout_width="match_parent"

View file

@ -72,7 +72,13 @@
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/dialog_content_margin" />
android:layout_marginBottom="@dimen/context_menu_padding_margin_small" />
<LinearLayout
android:id="@+id/segments_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/block_statistics"

View file

@ -40,7 +40,6 @@ import java.util.LinkedHashMap;
import static net.osmand.plus.activities.PluginInfoFragment.PLUGIN_INFO;
import static net.osmand.plus.monitoring.OsmandMonitoringPlugin.MINUTES;
import static net.osmand.plus.monitoring.OsmandMonitoringPlugin.SECONDS;
import static net.osmand.plus.monitoring.TripRecordingStartingBottomFragment.UPDATE_LOGGING_INTERVAL;
import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID;
import static net.osmand.plus.settings.backend.OsmandSettings.MONTHLY_DIRECTORY;
import static net.osmand.plus.settings.backend.OsmandSettings.REC_DIRECTORY;

View file

@ -9,6 +9,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
@ -31,7 +32,10 @@ import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.TrkSegment;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
@ -42,27 +46,41 @@ import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.mapcontextmenu.other.TrackChartPoints;
import net.osmand.plus.myplaces.GPXItemPagerAdapter;
import net.osmand.plus.myplaces.SegmentActionsListener;
import net.osmand.plus.myplaces.SegmentGPXAdapter;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.GpxBlockStatisticsBuilder;
import net.osmand.plus.track.TrackAppearanceFragment;
import net.osmand.plus.track.TrackDisplayHelper;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
import net.osmand.plus.views.controls.WrapContentHeightViewPager;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import static net.osmand.AndroidUtils.getSecondaryTextColorId;
import static net.osmand.AndroidUtils.setPadding;
import static net.osmand.plus.UiUtilities.CompoundButtonType.GLOBAL;
import static net.osmand.plus.track.GpxBlockStatisticsBuilder.INIT_BLOCKS_ALTITUDE;
import static net.osmand.plus.track.GpxBlockStatisticsBuilder.INIT_BLOCKS_GENERAL;
import static net.osmand.plus.track.GpxBlockStatisticsBuilder.INIT_BLOCKS_SPEED;
public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment implements SegmentActionsListener {
public static final String TAG = TripRecordingBottomFragment.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(TripRecordingBottomFragment.class);
public static final String UPDATE_TRACK_ICON = "update_track_icon";
private static final int GPS_UPDATE_INTERVAL = 1000;
private static final String[] INIT_BLOCKS_KEYS =
new String[]{INIT_BLOCKS_GENERAL, INIT_BLOCKS_ALTITUDE, INIT_BLOCKS_SPEED};
private OsmandApplication app;
private OsmandSettings settings;
@ -71,8 +89,13 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
private View statusContainer;
private AppCompatImageView trackAppearanceIcon;
private GpxBlockStatisticsBuilder blockStatisticsBuilder;
private LinearLayout segmentsContainer;
private TrackDisplayHelper displayHelper;
private TrackChartPoints trackChartPoints;
private GPXItemPagerAdapter graphsAdapter;
private GpxBlockStatisticsBuilder blockStatisticsBuilder;
private SelectedGpxFile selectedGpxFile;
private final Handler handler = new Handler();
private Runnable updatingGPS;
@ -123,12 +146,6 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
statusContainer = itemView.findViewById(R.id.status_container);
updateStatus();
RecyclerView statBlocks = itemView.findViewById(R.id.block_statistics);
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile);
blockStatisticsBuilder.setBlocksView(statBlocks);
blockStatisticsBuilder.setBlocksClickable(false);
blockStatisticsBuilder.initStatBlocks(null, ContextCompat.getColor(app, getActiveTextColorId(nightMode)), nightMode);
LinearLayout showTrackContainer = itemView.findViewById(R.id.show_track_on_map);
trackAppearanceIcon = showTrackContainer.findViewById(R.id.additional_button_icon);
createShowTrackItem(showTrackContainer, trackAppearanceIcon, ItemType.SHOW_TRACK.getTitleId(),
@ -139,6 +156,17 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
}
});
segmentsContainer = itemView.findViewById(R.id.segments_container);
createSegmentsTabs(segmentsContainer);
RecyclerView statBlocks = itemView.findViewById(R.id.block_statistics);
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile, nightMode);
blockStatisticsBuilder.setBlocksView(statBlocks);
blockStatisticsBuilder.setBlocksClickable(false);
blockStatisticsBuilder.setInitBlocksKey(INIT_BLOCKS_GENERAL);
blockStatisticsBuilder.initStatBlocks(null,
ContextCompat.getColor(app, getActiveTextColorId(nightMode)));
CardView cardLeft = itemView.findViewById(R.id.button_left);
createItem(cardLeft, ItemType.CANCEL);
cardLeft.setOnClickListener(new View.OnClickListener() {
@ -197,6 +225,10 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
super.onResume();
blockStatisticsBuilder.runUpdatingStatBlocksIfNeeded();
runUpdatingGPS();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints);
}
}
@Override
@ -204,6 +236,10 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
super.onPause();
blockStatisticsBuilder.stopUpdatingStatBlocks();
stopUpdatingGPS();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(null);
}
}
public void show() {
@ -245,6 +281,51 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
handler.post(updatingGPS);
}
private void recreateStatBlocks(String initBlocksKey) {
blockStatisticsBuilder.stopUpdatingStatBlocks();
blockStatisticsBuilder.setInitBlocksKey(initBlocksKey);
blockStatisticsBuilder.runUpdatingStatBlocksIfNeeded();
}
private void setupDisplayHelper() {
displayHelper = new TrackDisplayHelper(app);
if (!selectedGpxFile.isShowCurrentTrack()) {
File file = new File(getGPXFile().path);
displayHelper.setFile(file);
displayHelper.setGpxDataItem(app.getGpxDbHelper().getItem(file));
}
displayHelper.setGpx(getGPXFile());
}
private void createSegmentsTabs(ViewGroup viewGroup) {
viewGroup.removeAllViews();
setupDisplayHelper();
View segmentView = SegmentGPXAdapter.createGpxTabsView(displayHelper, viewGroup, this, nightMode);
AndroidUiHelper.setVisibility(View.GONE, segmentView.findViewById(R.id.list_item_divider));
WrapContentHeightViewPager pager = segmentView.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = segmentView.findViewById(R.id.sliding_tabs);
tabLayout.setOnTabReselectedListener(new PagerSlidingTabStrip.OnTabReselectedListener() {
@Override
public void onTabSelected(int position) {
recreateStatBlocks(INIT_BLOCKS_KEYS[position]);
}
@Override
public void onTabReselected(int position) {
recreateStatBlocks(INIT_BLOCKS_KEYS[position]);
}
});
graphsAdapter = new GPXItemPagerAdapter(app, GpxUiHelper.makeGpxDisplayItem(app,
displayHelper.getGpx()), displayHelper, nightMode, this, true);
pager.setAdapter(graphsAdapter);
tabLayout.setViewPager(pager);
viewGroup.addView(segmentView);
}
private void updateStatus() {
TextView statusTitle = statusContainer.findViewById(R.id.text_status);
AppCompatImageView statusIcon = statusContainer.findViewById(R.id.icon_status);
@ -474,6 +555,46 @@ public class TripRecordingBottomFragment extends MenuBottomSheetDialogFragment {
}
}
@Override
public void onPointSelected(TrkSegment segment, double lat, double lon) {
if (trackChartPoints == null) {
trackChartPoints = new TrackChartPoints();
trackChartPoints.setGpx(displayHelper.getGpx());
}
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
int segmentColor = segment != null ? segment.getColor(0) : 0;
trackChartPoints.setSegmentColor(segmentColor);
trackChartPoints.setHighlightedPoint(new LatLon(lat, lon));
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints);
mapActivity.refreshMap();
}
}
@Override
public void updateContent() {
}
@Override
public void onChartTouch() {
}
@Override
public void scrollBy(int px) {
}
@Override
public void openSplitInterval(GpxDisplayItem gpxItem, TrkSegment trkSegment) {
}
@Override
public void showOptionsPopupMenu(View view, TrkSegment segment, boolean confirmDeletion, GpxDisplayItem gpxItem) {
}
@Override
public void openAnalyzeOnMap(GpxDisplayItem gpxItem) {
}
public interface DismissTargetFragment {
void dismissTarget();
}

View file

@ -61,6 +61,8 @@ import java.util.Map;
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.ALTITUDE;
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SLOPE;
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SPEED;
import static net.osmand.plus.myplaces.GPXTabItemType.GPX_TAB_ITEM_ALTITUDE;
import static net.osmand.plus.myplaces.GPXTabItemType.GPX_TAB_ITEM_SPEED;
public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvider, ViewAtPositionInterface {
@ -79,18 +81,21 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
private boolean chartClicked;
private boolean nightMode;
private boolean onlyGraphs;
public GPXItemPagerAdapter(@NonNull OsmandApplication app,
@NonNull GpxDisplayItem gpxItem,
@NonNull TrackDisplayHelper displayHelper,
boolean nightMode, @NonNull SegmentActionsListener actionsListener) {
boolean nightMode,
@NonNull SegmentActionsListener actionsListener,
boolean onlyGraphs) {
super();
this.app = app;
this.gpxItem = gpxItem;
this.nightMode = nightMode;
this.displayHelper = displayHelper;
this.actionsListener = actionsListener;
this.onlyGraphs = onlyGraphs;
iconsCache = app.getUIUtilities();
fetchTabTypes();
}
@ -100,10 +105,10 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
if (gpxItem != null && gpxItem.analysis != null) {
if (gpxItem.analysis.hasElevationData) {
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
tabTypeList.add(GPX_TAB_ITEM_ALTITUDE);
}
if (gpxItem.analysis.isSpeedSpecified()) {
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_SPEED);
tabTypeList.add(GPX_TAB_ITEM_SPEED);
}
}
tabTypes = tabTypeList.toArray(new GPXTabItemType[0]);
@ -217,72 +222,87 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
private View getViewForTab(@NonNull ViewGroup container, @NonNull GPXTabItemType tabType) {
LayoutInflater inflater = LayoutInflater.from(container.getContext());
switch (tabType) {
case GPX_TAB_ITEM_ALTITUDE:
return inflater.inflate(R.layout.gpx_item_altitude, container, false);
case GPX_TAB_ITEM_SPEED:
return inflater.inflate(R.layout.gpx_item_speed, container, false);
case GPX_TAB_ITEM_GENERAL:
default:
return inflater.inflate(R.layout.gpx_item_general, container, false);
int layoutResId;
if (tabType == GPX_TAB_ITEM_ALTITUDE) {
layoutResId = R.layout.gpx_item_altitude;
} else if (tabType == GPX_TAB_ITEM_SPEED) {
layoutResId = R.layout.gpx_item_speed;
} else {
layoutResId = R.layout.gpx_item_general;
}
View view = inflater.inflate(layoutResId, container, false);
if (onlyGraphs) {
AndroidUiHelper.setVisibility(View.GONE,
view.findViewById(R.id.gpx_join_gaps_container),
view.findViewById(R.id.top_line_blocks),
view.findViewById(R.id.list_divider),
view.findViewById(R.id.bottom_line_blocks),
view.findViewById(R.id.details_divider),
view.findViewById(R.id.details_view)
);
}
return view;
}
private void setupSpeedTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
if (analysis != null && analysis.isSpeedSpecified()) {
if (analysis.hasSpeedData) {
GpxUiHelper.setupGPXChart(app, chart, 4);
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_SPEED, SPEED, null)));
chart.setData(new LineData(getDataSets(chart, GPX_TAB_ITEM_SPEED, SPEED, null)));
updateChart(chart);
chart.setVisibility(View.VISIBLE);
} else {
chart.setVisibility(View.GONE);
}
((ImageView) view.findViewById(R.id.average_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_speed));
((ImageView) view.findViewById(R.id.max_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_max_speed));
((ImageView) view.findViewById(R.id.time_moving_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
((ImageView) view.findViewById(R.id.distance_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
if (!onlyGraphs) {
((ImageView) view.findViewById(R.id.average_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_speed));
((ImageView) view.findViewById(R.id.max_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_max_speed));
((ImageView) view.findViewById(R.id.time_moving_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
((ImageView) view.findViewById(R.id.distance_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
((TextView) view.findViewById(R.id.average_text)).setText(avg);
((TextView) view.findViewById(R.id.max_text)).setText(max);
((TextView) view.findViewById(R.id.average_text)).setText(avg);
((TextView) view.findViewById(R.id.max_text)).setText(max);
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
actionsListener.updateContent();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
actionsListener.updateContent();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
}
}
}
}
});
});
}
} else {
chart.setVisibility(View.GONE);
view.findViewById(R.id.average_max).setVisibility(View.GONE);
view.findViewById(R.id.top_line_blocks).setVisibility(View.GONE);
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.time_distance).setVisibility(View.GONE);
view.findViewById(R.id.bottom_line_blocks).setVisibility(View.GONE);
}
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_SPEED);
if (!onlyGraphs) {
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAnalyzeOnMap(GPX_TAB_ITEM_SPEED);
}
});
TextView overflowMenu = view.findViewById(R.id.overflow_menu);
if (!gpxItem.group.getTrack().generalTrack) {
setupOptionsPopupMenu(overflowMenu, false);
} else {
overflowMenu.setVisibility(View.GONE);
}
});
TextView overflowMenu = view.findViewById(R.id.overflow_menu);
if (!gpxItem.group.getTrack().generalTrack) {
setupOptionsPopupMenu(overflowMenu, false);
} else {
overflowMenu.setVisibility(View.GONE);
}
}
@ -300,62 +320,66 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
if (analysis != null) {
if (analysis.hasElevationData) {
GpxUiHelper.setupGPXChart(app, chart, 4);
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, ALTITUDE, SLOPE)));
chart.setData(new LineData(getDataSets(chart, GPX_TAB_ITEM_ALTITUDE, ALTITUDE, SLOPE)));
updateChart(chart);
chart.setVisibility(View.VISIBLE);
} else {
chart.setVisibility(View.GONE);
}
((ImageView) view.findViewById(R.id.average_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
((ImageView) view.findViewById(R.id.range_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
((ImageView) view.findViewById(R.id.ascent_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_ascent));
((ImageView) view.findViewById(R.id.descent_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_descent));
if (!onlyGraphs) {
((ImageView) view.findViewById(R.id.average_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
((ImageView) view.findViewById(R.id.range_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
((ImageView) view.findViewById(R.id.ascent_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_ascent));
((ImageView) view.findViewById(R.id.descent_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_descent));
String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app);
String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app);
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app);
String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app);
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
((TextView) view.findViewById(R.id.average_text))
.setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app));
((TextView) view.findViewById(R.id.range_text)).setText(String.format("%s - %s", min, max));
((TextView) view.findViewById(R.id.ascent_text)).setText(asc);
((TextView) view.findViewById(R.id.descent_text)).setText(desc);
((TextView) view.findViewById(R.id.average_text))
.setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app));
((TextView) view.findViewById(R.id.range_text)).setText(String.format("%s - %s", min, max));
((TextView) view.findViewById(R.id.ascent_text)).setText(asc);
((TextView) view.findViewById(R.id.descent_text)).setText(desc);
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
actionsListener.updateContent();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
actionsListener.updateContent();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
}
}
}
}
});
});
}
} else {
chart.setVisibility(View.GONE);
view.findViewById(R.id.average_range).setVisibility(View.GONE);
view.findViewById(R.id.top_line_blocks).setVisibility(View.GONE);
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.ascent_descent).setVisibility(View.GONE);
view.findViewById(R.id.bottom_line_blocks).setVisibility(View.GONE);
}
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
if (!onlyGraphs) {
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAnalyzeOnMap(GPX_TAB_ITEM_ALTITUDE);
}
});
TextView overflowMenu = view.findViewById(R.id.overflow_menu);
if (!gpxItem.group.getTrack().generalTrack) {
setupOptionsPopupMenu(overflowMenu, false);
} else {
overflowMenu.setVisibility(View.GONE);
}
});
TextView overflowMenu = view.findViewById(R.id.overflow_menu);
if (!gpxItem.group.getTrack().generalTrack) {
setupOptionsPopupMenu(overflowMenu, false);
} else {
overflowMenu.setVisibility(View.GONE);
}
}
@ -369,60 +393,63 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
} else {
chart.setVisibility(View.GONE);
}
if (!onlyGraphs) {
((ImageView) view.findViewById(R.id.distance_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
((ImageView) view.findViewById(R.id.duration_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
((ImageView) view.findViewById(R.id.start_time_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_start));
((ImageView) view.findViewById(R.id.end_time_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_end));
((ImageView) view.findViewById(R.id.distance_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
((ImageView) view.findViewById(R.id.duration_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
((ImageView) view.findViewById(R.id.start_time_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_start));
((ImageView) view.findViewById(R.id.end_time_icon))
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_end));
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
actionsListener.updateContent();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
actionsListener.updateContent();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
}
}
}
}
});
if (analysis.timeSpan > 0) {
DateFormat tf = SimpleDateFormat.getTimeInstance(DateFormat.SHORT);
DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM);
});
if (analysis.timeSpan > 0) {
DateFormat tf = SimpleDateFormat.getTimeInstance(DateFormat.SHORT);
DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM);
Date start = new Date(analysis.startTime);
((TextView) view.findViewById(R.id.start_time_text)).setText(tf.format(start));
((TextView) view.findViewById(R.id.start_date_text)).setText(df.format(start));
Date end = new Date(analysis.endTime);
((TextView) view.findViewById(R.id.end_time_text)).setText(tf.format(end));
((TextView) view.findViewById(R.id.end_date_text)).setText(df.format(end));
} else {
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
Date start = new Date(analysis.startTime);
((TextView) view.findViewById(R.id.start_time_text)).setText(tf.format(start));
((TextView) view.findViewById(R.id.start_date_text)).setText(df.format(start));
Date end = new Date(analysis.endTime);
((TextView) view.findViewById(R.id.end_time_text)).setText(tf.format(end));
((TextView) view.findViewById(R.id.end_date_text)).setText(df.format(end));
} else {
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.bottom_line_blocks).setVisibility(View.GONE);
}
}
} else {
chart.setVisibility(View.GONE);
view.findViewById(R.id.distance_time_span).setVisibility(View.GONE);
view.findViewById(R.id.top_line_blocks).setVisibility(View.GONE);
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
view.findViewById(R.id.bottom_line_blocks).setVisibility(View.GONE);
}
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
if (!onlyGraphs) {
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
}
});
TextView overflowMenu = view.findViewById(R.id.overflow_menu);
if (!gpxItem.group.getTrack().generalTrack) {
setupOptionsPopupMenu(overflowMenu, true);
} else {
overflowMenu.setVisibility(View.GONE);
}
});
TextView overflowMenu = view.findViewById(R.id.overflow_menu);
if (!gpxItem.group.getTrack().generalTrack) {
setupOptionsPopupMenu(overflowMenu, true);
} else {
overflowMenu.setVisibility(View.GONE);
}
}
@ -598,7 +625,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
@Override
public void tabStylesUpdated(View tabsContainer, int currentPosition) {
ViewGroup.MarginLayoutParams params = (MarginLayoutParams) tabsContainer.getLayoutParams();
params.height = app.getResources().getDimensionPixelSize(R.dimen.dialog_button_height);
params.height = app.getResources().getDimensionPixelSize(!onlyGraphs ? R.dimen.dialog_button_height : R.dimen.context_menu_buttons_bottom_height);
tabsContainer.setLayoutParams(params);
UiUtilities.updateCustomRadioButtons(app, tabsContainer, nightMode, getCustomRadioButtonType(currentPosition));
}
@ -645,7 +672,7 @@ public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvid
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistance, app));
((TextView) view.findViewById(R.id.duration_text)).setText(Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()));
} else if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_SPEED)) {
} else if (tabType.equals(GPX_TAB_ITEM_SPEED)) {
long timeMoving = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeMovingWithoutGaps : analysis.timeMoving;
float totalDistanceMoving = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceMovingWithoutGaps : analysis.totalDistanceMoving;

View file

@ -55,7 +55,7 @@ public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
pager.setAdapter(new GPXItemPagerAdapter(app, item, displayHelper, nightMode, listener));
pager.setAdapter(new GPXItemPagerAdapter(app, item, displayHelper, nightMode, listener, false));
if (create) {
tabLayout.setViewPager(pager);
} else {

View file

@ -8,6 +8,16 @@ import android.view.View;
import android.view.ViewGroup;
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.GPXFile;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
@ -26,39 +36,44 @@ import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
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.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import static net.osmand.plus.liveupdates.LiveUpdatesFragmentNew.getDefaultIconColorId;
public class GpxBlockStatisticsBuilder {
private static final Log log = PlatformUtil.getLog(GpxBlockStatisticsBuilder.class);
private static final int GENERAL_UPDATE_INTERVAL = 1000;
private static final Log LOG = PlatformUtil.getLog(GpxBlockStatisticsBuilder.class);
private static final int BLOCKS_UPDATE_INTERVAL = 1000;
public static final String INIT_BLOCKS_BASE = "init_blocks_base";
public static final String INIT_BLOCKS_GENERAL = "init_blocks_general";
public static final String INIT_BLOCKS_ALTITUDE = "init_blocks_altitude";
public static final String INIT_BLOCKS_SPEED = "init_blocks_speed";
private final OsmandApplication app;
private final boolean nightMode;
private RecyclerView blocksView;
private final SelectedGpxFile selectedGpxFile;
private GPXTrackAnalysis analysis;
private BlockStatisticsAdapter adapter;
private final List<StatBlock> items = new ArrayList<>();
private boolean blocksClickable = true;
private String initBlocksKey = INIT_BLOCKS_BASE;
private final Handler handler = new Handler();
private Runnable updatingItems;
private boolean updateRunning = false;
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile) {
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile, boolean nightMode) {
this.app = app;
this.selectedGpxFile = selectedGpxFile;
this.nightMode = nightMode;
}
public boolean isUpdateRunning() {
@ -73,6 +88,10 @@ public class GpxBlockStatisticsBuilder {
this.blocksView = blocksView;
}
public void setInitBlocksKey(String initBlocksKey) {
this.initBlocksKey = initBlocksKey;
}
@Nullable
public GpxDisplayItem getDisplayItem(GPXFile gpxFile) {
return gpxFile.tracks.size() > 0 ? GpxUiHelper.makeGpxDisplayItem(app, gpxFile) : null;
@ -82,9 +101,9 @@ public class GpxBlockStatisticsBuilder {
return selectedGpxFile.getGpxFile();
}
public void initStatBlocks(@Nullable SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
public void initStatBlocks(@Nullable SegmentActionsListener actionsListener, @ColorInt int activeColor) {
initItems();
adapter = new BlockStatisticsAdapter(getDisplayItem(getGPXFile()), actionsListener, activeColor, nightMode);
adapter = new BlockStatisticsAdapter(getDisplayItem(getGPXFile()), actionsListener, activeColor);
adapter.setItems(items);
blocksView.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false));
blocksView.setAdapter(adapter);
@ -107,7 +126,7 @@ public class GpxBlockStatisticsBuilder {
}
AndroidUiHelper.updateVisibility(blocksView, !Algorithms.isEmpty(items));
int interval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
updateRunning = handler.postDelayed(this, Math.max(GENERAL_UPDATE_INTERVAL, interval));
updateRunning = handler.postDelayed(this, Math.max(BLOCKS_UPDATE_INTERVAL, interval));
}
};
updateRunning = handler.post(updatingItems);
@ -119,7 +138,7 @@ public class GpxBlockStatisticsBuilder {
if (app == null || gpxFile == null) {
return;
}
GPXTrackAnalysis analysis = null;
analysis = null;
boolean withoutGaps = true;
if (gpxFile.equals(app.getSavingTrackHelper().getCurrentGpx())) {
GPXFile currentGpx = app.getSavingTrackHelper().getCurrentTrack().getGpxFile();
@ -133,34 +152,140 @@ public class GpxBlockStatisticsBuilder {
withoutGaps = !selectedGpxFile.isJoinSegments() && gpxDisplayItem.isGeneralTrack();
}
}
items.clear();
if (analysis != null) {
float totalDistance = withoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = withoutGaps ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
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);
switch (initBlocksKey) {
case INIT_BLOCKS_GENERAL: {
float totalDistance = withoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = withoutGaps ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
Date start = new Date(analysis.startTime);
Date end = new Date(analysis.endTime);
prepareDataDistance(totalDistance);
prepareDataTimeSpan(timeSpan);
prepareDataStartTime(start);
prepareDataEndTime(end);
break;
}
case INIT_BLOCKS_ALTITUDE: {
String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app);
String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app);
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
prepareDataAverageAltitude();
prepareDataAltitudeRange(min, max);
prepareDataAscent(asc);
prepareDataDescent(desc);
break;
}
case INIT_BLOCKS_SPEED: {
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
long timeMoving = withoutGaps ? analysis.timeMovingWithoutGaps : analysis.timeMoving;
float totalDistanceMoving = withoutGaps ? analysis.totalDistanceMovingWithoutGaps : analysis.totalDistanceMoving;
prepareDataAverageSpeed(avg);
prepareDataMaximumSpeed(max);
prepareDataTimeMoving(timeMoving);
prepareDataDistanceCorrected(totalDistanceMoving);
break;
}
default:
case INIT_BLOCKS_BASE: {
float totalDistance = withoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
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);
float timeSpan = withoutGaps ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
prepareDataDistance(totalDistance);
prepareDataAscent(asc);
prepareDataDescent(desc);
prepareDataAverageSpeed(avg);
prepareDataMaximumSpeed(max);
prepareDataTimeSpan(timeSpan);
break;
}
}
}
}
public void prepareData(GPXTrackAnalysis analysis, String title, String value,
@DrawableRes int imageResId, @ColorRes int imageColorId,
public void prepareDataDistance(float totalDistance) {
prepareData(app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app),
R.drawable.ic_action_track_16, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ItemType.ITEM_DISTANCE);
}
public void prepareDataAverageAltitude() {
prepareData(app.getString(R.string.average_altitude), OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app),
R.drawable.ic_action_altitude_average_16, GPXDataSetType.ALTITUDE, null, ItemType.ITEM_ALTITUDE);
}
public void prepareDataAltitudeRange(String min, String max) {
String pattern = app.getString(R.string.ltr_or_rtl_combine_via_dash);
prepareData(app.getString(R.string.altitude_range), String.format(pattern, min, max),
R.drawable.ic_action_altitude_range_16, GPXDataSetType.ALTITUDE, null, ItemType.ITEM_ALTITUDE);
}
public void prepareDataAscent(String asc) {
prepareData(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);
}
public void prepareDataDescent(String desc) {
prepareData(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);
}
public void prepareDataAverageSpeed(String avg) {
prepareData(app.getString(R.string.average_speed), avg,
R.drawable.ic_action_speed_16, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
}
public void prepareDataMaximumSpeed(String max) {
prepareData(app.getString(R.string.max_speed), max,
R.drawable.ic_action_max_speed_16, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
}
public void prepareDataTimeMoving(long timeMoving) {
prepareData(app.getString(R.string.shared_string_time_moving),
Algorithms.formatDuration((int) (timeMoving / 1000), app.accessibilityEnabled()),
R.drawable.ic_action_time_span_16, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME_MOVING);
}
public void prepareDataDistanceCorrected(float totalDistanceMoving) {
prepareData(app.getString(R.string.distance_moving),
OsmAndFormatter.getFormattedDistance(totalDistanceMoving, app),
R.drawable.ic_action_polygom_dark, GPXDataSetType.SPEED, null, ItemType.ITEM_DISTANCE_MOVING);
}
public void prepareDataTimeSpan(float timeSpan) {
prepareData(app.getString(R.string.shared_string_time_span),
Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()),
R.drawable.ic_action_time_span_16, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME_SPAN);
}
public void prepareDataStartTime(Date start) {
DateFormat dtf = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
prepareData(app.getString(R.string.shared_string_start_time), dtf.format(start),
R.drawable.ic_action_time_start_16, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME);
}
public void prepareDataEndTime(Date end) {
DateFormat dtf = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
prepareData(app.getString(R.string.shared_string_end_time), dtf.format(end),
R.drawable.ic_action_time_end_16, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME);
}
public void prepareData(String title, String value, @DrawableRes int imageResId,
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
prepareData(title, value, imageResId, getDefaultIconColorId(nightMode), firstType, secondType, itemType);
}
public void prepareData(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
if (analysis == null) {
return;
}
StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType);
switch (statBlock.itemType) {
case ITEM_DISTANCE: {
@ -169,6 +294,12 @@ public class GpxBlockStatisticsBuilder {
}
break;
}
case ITEM_DISTANCE_MOVING: {
if (analysis.totalDistanceMoving != 0f) {
items.add(statBlock);
}
break;
}
case ITEM_ALTITUDE: {
if (analysis.hasElevationData) {
items.add(statBlock);
@ -182,11 +313,23 @@ public class GpxBlockStatisticsBuilder {
break;
}
case ITEM_TIME: {
if (analysis.timeSpan > 0) {
items.add(statBlock);
}
break;
}
case ITEM_TIME_SPAN: {
if (analysis.hasSpeedData) {
items.add(statBlock);
}
break;
}
case ITEM_TIME_MOVING: {
if (analysis.isTimeMoving()) {
items.add(statBlock);
}
break;
}
}
}
@ -213,9 +356,12 @@ public class GpxBlockStatisticsBuilder {
public enum ItemType {
ITEM_DISTANCE,
ITEM_DISTANCE_MOVING,
ITEM_ALTITUDE,
ITEM_SPEED,
ITEM_TIME;
ITEM_TIME,
ITEM_TIME_SPAN,
ITEM_TIME_MOVING;
}
private class BlockStatisticsAdapter extends RecyclerView.Adapter<BlockStatisticsViewHolder> {
@ -225,17 +371,15 @@ public class GpxBlockStatisticsBuilder {
private final SegmentActionsListener actionsListener;
@ColorInt
private final int activeColor;
private final boolean nightMode;
private final int minWidthPx;
private final int maxWidthPx;
private final int textSize;
public BlockStatisticsAdapter(GpxDisplayItem displayItem, SegmentActionsListener actionsListener,
@ColorInt int activeColor, boolean nightMode) {
@ColorInt int activeColor) {
this.displayItem = displayItem;
this.actionsListener = actionsListener;
this.activeColor = activeColor;
this.nightMode = nightMode;
minWidthPx = AndroidUtils.dpToPx(app, 60f);
maxWidthPx = AndroidUtils.dpToPx(app, 120f);
textSize = app.getResources().getDimensionPixelSize(R.dimen.default_desc_text_size);
@ -260,7 +404,7 @@ public class GpxBlockStatisticsBuilder {
holder.valueText.setText(item.value);
holder.valueText.setTextColor(activeColor);
holder.titleText.setText(item.title);
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
holder.titleText.setTextColor(ContextCompat.getColor(app, R.color.text_color_secondary_light));
float letterSpacing = 0.00f;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
letterSpacing = Math.max(holder.valueText.getLetterSpacing(), holder.titleText.getLetterSpacing());

View file

@ -51,7 +51,7 @@ public class OverviewCard extends BaseCard {
super(mapActivity);
this.actionsListener = actionsListener;
this.selectedGpxFile = selectedGpxFile;
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile);
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile, nightMode);
}
@Override
@ -80,7 +80,7 @@ public class OverviewCard extends BaseCard {
initEditButton(iconColorDef, iconColorPres);
initDirectionsButton(iconColorDef, iconColorPres);
}
blockStatisticsBuilder.initStatBlocks(actionsListener, getActiveColor(), nightMode);
blockStatisticsBuilder.initStatBlocks(actionsListener, getActiveColor());
}
private GPXFile getGPXFile() {

View file

@ -47,7 +47,7 @@ public class SegmentsCard extends BaseCard {
WrapContentHeightViewPager pager = segmentView.findViewById(R.id.pager);
PagerSlidingTabStrip tabLayout = segmentView.findViewById(R.id.sliding_tabs);
pager.setAdapter(new GPXItemPagerAdapter(app, displayItem, displayHelper, nightMode, listener));
pager.setAdapter(new GPXItemPagerAdapter(app, displayItem, displayHelper, nightMode, listener, false));
tabLayout.setViewPager(pager);
container.addView(segmentView);

View file

@ -66,12 +66,17 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
public interface CustomTabProvider {
public View getCustomTabView(@NonNull ViewGroup parent, int position);
public void select(View tab);
public void deselect(View tab);
public void tabStylesUpdated(View tabsContainer, int currentPosition);
}
public interface OnTabReselectedListener {
public void onTabSelected(int position);
public void onTabReselected(int position);
}
@ -121,7 +126,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
private int underlineHeight = 0;
@ColorInt
private int underlineColor;
private int dividerWidth = 0;
private int dividerPadding = 0;
@ -197,7 +202,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
//In case we have the padding they must be equal so we take the biggest
padding = Math.max(paddingLeft, paddingRight);
// get custom attrs
a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip);
@ -221,7 +226,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
tabTypefaceSelectedStyle = a.getInt(R.styleable.PagerSlidingTabStrip_pstsTextSelectedStyle, Typeface.NORMAL);
tabTextAlpha = a.getFloat(R.styleable.PagerSlidingTabStrip_pstsTextAlpha, HALF_TRANSP);
tabTextSelectedAlpha = a.getFloat(R.styleable.PagerSlidingTabStrip_pstsTextSelectedAlpha, OPAQUE);
tabTypeface = FontCache.getRobotoMedium(context);
tabTypeface = FontCache.getRobotoMedium(context);
a.recycle();
setMarginBottomTabContainer();
@ -326,6 +331,9 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
View tab = tabsContainer.getChildAt(pager.getCurrentItem());
notSelected(tab);
pager.setCurrentItem(position);
if (tabReselectedListener != null) {
tabReselectedListener.onTabSelected(position);
}
} else if (tabReselectedListener != null) {
tabReselectedListener.onTabReselected(position);
}
@ -470,7 +478,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
// draw underline
rectPaint.setColor(underlineColor); //underlineColor
canvas.drawRect(padding, height - underlineHeight, tabsContainer.getWidth() + padding, height, rectPaint);
// draw divider
if (dividerWidth != 0) {
dividerPaint.setStrokeWidth(dividerWidth);