GPX chart UI fixes

This commit is contained in:
Alexey Kulish 2017-02-24 14:56:41 +03:00
parent 6791fcc024
commit aad04c7bd3
12 changed files with 215 additions and 118 deletions

View file

@ -2,5 +2,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/osmand_orange"/>
<solid android:color="@color/gpx_chart_blue"/>
</shape>

View 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">
<corners android:radius="4dp" />
<solid android:color="@color/gpx_chart_orange"/>
</shape>

View file

@ -2,23 +2,84 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@drawable/chart_marker_background" >
android:gravity="center">
<TextView
android:id="@+id/tvContent"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:text="100 m"
android:textSize="@dimen/default_desc_text_size"
android:textColor="@android:color/white"
android:textStyle="bold"
android:ellipsize="end"
android:singleLine="true"/>
android:orientation="vertical">
<LinearLayout
android:id="@+id/text_alt_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="2dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:background="@drawable/chart_marker_blue_background">
<TextView
android:id="@+id/text_alt_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100 "
android:textSize="@dimen/default_desc_text_size"
android:textColor="@android:color/white"
android:textStyle="bold"
android:ellipsize="end"
android:singleLine="true"/>
<TextView
android:id="@+id/text_alt_units"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="m"
android:textSize="@dimen/default_sub_text_size"
android:textColor="@android:color/white"
android:ellipsize="end"
android:singleLine="true"/>
</LinearLayout>
<LinearLayout
android:id="@+id/text_spd_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="2dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:background="@drawable/chart_marker_orange_background">
<TextView
android:id="@+id/text_spd_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100 "
android:textSize="@dimen/default_desc_text_size"
android:textColor="@android:color/white"
android:textStyle="bold"
android:ellipsize="end"
android:singleLine="true"/>
<TextView
android:id="@+id/text_spd_units"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="km/h"
android:textSize="@dimen/default_sub_text_size"
android:textColor="@android:color/white"
android:ellipsize="end"
android:singleLine="true"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View file

@ -62,7 +62,7 @@
android:layout_height="wrap_content"
android:background="@null"
android:layout_marginTop="3dp"
android:text="@string/average_altitude"
android:text="@string/average_speed"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_sub_text_size"/>
@ -106,7 +106,7 @@
android:layout_height="wrap_content"
android:background="@null"
android:layout_marginTop="3dp"
android:text="@string/shared_string_max"
android:text="@string/max_speed"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_sub_text_size"/>

View file

@ -19,6 +19,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:paddingTop="8dp"/>
android:paddingTop="4dp"/>
</LinearLayout>

View file

@ -226,4 +226,9 @@
<!-- Dialog Live Updates Settings -->
<color name="white_50_transparent">#8FFF</color>
<color name="white_80_transparent">#CFFF</color>
<color name="gpx_chart_blue">#2f7af5</color>
<color name="gpx_chart_orange">#ff8800</color>
<color name="gpx_chart_green">#23b03b</color>
</resources>

View file

@ -9,6 +9,8 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
<string name="max_speed">Max speed</string>
<string name="average_speed">Average speed</string>
<string name="shared_string_time_moving">Time moving</string>
<string name="shared_string_time_span">Time span</string>
<string name="shared_string_max">Max</string>
@ -25,7 +27,7 @@
<string name="altitude_descent">Descent</string>
<string name="altitude_ascent">Ascent</string>
<string name="altitude_range">Altitude range</string>
<string name="average_altitude">Average</string>
<string name="average_altitude">Average altitude</string>
<string name="shared_string_time">Time</string>
<string name="total_distance">Total distance</string>
<string name="routing_attr_height_relief_smoothness_factor_name">Relief smoothness factor</string>

View file

@ -661,6 +661,8 @@ public class GpxSelectionHelper {
public String url;
public Bitmap image;
public boolean expanded;
public Matrix chartMatrix;
public float chartHighlightPos = -1f;
}
}

View file

@ -8,6 +8,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import net.osmand.AndroidUtils;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GpxSelectionHelper;
@ -67,7 +68,7 @@ public class TrackActivity extends TabActivity {
getSupportActionBar().setElevation(0);
setContentView(R.layout.tab_content);
PagerSlidingTabStrip mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tabs);
final PagerSlidingTabStrip mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setShouldExpand(true);
mViewPager = (ViewPager) findViewById(R.id.pager);
@ -102,6 +103,9 @@ public class TrackActivity extends TabActivity {
if (isHavingWayPoints() || isHavingRoutePoints()) {
((OsmandFragmentPagerAdapter) mViewPager.getAdapter()).addTab(
getTabIndicator(R.string.points, TrackPointFragment.class));
} else {
mSlidingTabLayout.setVisibility(View.GONE);
getSupportActionBar().setElevation(AndroidUtils.dpToPx(getMyApplication(), 4f));
}
};
}.execute((Void)null);

View file

@ -1,13 +1,14 @@
package net.osmand.plus.helpers;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
@ -36,17 +37,19 @@ import android.widget.Toast;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.MarkerView;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.ChartData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.DefaultFillFormatter;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IFillFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.MPPointF;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
@ -63,7 +66,6 @@ import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
import net.osmand.plus.activities.MapActivity;
@ -71,15 +73,11 @@ import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.dialogs.ConfigureMapMenu;
import net.osmand.plus.dialogs.ConfigureMapMenu.AppearanceListItem;
import net.osmand.plus.dialogs.ConfigureMapMenu.GpxAppearanceAdapter;
import net.osmand.plus.myplaces.SelectedGPXFragment;
import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
@ -97,7 +95,6 @@ import static net.osmand.plus.OsmAndFormatter.METERS_IN_ONE_NAUTICALMILE;
import static net.osmand.plus.OsmAndFormatter.YARDS_IN_ONE_METER;
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR;
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR;
import static net.osmand.plus.dialogs.ConfigureMapMenu.refreshMapComplete;
import static net.osmand.plus.download.DownloadActivity.formatMb;
public class GpxUiHelper {
@ -867,8 +864,7 @@ public class GpxUiHelper {
// create a custom MarkerView (extend MarkerView) and specify the layout
// to use for it
SelectedGPXFragment.MyMarkerView mv =
new SelectedGPXFragment.MyMarkerView(mChart.getContext(), R.layout.chart_marker_view);
GPXMarkerView mv = new GPXMarkerView(mChart.getContext());
mv.setChartView(mChart); // For bounds control
mChart.setMarker(mv); // Set the marker to the chart
mChart.setDrawMarkers(true);
@ -1005,10 +1001,8 @@ public class GpxUiHelper {
if (useRightAxis) {
yAxis = mChart.getAxisRight();
yAxis.setEnabled(true);
((SelectedGPXFragment.MyMarkerView)mChart.getMarker()).setUnitsRight(mainUnitY);
} else {
yAxis = mChart.getAxisLeft();
((SelectedGPXFragment.MyMarkerView)mChart.getMarker()).setUnitsLeft(mainUnitY);
}
yAxis.setGranularity(1f);
yAxis.setValueFormatter(new IAxisValueFormatter() {
@ -1031,17 +1025,20 @@ public class GpxUiHelper {
}
}
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "");
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.ALTITUDE);
dataSet.priority = (float) (analysis.avgElevation - analysis.minElevation) * convEle;
dataSet.units = mainUnitY;
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_blue));
dataSet.setLineWidth(1f);
if (drawFilled) {
dataSet.setColor(Color.BLACK);
dataSet.setLineWidth(0f);
dataSet.setFillAlpha(128);
dataSet.setFillColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_blue));
dataSet.setDrawFilled(true);
} else {
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.map_widget_blue));
dataSet.setLineWidth(1f);
dataSet.setDrawFilled(false);
}
dataSet.setDrawValues(false);
dataSet.setValueTextSize(9f);
dataSet.setFormLineWidth(1f);
@ -1055,13 +1052,6 @@ public class GpxUiHelper {
dataSet.setDrawHorizontalHighlightIndicator(false);
dataSet.setHighLightColor(light ? mChart.getResources().getColor(R.color.secondary_text_light) : mChart.getResources().getColor(R.color.secondary_text_dark));
if (Utils.getSDKInt() >= 18) {
// fill drawable only supported on api level 18 and above
Drawable drawable = ContextCompat.getDrawable(mChart.getContext(), R.drawable.line_chart_fade_blue);
dataSet.setFillDrawable(drawable);
} else {
dataSet.setFillColor(ContextCompat.getColor(mChart.getContext(), R.color.transport_route_line));
}
dataSet.setFillFormatter(new IFillFormatter() {
@Override
public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) {
@ -1132,10 +1122,8 @@ public class GpxUiHelper {
if (useRightAxis) {
yAxis = mChart.getAxisRight();
yAxis.setEnabled(true);
((SelectedGPXFragment.MyMarkerView)mChart.getMarker()).setUnitsRight(mainUnitY);
} else {
yAxis = mChart.getAxisLeft();
((SelectedGPXFragment.MyMarkerView)mChart.getMarker()).setUnitsLeft(mainUnitY);
}
yAxis.setAxisMinimum(0f);
yAxis.setValueFormatter(new IAxisValueFormatter() {
@ -1165,21 +1153,22 @@ public class GpxUiHelper {
}
}
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "");
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.SPEED);
if (Float.isNaN(divSpeed)) {
dataSet.priority = analysis.avgSpeed * mulSpeed;
} else {
dataSet.priority = divSpeed / analysis.avgSpeed;
}
dataSet.units = mainUnitY;
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_orange));
dataSet.setLineWidth(1f);
if (drawFilled) {
dataSet.setColor(Color.BLACK);
dataSet.setLineWidth(0f);
dataSet.setFillAlpha(128);
dataSet.setFillColor(ContextCompat.getColor(mChart.getContext(), R.color.gpx_chart_orange));
dataSet.setDrawFilled(true);
} else {
dataSet.setColor(ContextCompat.getColor(mChart.getContext(), R.color.transport_end));
dataSet.setLineWidth(1f);
dataSet.setDrawFilled(false);
}
dataSet.setDrawValues(false);
@ -1195,13 +1184,6 @@ public class GpxUiHelper {
dataSet.setDrawHorizontalHighlightIndicator(false);
dataSet.setHighLightColor(light ? mChart.getResources().getColor(R.color.secondary_text_light) : mChart.getResources().getColor(R.color.secondary_text_dark));
if (Utils.getSDKInt() >= 18) {
// fill drawable only supported on api level 18 and above
Drawable drawable = ContextCompat.getDrawable(mChart.getContext(), R.drawable.line_chart_fade_red);
dataSet.setFillDrawable(drawable);
} else {
dataSet.setFillColor(ContextCompat.getColor(mChart.getContext(), R.color.transport_end));
}
if (useRightAxis) {
dataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
}
@ -1216,12 +1198,95 @@ public class GpxUiHelper {
mChart.setData(data);
}
public enum GPXDataSetType {
ALTITUDE,
SPEED
}
public static class OrderedLineDataSet extends LineDataSet {
public float priority;
private GPXDataSetType dataSetType;
public OrderedLineDataSet(List<Entry> yVals, String label) {
public float priority;
public String units;
public OrderedLineDataSet(List<Entry> yVals, String label, GPXDataSetType dataSetType) {
super(yVals, label);
this.dataSetType = dataSetType;
}
public GPXDataSetType getDataSetType() {
return dataSetType;
}
}
@SuppressLint("ViewConstructor")
private static class GPXMarkerView extends MarkerView {
private View textAltView;
private View textSpdView;
public GPXMarkerView(Context context) {
super(context, R.layout.chart_marker_view);
textAltView = findViewById(R.id.text_alt_container);
textSpdView = findViewById(R.id.text_spd_container);
}
// callbacks everytime the MarkerView is redrawn, can be used to update the
// content (user-interface)
@Override
public void refreshContent(Entry e, Highlight highlight) {
ChartData chartData = getChartView().getData();
if (chartData.getDataSetCount() == 1) {
OrderedLineDataSet dataSet = (OrderedLineDataSet) chartData.getDataSetByIndex(0);
switch (dataSet.getDataSetType()) {
case ALTITUDE:
((TextView) textAltView.findViewById(R.id.text_alt_value)).setText(Integer.toString((int) e.getY()) + " ");
((TextView) textAltView.findViewById(R.id.text_alt_units)).setText(dataSet.units);
textAltView.setVisibility(VISIBLE);
textSpdView.setVisibility(GONE);
break;
case SPEED:
((TextView) textSpdView.findViewById(R.id.text_spd_value)).setText(Integer.toString((int) e.getY()) + " ");
((TextView) textSpdView.findViewById(R.id.text_spd_units)).setText(dataSet.units);
textAltView.setVisibility(GONE);
textSpdView.setVisibility(VISIBLE);
break;
}
} else if (chartData.getDataSetCount() == 2) {
OrderedLineDataSet dataSet1 = (OrderedLineDataSet) chartData.getDataSetByIndex(0);
OrderedLineDataSet dataSet2 = (OrderedLineDataSet) chartData.getDataSetByIndex(1);
int altSetIndex = dataSet1.getDataSetType() == GPXDataSetType.ALTITUDE ? 0 : 1;
int spdSetIndex = dataSet2.getDataSetType() == GPXDataSetType.SPEED ? 1 : 0;
Entry eAlt = chartData.getEntryForHighlight(new Highlight(e.getX(), Float.NaN, altSetIndex));
Entry eSpd = chartData.getEntryForHighlight(new Highlight(e.getX(), Float.NaN, spdSetIndex));
((TextView) textAltView.findViewById(R.id.text_alt_value)).setText(Integer.toString((int) eAlt.getY()) + " ");
((TextView) textAltView.findViewById(R.id.text_alt_units)).setText((altSetIndex == 0 ? dataSet1.units : dataSet2.units));
((TextView) textSpdView.findViewById(R.id.text_spd_value)).setText(Integer.toString((int) eSpd.getY()) + " ");
((TextView) textSpdView.findViewById(R.id.text_spd_units)).setText(spdSetIndex == 0 ? dataSet1.units : dataSet2.units);
textAltView.setVisibility(VISIBLE);
textSpdView.setVisibility(VISIBLE);
} else {
textAltView.setVisibility(GONE);
textSpdView.setVisibility(GONE);
}
super.refreshContent(e, highlight);
}
@Override
public MPPointF getOffset() {
if (getChartView().getData().getDataSetCount() > 1) {
return new MPPointF(-(textAltView.getWidth() / 2), 0);
} else {
return new MPPointF(-(getWidth() / 2), 0);
}
}
@Override
public MPPointF getOffsetForDrawingAtPoint(float posX, float posY) {
MPPointF offset = getOffset();
offset.y = -posY;
return offset;
}
}

View file

@ -2,7 +2,6 @@ package net.osmand.plus.myplaces;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
@ -26,12 +25,6 @@ import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import com.github.mikephil.charting.components.MarkerView;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.utils.MPPointF;
import net.osmand.data.FavouritePoint;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
@ -526,55 +519,6 @@ public class SelectedGPXFragment extends OsmAndListFragment {
*/
}
public static class MyMarkerView extends MarkerView {
private TextView tvContent;
private String unitsLeft;
private String unitsRight;
public MyMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
tvContent = (TextView) findViewById(R.id.tvContent);
}
public String getUnitsLeft() {
return unitsLeft;
}
public void setUnitsLeft(String unitsLeft) {
this.unitsLeft = unitsLeft;
}
public String getUnitsRight() {
return unitsRight;
}
public void setUnitsRight(String unitsRight) {
this.unitsRight = unitsRight;
}
// callbacks everytime the MarkerView is redrawn, can be used to update the
// content (user-interface)
@Override
public void refreshContent(Entry e, Highlight highlight) {
tvContent.setText(Integer.toString((int)e.getY()) + " "
+ (highlight.getAxis() == YAxis.AxisDependency.LEFT ? unitsLeft : unitsRight));
super.refreshContent(e, highlight);
}
@Override
public MPPointF getOffset() {
return new MPPointF(-(getWidth() / 2), 0);
}
@Override
public MPPointF getOffsetForDrawingAtPoint(float posX, float posY) {
MPPointF offset = getOffset();
offset.y = -posY;
return offset;
}
}
public static class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
@Nullable private final SelectedGpxFile mSelectedGpxFile;
@NonNull private final SelectedGPXFragment mFragment;

View file

@ -20,6 +20,7 @@ import android.widget.TextView;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture;
import com.github.mikephil.charting.listener.OnChartGestureListener;
@ -233,6 +234,12 @@ public class TrackSegmentFragment extends SelectedGPXFragment {
@Override
public void onChartGestureEnd(MotionEvent me, ChartGesture lastPerformedGesture) {
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
Highlight[] highlights = chart.getHighlighted();
if (highlights != null && highlights.length > 0) {
gpxItem.chartHighlightPos = highlights[0].getX();
} else {
gpxItem.chartHighlightPos = -1;
}
for (int i = 0; i < getCount(); i++) {
View v = getViewAtPosition(i);
if (v != finalView) {
@ -508,6 +515,7 @@ public class TrackSegmentFragment extends SelectedGPXFragment {
if (gpxItem.chartMatrix != null) {
chart.getViewPortHandler().refresh(new Matrix(gpxItem.chartMatrix), chart, true);
}
chart.highlightValue(gpxItem.chartHighlightPos, 0);
}
}
}