[android] Add route plan info

Signed-off-by: Gonzalo Pesquero <gpesquero@yahoo.es>
This commit is contained in:
Gonzalo Pesquero 2024-12-26 16:45:22 +01:00
parent 88b138f7ef
commit 19c91ebd6b
12 changed files with 573 additions and 202 deletions

View file

@ -1608,13 +1608,15 @@ Java_app_organicmaps_Framework_nativeGetRoutePoints(JNIEnv * env, jclass)
// Java signature : RouteMarkData(String title, String subtitle,
// @RoutePointInfo.RouteMarkType int pointType,
// int intermediateIndex, boolean isVisible, boolean isMyPosition,
// boolean isPassed, double lat, double lon)
// boolean isPassed, double lat, double lon, long timeSec,
// String distanceString)
static jmethodID const pointConstructor = jni::GetConstructorID(env, pointClazz,
"(Ljava/lang/String;Ljava/lang/String;IIZZZDD)V");
"(Ljava/lang/String;Ljava/lang/String;IIZZZDDJLjava/lang/String;)V");
return jni::ToJavaArray(env, pointClazz, points, [&](JNIEnv * jEnv, RouteMarkData const & data)
{
jni::TScopedLocalRef const title(env, jni::ToJavaString(env, data.m_title));
jni::TScopedLocalRef const subtitle(env, jni::ToJavaString(env, data.m_subTitle));
jni::TScopedLocalRef const distance(env, jni::ToJavaString(env, data.m_distance));
return env->NewObject(pointClazz, pointConstructor,
title.get(), subtitle.get(),
static_cast<jint>(data.m_pointType),
@ -1623,7 +1625,9 @@ Java_app_organicmaps_Framework_nativeGetRoutePoints(JNIEnv * env, jclass)
static_cast<jboolean>(data.m_isMyPosition),
static_cast<jboolean>(data.m_isPassed),
mercator::YToLat(data.m_position.y),
mercator::XToLon(data.m_position.x));
mercator::XToLon(data.m_position.x),
static_cast<jlong>(data.m_timeSec),
distance.get());
});
}

View file

@ -3,6 +3,8 @@ package app.organicmaps.routing;
import androidx.annotation.Keep;
import androidx.annotation.Nullable;
import app.organicmaps.util.Distance;
/**
* Represents RouteMarkData from core.
*/
@ -23,11 +25,14 @@ public class RouteMarkData
public final boolean mIsPassed;
public final double mLat;
public final double mLon;
public final long mTimeSec;
public final String mDistance;
public RouteMarkData(@Nullable String title, @Nullable String subtitle,
@RoutePointInfo.RouteMarkType int pointType,
int intermediateIndex, boolean isVisible, boolean isMyPosition,
boolean isPassed, double lat, double lon)
boolean isPassed, double lat, double lon, long timeSec,
String distance)
{
mTitle = title;
mSubtitle = subtitle;
@ -38,5 +43,7 @@ public class RouteMarkData
mIsPassed = isPassed;
mLat = lat;
mLon = lon;
mTimeSec = timeSec;
mDistance = distance;
}
}

View file

@ -0,0 +1,125 @@
package app.organicmaps.routing;
import android.content.Context;
import android.content.res.TypedArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.util.DateUtils;
import app.organicmaps.util.UiUtils;
public class RoutePlanAdapter extends RecyclerView.Adapter<RoutePlanAdapter.RoutePlanViewHolder>
{
Context mContext;
RouteMarkData[] mRouteMarkData;
public RoutePlanAdapter(Context context, RouteMarkData[] routeMarkData)
{
mContext = context;
// Copy all route points, except the first one (starting point).
mRouteMarkData = new RouteMarkData[routeMarkData.length - 1];
System.arraycopy(routeMarkData, 1, mRouteMarkData, 0, routeMarkData.length - 1);
}
@NonNull
@Override
public RoutePlanViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.route_plan_list_item,
parent, false);
return new RoutePlanViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RoutePlanViewHolder holder, int position)
{
int markPos = mRouteMarkData.length - 1 - position;
int iconId;
if (mRouteMarkData[markPos].mPointType == 0)
{
// Start point.
iconId = R.drawable.route_point_start;
}
else if (mRouteMarkData[markPos].mPointType == 1)
{
// Intermediate stop.
TypedArray iconArray = mContext.getResources().obtainTypedArray(R.array.route_stop_icons);
iconId = iconArray.getResourceId(mRouteMarkData[markPos].mIntermediateIndex,
R.drawable.route_point_01);
}
else
{
// Finish point.
iconId = R.drawable.route_point_finish;
}
holder.mImageViewIcon.setImageDrawable(AppCompatResources.getDrawable(mContext, iconId));
holder.mTextViewEta.setText(DateUtils.getEstimateTimeString(mContext,
mRouteMarkData[markPos].mTimeSec));
if (mRouteMarkData[markPos].mPointType == 0)
{
UiUtils.hide(holder.mTextViewSeparator1);
UiUtils.hide(holder.mTextViewTime);
UiUtils.hide(holder.mTextViewSeparator2);
UiUtils.hide(holder.mTextViewDistance);
}
else
{
holder.mTextViewTime.setText(DateUtils.getRemainingTimeString(mContext,
mRouteMarkData[markPos].mTimeSec));
holder.mTextViewDistance.setText(mRouteMarkData[markPos].mDistance);
}
}
@Override
public int getItemCount()
{
return mRouteMarkData.length;
}
static class RoutePlanViewHolder extends RecyclerView.ViewHolder
{
@NonNull
public final ImageView mImageViewIcon;
@NonNull
public final TextView mTextViewEta;
@NonNull
public final TextView mTextViewSeparator1;
@NonNull
public final TextView mTextViewTime;
@NonNull
public final TextView mTextViewSeparator2;
@NonNull
public final TextView mTextViewDistance;
RoutePlanViewHolder(@NonNull View itemView)
{
super(itemView);
mImageViewIcon = itemView.findViewById(R.id.icon);
mTextViewEta = itemView.findViewById(R.id.eta);
mTextViewSeparator1 = itemView.findViewById(R.id.separator1);
mTextViewTime = itemView.findViewById(R.id.time);
mTextViewSeparator2 = itemView.findViewById(R.id.separator2);
mTextViewDistance = itemView.findViewById(R.id.distance);
}
}
}

View file

@ -17,6 +17,8 @@ import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ScrollView;
@ -26,14 +28,17 @@ import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.Framework;
import app.organicmaps.R;
import app.organicmaps.bookmarks.data.DistanceAndAzimut;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.util.DateUtils;
import app.organicmaps.util.Distance;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.StringUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.recycler.DotDividerItemDecoration;
@ -50,7 +55,7 @@ final class RoutingBottomMenuController implements View.OnClickListener
@NonNull
private final Activity mContext;
@NonNull
private final View mTimeElevationLine;
private final View mAltitudeLine;
@NonNull
private final View mAltitudeChartFrame;
@NonNull
@ -62,13 +67,9 @@ final class RoutingBottomMenuController implements View.OnClickListener
@NonNull
private final ImageView mAltitudeChart;
@NonNull
private final TextView mTime;
private final TextView mAltitudeDiffAscent;
@NonNull
private final TextView mAltitudeDifference;
@NonNull
private final TextView mTimeVehicle;
@Nullable
private final TextView mArrival;
private final TextView mAltitudeDiffDescent;
@NonNull
private final View mActionFrame;
@NonNull
@ -79,6 +80,8 @@ final class RoutingBottomMenuController implements View.OnClickListener
private final ImageView mActionIcon;
@NonNull
private final DotDividerItemDecoration mTransitViewDecorator;
@NonNull
private final RecyclerView mRoutePlanList;
@Nullable
private final RoutingBottomMenuListener mListener;
@ -88,20 +91,19 @@ final class RoutingBottomMenuController implements View.OnClickListener
@Nullable RoutingBottomMenuListener listener)
{
View altitudeChartFrame = getViewById(activity, frame, R.id.altitude_chart_panel);
View timeElevationLine = getViewById(activity, frame, R.id.time_elevation_line);
View altitudeLine = getViewById(activity, frame, R.id.altitude_line);
View transitFrame = getViewById(activity, frame, R.id.transit_panel);
TextView error = (TextView) getViewById(activity, frame, R.id.error);
Button start = (Button) getViewById(activity, frame, R.id.start);
ImageView altitudeChart = (ImageView) getViewById(activity, frame, R.id.altitude_chart);
TextView time = (TextView) getViewById(activity, frame, R.id.time);
TextView timeVehicle = (TextView) getViewById(activity, frame, R.id.time_vehicle);
TextView altitudeDifference = (TextView) getViewById(activity, frame, R.id.altitude_difference);
TextView arrival = (TextView) getViewById(activity, frame, R.id.arrival);
TextView altitudeDiffAscent = (TextView) getViewById(activity, frame, R.id.altitude_diff_ascent);
TextView altitudeDiffDescent = (TextView) getViewById(activity, frame, R.id.altitude_diff_descent);
View actionFrame = getViewById(activity, frame, R.id.routing_action_frame);
RecyclerView routePlanList = (RecyclerView) getViewById(activity, frame, R.id.route_plan_list);
return new RoutingBottomMenuController(activity, altitudeChartFrame, timeElevationLine, transitFrame,
error, start, altitudeChart, time, altitudeDifference,
timeVehicle, arrival, actionFrame, listener);
return new RoutingBottomMenuController(activity, altitudeChartFrame, altitudeLine, transitFrame,
error, start, altitudeChart, altitudeDiffAscent,
altitudeDiffDescent, actionFrame, routePlanList, listener);
}
@NonNull
@ -114,29 +116,26 @@ final class RoutingBottomMenuController implements View.OnClickListener
private RoutingBottomMenuController(@NonNull Activity context,
@NonNull View altitudeChartFrame,
@NonNull View timeElevationLine,
@NonNull View altitudeLine,
@NonNull View transitFrame,
@NonNull TextView error,
@NonNull Button start,
@NonNull ImageView altitudeChart,
@NonNull TextView time,
@NonNull TextView altitudeDifference,
@NonNull TextView timeVehicle,
@Nullable TextView arrival,
@NonNull TextView altitudeDiffAscent,
@NonNull TextView altitudeDiffDescent,
@NonNull View actionFrame,
@NonNull RecyclerView routePlanList,
@Nullable RoutingBottomMenuListener listener)
{
mContext = context;
mAltitudeChartFrame = altitudeChartFrame;
mTimeElevationLine = timeElevationLine;
mAltitudeLine = altitudeLine;
mTransitFrame = transitFrame;
mError = error;
mStart = start;
mAltitudeChart = altitudeChart;
mTime = time;
mAltitudeDifference = altitudeDifference;
mTimeVehicle = timeVehicle;
mArrival = arrival;
mAltitudeDiffAscent = altitudeDiffAscent;
mAltitudeDiffDescent = altitudeDiffDescent;
mActionFrame = actionFrame;
mActionMessage = actionFrame.findViewById(R.id.tv__message);
mActionButton = actionFrame.findViewById(R.id.btn__my_position_use);
@ -149,13 +148,16 @@ final class RoutingBottomMenuController implements View.OnClickListener
int dividerRes = ThemeUtils.getResource(mContext, R.attr.transitStepDivider);
Drawable dividerDrawable = ContextCompat.getDrawable(mContext, dividerRes);
Resources res = mContext.getResources();
mTransitViewDecorator = new DotDividerItemDecoration(dividerDrawable, res.getDimensionPixelSize(R.dimen.margin_base),
mTransitViewDecorator = new DotDividerItemDecoration(dividerDrawable,
res.getDimensionPixelSize(R.dimen.margin_base),
res.getDimensionPixelSize(R.dimen.margin_half));
mRoutePlanList = routePlanList;
mRoutePlanList.setLayoutManager(new LinearLayoutManager(mContext));
}
void showAltitudeChartAndRoutingDetails()
{
UiUtils.hide(mError, mActionFrame, mAltitudeChart, mTimeElevationLine, mTransitFrame);
UiUtils.hide(mError, mActionFrame, mAltitudeChart, mAltitudeLine, mTransitFrame);
if (!RoutingController.get().isVehicleRouterType() && !RoutingController.get().isRulerRouterType())
showRouteAltitudeChart();
@ -185,13 +187,19 @@ final class RoutingBottomMenuController implements View.OnClickListener
scrollToBottom(rv);
TextView estimatedTimeOfArrivalView = mTransitFrame.findViewById(R.id.estimated_time_of_arrival);
estimatedTimeOfArrivalView.setText(DateUtils.getEstimateTimeString(mContext, info.getTotalTime()));
UiUtils.show(mTransitFrame, estimatedTimeOfArrivalView);
UiUtils.show(mTransitFrame, R.id.dot1);
TextView totalTimeView = mTransitFrame.findViewById(R.id.total_time);
totalTimeView.setText(RoutingController.formatRoutingTime(mContext, info.getTotalTime(),
R.dimen.text_size_routing_number));
View dotView = mTransitFrame.findViewById(R.id.dot);
View dot2View = mTransitFrame.findViewById(R.id.dot2);
View pedestrianIcon = mTransitFrame.findViewById(R.id.pedestrian_icon);
TextView distanceView = mTransitFrame.findViewById(R.id.total_distance);
UiUtils.showIf(info.getTotalPedestrianTimeInSec() > 0, dotView, pedestrianIcon, distanceView);
UiUtils.showIf(info.getTotalPedestrianTimeInSec() > 0, dot2View, pedestrianIcon, distanceView);
distanceView.setText(info.getTotalPedestrianDistance() + " " + info.getTotalPedestrianDistanceUnits());
}
@ -216,13 +224,15 @@ final class RoutingBottomMenuController implements View.OnClickListener
scrollToBottom(rv);
}
else
UiUtils.hide(rv); // Show only distance between start and finish
UiUtils.hide(rv); // Show only distance between start and finish.
TextView totalTimeView = mTransitFrame.findViewById(R.id.total_time);
totalTimeView.setText(mContext.getString(R.string.placepage_distance) + ": " +
totalLength.mDistanceStr + " " + totalLength.getUnitsStr(mContext));
UiUtils.hide(mTransitFrame, R.id.dot);
UiUtils.hide(mTransitFrame, R.id.estimated_time_of_arrival);
UiUtils.hide(mTransitFrame, R.id.dot1);
UiUtils.hide(mTransitFrame, R.id.dot2);
UiUtils.hide(mTransitFrame, R.id.pedestrian_icon);
UiUtils.hide(mTransitFrame, R.id.total_distance);
}
@ -330,11 +340,11 @@ final class RoutingBottomMenuController implements View.OnClickListener
{
if (RoutingController.get().isVehicleRouterType())
{
UiUtils.hide(mTimeElevationLine, mAltitudeChart);
UiUtils.hide(mAltitudeLine, mAltitudeChart);
return;
}
UiUtils.hide(mTimeVehicle);
UiUtils.show(mAltitudeLine, mAltitudeChart);
int chartWidth = UiUtils.dimen(mContext, R.dimen.altitude_chart_image_width);
int chartHeight = UiUtils.dimen(mContext, R.dimen.altitude_chart_image_height);
@ -344,39 +354,23 @@ final class RoutingBottomMenuController implements View.OnClickListener
{
mAltitudeChart.setImageBitmap(bm);
UiUtils.show(mAltitudeChart);
final String unit = limits.isMetricUnits ? mAltitudeDifference.getResources().getString(R.string.m) : mAltitudeDifference.getResources().getString(R.string.ft);
mAltitudeDifference.setText("" + limits.totalAscentString + " " + unit +
"" + limits.totalDescentString + " " + unit);
UiUtils.show(mAltitudeDifference);
final String unit = limits.isMetricUnits ? mAltitudeDiffAscent.getResources().getString(R.string.m) :
mAltitudeDiffAscent.getResources().getString(R.string.ft);
mAltitudeDiffAscent.setText(limits.totalAscentString + StringUtils.kNarrowNonBreakingSpace + unit);
mAltitudeDiffDescent.setText(limits.totalDescentString + StringUtils.kNarrowNonBreakingSpace + unit);
UiUtils.show(mAltitudeDiffAscent, mAltitudeDiffDescent);
}
}
private void showRoutingDetails()
{
// Show route plan info.
mRoutePlanList.setAdapter(new RoutePlanAdapter(mContext, Framework.nativeGetRoutePoints()));
final RoutingInfo rinfo = RoutingController.get().getCachedRoutingInfo();
if (rinfo == null)
{
UiUtils.hide(mTimeElevationLine, mTimeVehicle);
return;
}
Spanned spanned = makeSpannedRoutingDetails(mContext, rinfo);
if (RoutingController.get().isVehicleRouterType())
{
UiUtils.show(mTimeVehicle);
mTimeVehicle.setText(spanned);
}
else
{
UiUtils.show(mTimeElevationLine);
mTime.setText(spanned);
}
if (mArrival != null)
{
String arrivalTime = RoutingController.formatArrivalTime(rinfo.totalTimeInSeconds);
mArrival.setText(arrivalTime);
}
UiUtils.hide(mAltitudeLine);
}
// Scroll RecyclerView to bottom using parent ScrollView.
@ -389,7 +383,6 @@ final class RoutingBottomMenuController implements View.OnClickListener
@NonNull
private static Spanned makeSpannedRoutingDetails(@NonNull Context context, @NonNull RoutingInfo routingInfo)
{
CharSequence time = RoutingController.formatRoutingTime(context,
routingInfo.totalTimeInSeconds,

View file

@ -6,7 +6,12 @@ import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import java.text.DateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import app.organicmaps.R;
public final class DateUtils
{
@ -27,4 +32,28 @@ public final class DateUtils
{
return android.text.format.DateFormat.is24HourFormat(context);
}
public static String getEstimateTimeString(@NonNull Context context, long seconds)
{
final String format = android.text.format.DateFormat.is24HourFormat(context)? "HH:mm" : "h:mm a";
final LocalTime localTime = LocalTime.now().plusSeconds(seconds);
return localTime.format(DateTimeFormatter.ofPattern(format));
}
public static String getRemainingTimeString(@NonNull Context context, long seconds)
{
final long hours = TimeUnit.SECONDS.toHours(seconds);
final long minutes = TimeUnit.SECONDS.toMinutes(seconds) % 60;
String timeString = "";
if (hours != 0)
timeString = String.valueOf(hours) + StringUtils.kNarrowNonBreakingSpace +
context.getResources().getString(R.string.hour) + " ";
timeString += String.valueOf(minutes) + StringUtils.kNarrowNonBreakingSpace +
context.getResources().getString(R.string.minute);
return timeString;
}
}

View file

@ -14,6 +14,8 @@ import java.util.Locale;
public class StringUtils
{
final public static String kNarrowNonBreakingSpace = "\u202F";
public static String formatUsingUsLocale(String pattern, Object... args)
{
return String.format(Locale.US, pattern, args);

View file

@ -114,6 +114,21 @@ public final class UiUtils
v.setVisibility(View.VISIBLE);
}
public static void show(View frame, @IdRes int viewId)
{
View view = frame.findViewById(viewId);
if (view == null)
return;
show(view);
}
public static void show(View frame, @IdRes int... viewIds)
{
for (final int id : viewIds)
show(frame, id);
}
public static void invisible(View... views)
{
for (final View v : views)

View file

@ -16,6 +16,7 @@ import app.organicmaps.R;
import app.organicmaps.location.LocationHelper;
import app.organicmaps.routing.RoutingInfo;
import app.organicmaps.sound.TtsPlayer;
import app.organicmaps.util.DateUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.StringUtils;
import app.organicmaps.util.ThemeUtils;
@ -200,10 +201,8 @@ public class NavMenu
private void updateTimeEstimate(int seconds)
{
final String format = android.text.format.DateFormat.is24HourFormat(mTimeMinuteValue.getContext())
? "HH:mm" : "h:mm a";
final LocalTime localTime = LocalTime.now().plusSeconds(seconds);
mTimeEstimate.setText(localTime.format(DateTimeFormatter.ofPattern(format)));
mTimeEstimate.setText(DateUtils.getEstimateTimeString(mTimeMinuteValue.getContext(),
seconds));
}
private void updateSpeedView(@NonNull RoutingInfo info)

View file

@ -1,77 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/altitude_chart_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="@dimen/margin_half"
android:layout_marginBottom="@dimen/margin_half"
android:paddingStart="@dimen/altitude_chart_container_padding_left"
android:paddingEnd="@dimen/altitude_chart_container_padding_left"
android:orientation="horizontal"
android:gravity="center_vertical"
tools:showIn="@layout/fragment_routing">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/altitude_chart_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="@dimen/margin_half"
android:layout_marginBottom="@dimen/margin_half"
android:paddingStart="@dimen/altitude_chart_container_padding_left"
android:paddingEnd="@dimen/altitude_chart_container_padding_left"
android:orientation="horizontal"
android:gravity="center_vertical"
tools:showIn="@layout/fragment_routing">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="0"
android:maxHeight="100dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/route_plan_list"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scrollbars="vertical"
app:layout_constraintHeight="true"
app:layout_constraintHeight_default="wrap"
app:layout_constraintHeight_max="100dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:itemCount="3"
tools:listitem="@layout/route_plan_list_item"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/time_elevation_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:orientation="vertical"
android:layout_marginEnd="@dimen/margin_base"
android:layout_gravity="center_vertical" >
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:maxLines="2"
android:ellipsize="end"
tools:text="5 h 55 min • 1555km"
tools:visibility="visible" />
android:id="@+id/altitude_line"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:visibility="visible">
<ImageView
android:id="@+id/altitude_chart"
android:layout_height="match_parent"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:layout_gravity="center"
android:layout_weight="1"
android:layout_width="0dp"
android:scaleType="fitXY"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="2dp"
android:orientation="vertical">
<TextView
android:id="@+id/altitude_difference"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:text="↗"
android:textColor="?colorAccent"
tools:ignore="HardcodedText"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:text="↘"
android:textColor="?colorAccent"
tools:ignore="HardcodedText"/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/altitude_diff_ascent"
android:layout_gravity="end"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:layout_width="wrap_content"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:gravity="center"
tools:text="↗ 43 m ↘ 88 m"
tools:visibility="visible" />
tools:text="1043 m"/>
<TextView
android:id="@+id/altitude_diff_descent"
android:layout_gravity="end"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:layout_width="wrap_content"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:gravity="start"
android:visibility="visible"
tools:text="88 m"
tools:visibility="visible"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/altitude_chart"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
<Button
android:id="@+id/start"
style="@style/MwmWidget.Button.Primary"
android:layout_gravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_marginStart="@dimen/margin_base"
android:minWidth="@dimen/start_button_width"
android:text="@string/p2p_start"
tools:showIn="@layout/menu_route_plan_line" />
<TextView
android:id="@+id/time_vehicle"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight="1"
android:maxLines="2"
android:ellipsize="end"
tools:text="5 h 55 min • 1555km"
tools:visibility="visible" />
<Button
android:id="@+id/start"
style="@style/MwmWidget.Button.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/margin_base"
android:minWidth="@dimen/start_button_width"
android:text="@string/p2p_start"
tools:showIn="@layout/menu_route_plan_line" />
</LinearLayout>

View file

@ -1,85 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/altitude_chart_panel"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/altitude_chart_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginBottom="@dimen/margin_half"
android:layout_marginTop="@dimen/margin_half"
android:paddingStart="@dimen/altitude_chart_container_padding_left"
android:paddingEnd="@dimen/altitude_chart_container_padding_left"
android:orientation="vertical"
tools:showIn="@layout/fragment_routing">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_width="0dp"
android:maxHeight="150dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/route_plan_list"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:scrollbars="vertical"
app:layout_constraintHeight="true"
app:layout_constraintHeight_max="150dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:itemCount="4"
tools:listitem="@layout/route_plan_list_item"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/start"
style="@style/MwmWidget.Button.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="@dimen/margin_half"
android:minWidth="@dimen/start_button_width"
android:text="@string/p2p_start"
tools:showIn="@layout/menu_route_plan_line"/>
</LinearLayout>
<LinearLayout
android:id="@+id/altitude_line"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginBottom="@dimen/margin_half"
android:orientation="horizontal"
android:layout_marginTop="@dimen/margin_half"
android:paddingStart="@dimen/altitude_chart_container_padding_left"
android:paddingEnd="@dimen/altitude_chart_container_padding_left"
android:orientation="vertical"
tools:showIn="@layout/fragment_routing">
android:layout_marginBottom="@dimen/margin_half">
<ImageView
android:id="@+id/altitude_chart"
android:layout_height="40dp"
android:layout_marginEnd="4dp"
android:layout_weight="1"
android:layout_width="0dp"
android:scaleType="fitXY"/>
<LinearLayout
android:id="@+id/time_elevation_line"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="@dimen/margin_half"
android:layout_marginBottom="@dimen/margin_half">
<TextView
android:id="@+id/time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="2"
android:ellipsize="end"
tools:text="5 h 55 min • 1555km"
tools:visibility="visible" />
android:layout_marginEnd="2dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:text="↗"
android:textColor="?colorAccent"
tools:ignore="HardcodedText"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:text="↘"
android:textColor="?colorAccent"
tools:ignore="HardcodedText"/>
<TextView
android:id="@+id/altitude_difference"
android:layout_width="wrap_content"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:layout_gravity="end"
android:gravity="center"
android:visibility="gone"
tools:text="↗ 43 m ↘ 88 m"
tools:visibility="visible" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical" >
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1">
<ImageView
android:id="@+id/altitude_chart"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
<TextView
android:id="@+id/time_vehicle"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:maxLines="2"
android:ellipsize="end"
tools:text="5 h 55 min • 1555km"
tools:visibility="visible" />
</LinearLayout>
<TextView
android:id="@+id/altitude_diff_ascent"
android:layout_width="wrap_content"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:layout_gravity="end"
tools:text="1043 m"/>
<TextView
android:id="@+id/altitude_diff_descent"
android:layout_width="wrap_content"
android:layout_height="@dimen/altitude_chart_time_distance_height"
android:textAppearance="@style/MwmTextAppearance.Body3"
android:fontFamily="@string/robotoMedium"
android:textColor="?colorAccent"
android:layout_gravity="end"
tools:text="88 m"/>
<Button
android:id="@+id/start"
style="@style/MwmWidget.Button.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_marginStart="@dimen/margin_half"
android:minWidth="@dimen/start_button_width"
android:text="@string/p2p_start"
tools:showIn="@layout/menu_route_plan_line"
android:layout_gravity="center_vertical" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,77 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:srcCompat="@drawable/route_point_finish" />
<TextView
android:id="@+id/eta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text="11:59 PM"
android:textAppearance="@style/MwmTextAppearance.Body1"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/separator1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="·"
android:textAppearance="@style/MwmTextAppearance.Body1"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/eta"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="9h 59min"
android:textAppearance="@style/MwmTextAppearance.Body1"
app:layout_constraintStart_toEndOf="@id/separator1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/separator2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="·"
android:textAppearance="@style/MwmTextAppearance.Body1"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/time"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="999 km"
android:textAppearance="@style/MwmTextAppearance.Body1"
app:layout_constraintStart_toEndOf="@id/separator2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -11,15 +11,34 @@
android:paddingBottom="@dimen/margin_half"
android:paddingTop="@dimen/margin_half_plus">
<TextView
android:id="@+id/total_time"
android:id="@+id/estimated_time_of_arrival"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style="@style/MwmWidget.TextView.PlanDetail.Number.Time"
tools:text="11:59 AM"/>
<TextView
android:id="@+id/dot1"
style="@style/MwmWidget.TextView.PlanDetail.Number.Secondary"
android:layout_marginStart="@dimen/margin_quarter_plus"
android:layout_marginTop="@dimen/margin_eighth"
android:layout_marginEnd="@dimen/margin_quarter_plus"
android:text="•"
app:layout_constraintStart_toEndOf="@id/estimated_time_of_arrival"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText"/>
<TextView
android:id="@+id/total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_quarter_plus"
app:layout_constraintStart_toEndOf="@id/dot1"
app:layout_constraintTop_toTopOf="parent"
style="@style/MwmWidget.TextView.PlanDetail.Number.Time"
tools:text="40 min"/>
<TextView
android:id="@+id/dot"
android:id="@+id/dot2"
style="@style/MwmWidget.TextView.PlanDetail.Number.Secondary"
android:layout_marginStart="@dimen/margin_quarter_plus"
android:layout_marginTop="@dimen/margin_eighth"
@ -35,7 +54,7 @@
android:layout_marginStart="@dimen/margin_quarter_plus"
app:srcCompat="@drawable/ic_20px_route_planning_walk"
app:layout_constraintBottom_toBottomOf="@id/total_time"
app:layout_constraintStart_toEndOf="@id/dot"
app:layout_constraintStart_toEndOf="@id/dot2"
app:tint="?iconTint"/>
<TextView
android:id="@+id/total_distance"