Fix small UI issues

This commit is contained in:
Victor Shcherb 2011-11-29 09:11:48 +01:00
parent b08f0a5ab3
commit 1eb19f170c
20 changed files with 367 additions and 327 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -87,9 +87,9 @@ public class OsmAndFormatter {
MetricsConstants mc = settings.METRIC_SYSTEM.get();
float kmh = metersperseconds * 3.6f;
if(mc == MetricsConstants.KILOMETERS_AND_METERS){
return ((int) kmh) + ctx.getString(R.string.km_h);
return ((int) kmh) + " " + ctx.getString(R.string.km_h);
} else {
return ((int) (kmh * METERS_IN_KILOMETER / METERS_IN_ONE_MILE)) + ctx.getString(R.string.mile_per_hour);
return ((int) (kmh * METERS_IN_KILOMETER / METERS_IN_ONE_MILE)) + " "+ ctx.getString(R.string.mile_per_hour);
}
}

View file

@ -3,7 +3,6 @@
*/
package net.osmand.plus.activities;
import java.text.MessageFormat;
import java.util.List;
import net.osmand.OsmAndFormatter;
@ -11,18 +10,8 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper.TurnType;
import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.TurnPathHelper;
import android.app.ListActivity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.util.DisplayMetrics;
@ -86,54 +75,6 @@ public class ShowRouteInfoActivity extends ListActivity {
}
class RouteDrawable extends Drawable {
Paint paintRouteDirection;
Path p = new Path();
Path dp = new Path();
public RouteDrawable(){
paintRouteDirection = new Paint();
paintRouteDirection.setStyle(Style.FILL_AND_STROKE);
paintRouteDirection.setColor(Color.rgb(100, 0, 255));
paintRouteDirection.setAntiAlias(true);
}
@Override
protected void onBoundsChange(Rect bounds) {
Matrix m = new Matrix();
m.setScale(bounds.width()/96f, bounds.height()/96f);
p.transform(m, dp);
}
public void setRouteType(TurnType t){
MapInfoLayer.calcTurnPath(p, t, null);
onBoundsChange(getBounds());
}
@Override
public void draw(Canvas canvas) {
canvas.drawPath(dp, paintRouteDirection);
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
paintRouteDirection.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paintRouteDirection.setColorFilter(cf);
}
}
class RouteInfoAdapter extends ArrayAdapter<RouteDirectionInfo> {
RouteInfoAdapter(List<RouteDirectionInfo> list) {
super(ShowRouteInfoActivity.this, R.layout.route_info_list_item, list);
@ -154,10 +95,10 @@ public class ShowRouteInfoActivity extends ListActivity {
TextView timeLabel = (TextView) row.findViewById(R.id.time);
ImageView icon = (ImageView) row.findViewById(R.id.direction);
if(!(icon.getDrawable() instanceof RouteDrawable)){
icon.setImageDrawable(new RouteDrawable());
if(!(icon.getDrawable() instanceof TurnPathHelper.RouteDrawable)){
icon.setImageDrawable(new TurnPathHelper.RouteDrawable());
}
((RouteDrawable) icon.getDrawable()).setRouteType(model.turnType);
((TurnPathHelper.RouteDrawable) icon.getDrawable()).setRouteType(model.turnType);
distanceLabel.setText(OsmAndFormatter.getFormattedDistance(model.distance, ShowRouteInfoActivity.this));
label.setText(model.descriptionRoute);
int seconds = model.expectedTime % 60;

View file

@ -12,11 +12,10 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
@ -47,15 +46,12 @@ public class ContextMenuLayer extends OsmandMapLayer {
private TextView textView;
private DisplayMetrics dm;
private OsmandMapTileView view;
private static final int BASE_TEXT_SIZE = 170;
private static final int MARGIN_Y_TO_BOX = 12;
private int textSize = BASE_TEXT_SIZE;
private int BASE_TEXT_SIZE = 170;
private int SHADOW_OF_LEG = 5;
private Paint paintLightBorder;
private Paint paintBlack;
private Paint paintBorder;
private final MapActivity activity;
private Rect padding = new Rect();
private Drawable boxLeg;
private float scaleCoefficient = 1;
public ContextMenuLayer(MapActivity activity){
this.activity = activity;
@ -71,29 +67,28 @@ public class ContextMenuLayer extends OsmandMapLayer {
dm = new DisplayMetrics();
WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
wmgr.getDefaultDisplay().getMetrics(dm);
textSize = (int) (BASE_TEXT_SIZE * dm.density);
scaleCoefficient = dm.density;
if (Math.min(dm.widthPixels / (dm.density * 160), dm.heightPixels / (dm.density * 160)) > 2.5f) {
// large screen
scaleCoefficient *= 1.5f;
}
BASE_TEXT_SIZE = (int) (BASE_TEXT_SIZE * scaleCoefficient);
SHADOW_OF_LEG = (int) (SHADOW_OF_LEG * scaleCoefficient);
paintLightBorder = new Paint();
paintLightBorder.setARGB(130, 220, 220, 220);
paintLightBorder.setStyle(Style.FILL);
paintBlack = new Paint();
paintBlack.setARGB(255, 0, 0, 0);
paintBlack.setStyle(Style.STROKE);
paintBlack.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setARGB(220, 160, 160, 160);
paintBorder.setStyle(Style.FILL);
boxLeg = view.getResources().getDrawable(R.drawable.box_leg);
boxLeg.setBounds(0, 0, boxLeg.getMinimumWidth(), boxLeg.getMinimumHeight());
textView = new TextView(view.getContext());
LayoutParams lp = new LayoutParams(textSize, LayoutParams.WRAP_CONTENT);
LayoutParams lp = new LayoutParams(BASE_TEXT_SIZE, LayoutParams.WRAP_CONTENT);
textView.setLayoutParams(lp);
textView.setTextSize(16);
textView.setTextSize(15 * scaleCoefficient);
textView.setTextColor(Color.argb(255, 0, 0, 0));
textView.setMinLines(1);
// textView.setMaxLines(15);
textView.setGravity(Gravity.CENTER_HORIZONTAL);
textView.setClickable(true);
textView.setBackgroundDrawable(view.getResources().getDrawable(R.drawable.box_free));
}
@ -102,11 +97,15 @@ public class ContextMenuLayer extends OsmandMapLayer {
if(latLon != null){
int x = view.getRotatedMapXForPoint(latLon.getLatitude(), latLon.getLongitude());
int y = view.getRotatedMapYForPoint(latLon.getLatitude(), latLon.getLongitude());
canvas.drawCircle(x, y, 5 * dm.density, paintBorder);
canvas.drawCircle(x, y, 5 * dm.density, paintBlack);
int tx = x - boxLeg.getMinimumWidth() / 2;
int ty = y - boxLeg.getMinimumHeight() + SHADOW_OF_LEG;
canvas.translate(tx, ty);
boxLeg.draw(canvas);
canvas.translate(-tx, -ty);
if (textView.getText().length() > 0) {
canvas.translate(x - textView.getWidth() / 2, y - textView.getHeight() - MARGIN_Y_TO_BOX);
canvas.translate(x - textView.getWidth() / 2, ty - textView.getTop());
int c = textView.getLineCount();
textView.draw(canvas);
@ -120,13 +119,13 @@ public class ContextMenuLayer extends OsmandMapLayer {
}
private void layoutText() {
Rect padding = new Rect();
if(textView.getLineCount() > 0) {
textView.getBackground().getPadding(padding);
}
int w = textSize;
int h = (int) ((textView.getPaint().getTextSize() +4) * textView.getLineCount()) +
padding.bottom + padding.top;
textView.layout(0, 0, w, h);
int w = BASE_TEXT_SIZE;
int h = (int) ((textView.getPaint().getTextSize() +4) * textView.getLineCount());
textView.layout(0, -padding.bottom - padding.top, w, h);
}
public void setLocation(LatLon loc, String description){
@ -190,7 +189,7 @@ public class ContextMenuLayer extends OsmandMapLayer {
int x = (int) (px - view.getRotatedMapXForPoint(latLon.getLatitude(), latLon.getLongitude()));
int y = (int) (py - view.getRotatedMapYForPoint(latLon.getLatitude(), latLon.getLongitude()));
x += bs.width() / 2;
y += bs.height() + MARGIN_Y_TO_BOX;
y += bs.height() + boxLeg.getMinimumHeight() - SHADOW_OF_LEG;
if (bs.contains(x, y)) {
return true;
}

View file

@ -20,14 +20,12 @@ import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@ -42,39 +40,27 @@ import android.widget.TextView;
public class MapInfoLayer extends OsmandMapLayer {
private OsmandMapTileView view;
private boolean showMiniMap = false;
private final MapActivity map;
private final RouteLayer routeLayer;
private OsmandMapTileView view;
private boolean showMiniMap = false;
private boolean showArrivalTime = true;
private Path pathForTurn;
private Paint paintBlack;
private Paint paintText;
private Paint paintSubText;
private Paint paintMiniRoute;
private Paint fillBlack;
private Paint fillRed;
private Paint paintAlphaGray;
private Paint paintRouteDirection;
private RectF boundsForMiniRoute;
private long cachedLeftTime = 0;
private float[] calculations = new float[1];
private int cachedMeters = 0;
private float cachedSpeed = 0;
private float cachedRotate = 0;
private int centerMiniRouteY;
private int centerMiniRouteX;
private float scaleMiniRoute;
private Matrix pathTransform;
private TurnType cachedTurnType = null;
private String cachedExitOut = null;
private DisplayMetrics dm;
private float scaleCoefficient;
@ -88,18 +74,22 @@ public class MapInfoLayer extends OsmandMapLayer {
private TextInfoControl distanceControl;
private TextInfoControl speedControl;
private TextInfoControl leftTimeControl;
private NextTurnInfoControl nextTurnInfo;
private ImageView backToLocation;
private ImageView compassView;
private View progressBar;
// groups
private List<MapInfoControl> leftControls = new ArrayList<MapInfoLayer.MapInfoControl>();
private List<MapInfoControl> rightControls = new ArrayList<MapInfoLayer.MapInfoControl>();
private ViewGroup statusBar;
private Drawable statusBarBackground;
// currently pressed view
private View pressedView = null;
private Drawable statusBarBackground;
public MapInfoLayer(MapActivity map, RouteLayer layer){
this.map = map;
@ -144,11 +134,6 @@ public class MapInfoLayer extends OsmandMapLayer {
paintImg.setFilterBitmap(true);
paintImg.setAntiAlias(true);
paintAlphaGray = new Paint();
paintAlphaGray.setStyle(Style.FILL_AND_STROKE);
paintAlphaGray.setColor(Color.LTGRAY);
paintAlphaGray.setAlpha(180); // do not make very transparent (to hide route)
paintRouteDirection = new Paint();
paintRouteDirection.setStyle(Style.FILL_AND_STROKE);
paintRouteDirection.setColor(Color.rgb(100, 0, 255));
@ -172,20 +157,6 @@ public class MapInfoLayer extends OsmandMapLayer {
fillRed.setColor(Color.RED);
fillRed.setAntiAlias(true);
boundsForMiniRoute = new RectF(0, 64, 96, 196);
// Scale to have proper view
scaleRect(boundsForMiniRoute);
centerMiniRouteX = (int) (boundsForMiniRoute.width()/2);
centerMiniRouteY= (int) (boundsForMiniRoute.top + 3 * boundsForMiniRoute.height() /4);
scaleMiniRoute = 0.15f;
pathForTurn = new Path();
pathTransform = new Matrix();
pathTransform.postScale(scaleCoefficient, scaleCoefficient);
pathTransform.postTranslate(boundsForMiniRoute.left, boundsForMiniRoute.top);
STATUS_BAR_MARGIN_X = (int) (STATUS_BAR_MARGIN_X * scaleCoefficient);
@ -224,14 +195,16 @@ public class MapInfoLayer extends OsmandMapLayer {
rightControls.add(leftTimeControl);
showArrivalTime = view.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME.get();
nextTurnInfo = new NextTurnInfoControl(R.drawable.box_top, paintText, paintSubText);
nextTurnInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showMiniMap = !showMiniMap;
view.refreshMap();
}
private void scaleRect(RectF r){
r.bottom *= scaleCoefficient;
r.left *= scaleCoefficient;
r.right *= scaleCoefficient;
r.top *= scaleCoefficient;
});
leftControls.add(nextTurnInfo);
showArrivalTime = view.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME.get();
}
public void relayoutLeftControls(MapInfoControl... cs){
@ -309,14 +282,17 @@ public class MapInfoLayer extends OsmandMapLayer {
@Override
public void onDraw(Canvas canvas, RectF latlonBounds, RectF tilesRect, boolean nightMode) {
// prepare data (left distance, speed)
// prepare data (left distance, speed, compass)
updateDistanceToGo();
updateSpeedInfo();
updateTimeLeftInfo();
// draw route information
drawRouteInfo(canvas);
if(view.getRotate() != cachedRotate) {
cachedRotate = view.getRotate();
compassView.invalidate();
}
if(nextTurnInfo.isVisible() != (nextTurnInfo.getMeasuredHeight() > 0)) {
relayoutLeftControls(nextTurnInfo);
}
// draw left controls
for (int i = leftControls.size() - 1; i >= 0; i--) {
@ -391,49 +367,6 @@ public class MapInfoLayer extends OsmandMapLayer {
}
private void drawRouteInfo(Canvas canvas) {
if(routeLayer != null && routeLayer.getHelper().isRouterEnabled()){
if (routeLayer.getHelper().isFollowingMode()) {
int d = routeLayer.getHelper().getDistanceToNextRouteDirection();
if (showMiniMap || d == 0) {
if (!routeLayer.getPath().isEmpty()) {
canvas.save();
canvas.clipRect(boundsForMiniRoute);
// TODO draw rect boundsForMiniRoute
canvas.translate(centerMiniRouteX - view.getCenterPointX(), centerMiniRouteY - view.getCenterPointY());
canvas.scale(scaleMiniRoute, scaleMiniRoute, view.getCenterPointX(), view.getCenterPointY());
canvas.rotate(view.getRotate(), view.getCenterPointX(), view.getCenterPointY());
canvas.drawCircle(view.getCenterPointX(), view.getCenterPointY(), 3 / scaleMiniRoute, fillBlack);
canvas.drawPath(routeLayer.getPath(), paintMiniRoute);
canvas.restore();
}
} else {
// TODO draw rect boundsForMiniRoute
RouteDirectionInfo next = routeLayer.getHelper().getNextRouteDirectionInfo();
if (next != null) {
if (!Algoritms.objectEquals(cachedTurnType, next.turnType)) {
cachedTurnType = next.turnType;
calcTurnPath(pathForTurn, cachedTurnType, pathTransform);
if (cachedTurnType.getExitOut() > 0) {
cachedExitOut = cachedTurnType.getExitOut() + ""; //$NON-NLS-1$
} else {
cachedExitOut = null;
}
}
canvas.drawPath(pathForTurn, paintRouteDirection);
canvas.drawPath(pathForTurn, paintBlack);
if (cachedExitOut != null) {
canvas.drawText(cachedExitOut, boundsForMiniRoute.centerX() - 6 * scaleCoefficient,
boundsForMiniRoute.centerY() - 9 * scaleCoefficient, paintBlack);
}
canvas.drawText(OsmAndFormatter.getFormattedDistance(d, map), boundsForMiniRoute.left + 10 * scaleCoefficient,
boundsForMiniRoute.bottom - 9 * scaleCoefficient, paintBlack);
}
}
}
}
}
@Override
public void destroyLayer() {
@ -487,17 +420,6 @@ public class MapInfoLayer extends OsmandMapLayer {
return progressBar;
}
@Override
public boolean onSingleTap(PointF point) {
if (routeLayer != null && routeLayer.getHelper().isRouterEnabled()) {
if (boundsForMiniRoute.contains(point.x, point.y) && routeLayer.getHelper().isFollowingMode()) {
showMiniMap = !showMiniMap;
view.refreshMap();
return true;
}
}
return false;
}
private ViewGroup createStatusBar() {
@ -524,8 +446,7 @@ public class MapInfoLayer extends OsmandMapLayer {
flp.gravity = Gravity.TOP;
statusBar.setLayoutParams(flp);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
//params.leftMargin = (int) (5 * scaleCoefficient);
ImageView compassView = new ImageView(view.getContext()) {
compassView = new ImageView(view.getContext()) {
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
@ -578,7 +499,8 @@ public class MapInfoLayer extends OsmandMapLayer {
fl.addView(progressBar, fparams);
params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (3 * scaleCoefficient);
params.leftMargin = (int) (10 * scaleCoefficient);
params.rightMargin = (int) (1 * scaleCoefficient);
backToLocation = new ImageView(view.getContext());
backToLocation.setImageDrawable(view.getResources().getDrawable(R.drawable.back_to_loc));
backToLocation.setOnClickListener(new View.OnClickListener() {
@ -715,134 +637,115 @@ public class MapInfoLayer extends OsmandMapLayer {
}
}
public class NextTurnInfoControl extends MapInfoControl {
// draw path 96x96
public static void calcTurnPath(Path pathForTurn, TurnType turnType, Matrix transform) {
if(turnType == null){
return;
private final float scaleMiniRoute = 0.15f;
private final float width = 96 * scaleCoefficient;
private final float height = 96 * scaleCoefficient;
private final float centerMiniRouteY = 3 * height /4;
private final float centerMiniRouteX = width / 2;
private Path pathForTurn = new Path();
private Matrix pathTransform = new Matrix();
private TurnType cachedTurnType = null;
private String cachedExitOut = null;
private final Paint textPaint;
private final Paint subtextPaint;
public NextTurnInfoControl(int background, Paint textPaint, Paint subtextPaint) {
super(background);
this.textPaint = textPaint;
this.subtextPaint = subtextPaint;
}
pathForTurn.reset();
int c = 48;
int w = 16;
pathForTurn.moveTo(c, 94);
float sarrowL = 30; // side of arrow
float harrowL = (float) Math.sqrt(2) * sarrowL; // hypotenuse of arrow
float spartArrowL = (float) ((sarrowL - w / Math.sqrt(2)) / 2);
float hpartArrowL = (float) (harrowL - w) / 2;
if (TurnType.C.equals(turnType.getValue())) {
int h = 65;
pathForTurn.rMoveTo(w / 2, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rLineTo(hpartArrowL, 0);
pathForTurn.rLineTo(-harrowL / 2, -harrowL / 2); // center
pathForTurn.rLineTo(-harrowL / 2, harrowL / 2);
pathForTurn.rLineTo(hpartArrowL, 0);
pathForTurn.rLineTo(0, h);
} else if (TurnType.TR.equals(turnType.getValue())|| TurnType.TL.equals(turnType.getValue())) {
int b = TurnType.TR.equals(turnType.getValue())? 1 : -1;
int h = 36;
float quadShiftX = 22;
float quadShiftY = 22;
pathForTurn.rMoveTo(-b * 8, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rQuadTo(0, -quadShiftY, b * quadShiftX, -quadShiftY);
pathForTurn.rLineTo(0, hpartArrowL);
pathForTurn.rLineTo(b * harrowL / 2, -harrowL / 2); // center
pathForTurn.rLineTo(-b * harrowL / 2, -harrowL / 2);
pathForTurn.rLineTo(0, hpartArrowL);
pathForTurn.rQuadTo(-b * (quadShiftX + w), 0, -b * (quadShiftX + w), quadShiftY + w);
pathForTurn.rLineTo(0, h);
} else if (TurnType.TSLR.equals(turnType.getValue()) || TurnType.TSLL.equals(turnType.getValue())) {
int b = TurnType.TSLR.equals(turnType.getValue()) ? 1 : -1;
int h = 40;
int quadShiftY = 22;
float quadShiftX = (float) (quadShiftY / (1 + Math.sqrt(2)));
float nQuadShiftX = (sarrowL - 2 * spartArrowL) - quadShiftX - w;
float nQuadShifty = quadShiftY + (sarrowL - 2 * spartArrowL);
pathForTurn.rMoveTo(-b * 4, 0);
pathForTurn.rLineTo(0, -h /* + partArrowL */);
pathForTurn.rQuadTo(0, -quadShiftY + quadShiftX /*- partArrowL*/, b * quadShiftX, -quadShiftY /*- partArrowL*/);
pathForTurn.rLineTo(b * spartArrowL, spartArrowL);
pathForTurn.rLineTo(0, -sarrowL); // center
pathForTurn.rLineTo(-b * sarrowL, 0);
pathForTurn.rLineTo(b * spartArrowL, spartArrowL);
pathForTurn.rQuadTo(b * nQuadShiftX, -nQuadShiftX, b * nQuadShiftX, nQuadShifty);
pathForTurn.rLineTo(0, h);
} else if (TurnType.TSHR.equals(turnType.getValue()) || TurnType.TSHL.equals(turnType.getValue())) {
int b = TurnType.TSHR.equals(turnType.getValue()) ? 1 : -1;
int h = 45;
float quadShiftX = 22;
float quadShiftY = -(float) (quadShiftX / (1 + Math.sqrt(2)));
float nQuadShiftX = -(sarrowL - 2 * spartArrowL) - quadShiftX - w;
float nQuadShiftY = -quadShiftY + (sarrowL - 2 * spartArrowL);
pathForTurn.rMoveTo(-b * 8, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rQuadTo(0, -(quadShiftX - quadShiftY), b * quadShiftX, quadShiftY);
pathForTurn.rLineTo(-b * spartArrowL, spartArrowL);
pathForTurn.rLineTo(b * sarrowL, 0); // center
pathForTurn.rLineTo(0, -sarrowL);
pathForTurn.rLineTo(-b * spartArrowL, spartArrowL);
pathForTurn.rCubicTo(b * nQuadShiftX / 2, nQuadShiftX / 2, b * nQuadShiftX, nQuadShiftX / 2, b * nQuadShiftX, nQuadShiftY);
pathForTurn.rLineTo(0, h);
} else if(TurnType.TU.equals(turnType.getValue())) {
int h = 54;
float quadShiftX = 13;
float quadShiftY = 13;
pathForTurn.rMoveTo(28, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rQuadTo(0, -(quadShiftY+w), -(quadShiftX+w), -(quadShiftY+w));
pathForTurn.rQuadTo(-(quadShiftX+w), 0, -(quadShiftX+w), (quadShiftY+w));
pathForTurn.rLineTo(-hpartArrowL, 0);
pathForTurn.rLineTo(harrowL/2, harrowL/2); // center
pathForTurn.rLineTo(harrowL/2, -harrowL/2);
pathForTurn.rLineTo(-hpartArrowL, 0);
pathForTurn.rQuadTo(0, -quadShiftX, quadShiftX, -quadShiftY);
pathForTurn.rQuadTo(quadShiftX, 0, quadShiftX, quadShiftY);
pathForTurn.rLineTo(0, h);
} else if (turnType != null && turnType.isRoundAbout()) {
float t = turnType.getTurnAngle();
if (t >= 170 && t < 220) {
t = 220;
} else if (t > 160 && t < 170) {
t = 160;
public boolean isVisible() {
// TODO
if (routeLayer != null && routeLayer.getHelper().isRouterEnabled() /*&& routeLayer.getHelper().isFollowingMode()*/) {
int d = routeLayer.getHelper().getDistanceToNextRouteDirection();
if (d > 0 || (showMiniMap && !routeLayer.getPath().isEmpty())) {
return true;
}
}
return false;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
pathTransform = new Matrix();
pathTransform.postScale(scaleCoefficient, scaleCoefficient);
pathTransform.postTranslate(left, top);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(!isVisible()) {
setMeasuredDimension(0, 0);
} else if(showMiniMap){
setMeasuredDimension((int) width, (int) height);
} else {
int h = (int) (5 * scaleCoefficient + Math.max(textPaint.getTextSize(), subtextPaint.getTextSize()));
setMeasuredDimension((int) width, (int) height + h);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// TODO
if (routeLayer != null /*&& routeLayer.getHelper().isFollowingMode()*/) {
int d = routeLayer.getHelper().getDistanceToNextRouteDirection();
if (showMiniMap || d == 0) {
if (!routeLayer.getPath().isEmpty()) {
canvas.save();
canvas.translate(centerMiniRouteX - view.getCenterPointX(), centerMiniRouteY - view.getCenterPointY());
canvas.scale(scaleMiniRoute, scaleMiniRoute, view.getCenterPointX(), view.getCenterPointY());
canvas.rotate(view.getRotate(), view.getCenterPointX(), view.getCenterPointY());
canvas.drawCircle(view.getCenterPointX(), view.getCenterPointY(), 3 / scaleMiniRoute, fillBlack);
canvas.drawPath(routeLayer.getPath(), paintMiniRoute);
canvas.restore();
}
} else {
RouteDirectionInfo next = routeLayer.getHelper().getNextRouteDirectionInfo();
if (next != null) {
if (!Algoritms.objectEquals(cachedTurnType, next.turnType)) {
cachedTurnType = next.turnType;
TurnPathHelper.calcTurnPath(pathForTurn, cachedTurnType, pathTransform);
if (cachedTurnType.getExitOut() > 0) {
cachedExitOut = cachedTurnType.getExitOut() + ""; //$NON-NLS-1$
} else {
cachedExitOut = null;
}
}
canvas.drawPath(pathForTurn, paintRouteDirection);
canvas.drawPath(pathForTurn, paintBlack);
// TODO test
if (cachedExitOut != null) {
canvas.drawText(cachedExitOut, (getLeft() + getRight()) / 2 - 6 * scaleCoefficient, (getTop() + getBottom())
/ 2 - 9 * scaleCoefficient, paintBlack);
}
String text = OsmAndFormatter.getFormattedDistance(cachedMeters, map);
String subtext = null;
int ls = text.lastIndexOf(' ');
if (ls != -1) {
subtext = text.substring(ls + 1);
text = text.substring(0, ls);
}
// TODO align center
int margin = (int) (10 * scaleCoefficient);
canvas.drawText(text, margin + getLeft(), getBottom() - 3 * scaleCoefficient, textPaint);
if (subtext != null) {
canvas.drawText(subtext, getLeft() + margin + 2 * scaleCoefficient + textPaint.measureText(text), getBottom()
- 3 * scaleCoefficient, subtextPaint);
}
}
float sweepAngle = (t - 360) - 180;
if (sweepAngle < -360) {
sweepAngle += 360;
}
float r1 = 32f;
float r2 = 24f;
float angleToRot = 0.3f;
pathForTurn.moveTo(48, 48 + r1 + 8);
pathForTurn.lineTo(48, 48 + r1);
RectF r = new RectF(48 - r1, 48 - r1, 48 + r1, 48 + r1);
pathForTurn.arcTo(r, 90, sweepAngle);
float angleRad = (float) ((180 + sweepAngle)*Math.PI/180f);
pathForTurn.lineTo(48 + (r1 + 4) * FloatMath.sin(angleRad), 48 - (r1 + 4) * FloatMath.cos(angleRad));
pathForTurn.lineTo(48 + (r1 + 6) * FloatMath.sin(angleRad + angleToRot/2), 48 - (r1 + 6) * FloatMath.cos(angleRad + angleToRot/2));
pathForTurn.lineTo(48 + (r1 + 12) * FloatMath.sin(angleRad - angleToRot/2), 48 - (r1 + 12) * FloatMath.cos(angleRad - angleToRot/2));
pathForTurn.lineTo(48 + (r1 + 6) * FloatMath.sin(angleRad - 3*angleToRot/2), 48 - (r1 + 6) * FloatMath.cos(angleRad - 3*angleToRot/2));
pathForTurn.lineTo(48 + (r1 + 4) * FloatMath.sin(angleRad - angleToRot), 48 - (r1 + 4) * FloatMath.cos(angleRad - angleToRot));
pathForTurn.lineTo(48 + r2 * FloatMath.sin(angleRad - angleToRot), 48 - r2 * FloatMath.cos(angleRad - angleToRot));
r.set(48 - r2, 48 - r2, 48 + r2, 48 + r2);
pathForTurn.arcTo(r, 360 + sweepAngle + 90, -sweepAngle);
pathForTurn.lineTo(40, 48 + r2);
pathForTurn.lineTo(40, 48 + r1 + 8);
pathForTurn.close();
}
pathForTurn.close();
if(transform != null){
pathForTurn.transform(transform);
}
}

View file

@ -0,0 +1,197 @@
package net.osmand.plus.views;
import net.osmand.plus.routing.RoutingHelper.TurnType;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.util.FloatMath;
public class TurnPathHelper {
// draw path 96x96
public static void calcTurnPath(Path pathForTurn, TurnType turnType, Matrix transform) {
if(turnType == null){
return;
}
pathForTurn.reset();
int c = 48;
int w = 16;
pathForTurn.moveTo(c, 94);
float sarrowL = 30; // side of arrow
float harrowL = (float) Math.sqrt(2) * sarrowL; // hypotenuse of arrow
float spartArrowL = (float) ((sarrowL - w / Math.sqrt(2)) / 2);
float hpartArrowL = (float) (harrowL - w) / 2;
if (TurnType.C.equals(turnType.getValue())) {
int h = 65;
pathForTurn.rMoveTo(w / 2, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rLineTo(hpartArrowL, 0);
pathForTurn.rLineTo(-harrowL / 2, -harrowL / 2); // center
pathForTurn.rLineTo(-harrowL / 2, harrowL / 2);
pathForTurn.rLineTo(hpartArrowL, 0);
pathForTurn.rLineTo(0, h);
} else if (TurnType.TR.equals(turnType.getValue())|| TurnType.TL.equals(turnType.getValue())) {
int b = TurnType.TR.equals(turnType.getValue())? 1 : -1;
int h = 36;
float quadShiftX = 22;
float quadShiftY = 22;
pathForTurn.rMoveTo(-b * 8, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rQuadTo(0, -quadShiftY, b * quadShiftX, -quadShiftY);
pathForTurn.rLineTo(0, hpartArrowL);
pathForTurn.rLineTo(b * harrowL / 2, -harrowL / 2); // center
pathForTurn.rLineTo(-b * harrowL / 2, -harrowL / 2);
pathForTurn.rLineTo(0, hpartArrowL);
pathForTurn.rQuadTo(-b * (quadShiftX + w), 0, -b * (quadShiftX + w), quadShiftY + w);
pathForTurn.rLineTo(0, h);
} else if (TurnType.TSLR.equals(turnType.getValue()) || TurnType.TSLL.equals(turnType.getValue())) {
int b = TurnType.TSLR.equals(turnType.getValue()) ? 1 : -1;
int h = 40;
int quadShiftY = 22;
float quadShiftX = (float) (quadShiftY / (1 + Math.sqrt(2)));
float nQuadShiftX = (sarrowL - 2 * spartArrowL) - quadShiftX - w;
float nQuadShifty = quadShiftY + (sarrowL - 2 * spartArrowL);
pathForTurn.rMoveTo(-b * 4, 0);
pathForTurn.rLineTo(0, -h /* + partArrowL */);
pathForTurn.rQuadTo(0, -quadShiftY + quadShiftX /*- partArrowL*/, b * quadShiftX, -quadShiftY /*- partArrowL*/);
pathForTurn.rLineTo(b * spartArrowL, spartArrowL);
pathForTurn.rLineTo(0, -sarrowL); // center
pathForTurn.rLineTo(-b * sarrowL, 0);
pathForTurn.rLineTo(b * spartArrowL, spartArrowL);
pathForTurn.rQuadTo(b * nQuadShiftX, -nQuadShiftX, b * nQuadShiftX, nQuadShifty);
pathForTurn.rLineTo(0, h);
} else if (TurnType.TSHR.equals(turnType.getValue()) || TurnType.TSHL.equals(turnType.getValue())) {
int b = TurnType.TSHR.equals(turnType.getValue()) ? 1 : -1;
int h = 45;
float quadShiftX = 22;
float quadShiftY = -(float) (quadShiftX / (1 + Math.sqrt(2)));
float nQuadShiftX = -(sarrowL - 2 * spartArrowL) - quadShiftX - w;
float nQuadShiftY = -quadShiftY + (sarrowL - 2 * spartArrowL);
pathForTurn.rMoveTo(-b * 8, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rQuadTo(0, -(quadShiftX - quadShiftY), b * quadShiftX, quadShiftY);
pathForTurn.rLineTo(-b * spartArrowL, spartArrowL);
pathForTurn.rLineTo(b * sarrowL, 0); // center
pathForTurn.rLineTo(0, -sarrowL);
pathForTurn.rLineTo(-b * spartArrowL, spartArrowL);
pathForTurn.rCubicTo(b * nQuadShiftX / 2, nQuadShiftX / 2, b * nQuadShiftX, nQuadShiftX / 2, b * nQuadShiftX, nQuadShiftY);
pathForTurn.rLineTo(0, h);
} else if(TurnType.TU.equals(turnType.getValue())) {
int h = 54;
float quadShiftX = 13;
float quadShiftY = 13;
pathForTurn.rMoveTo(28, 0);
pathForTurn.rLineTo(0, -h);
pathForTurn.rQuadTo(0, -(quadShiftY+w), -(quadShiftX+w), -(quadShiftY+w));
pathForTurn.rQuadTo(-(quadShiftX+w), 0, -(quadShiftX+w), (quadShiftY+w));
pathForTurn.rLineTo(-hpartArrowL, 0);
pathForTurn.rLineTo(harrowL/2, harrowL/2); // center
pathForTurn.rLineTo(harrowL/2, -harrowL/2);
pathForTurn.rLineTo(-hpartArrowL, 0);
pathForTurn.rQuadTo(0, -quadShiftX, quadShiftX, -quadShiftY);
pathForTurn.rQuadTo(quadShiftX, 0, quadShiftX, quadShiftY);
pathForTurn.rLineTo(0, h);
} else if (turnType != null && turnType.isRoundAbout()) {
float t = turnType.getTurnAngle();
if (t >= 170 && t < 220) {
t = 220;
} else if (t > 160 && t < 170) {
t = 160;
}
float sweepAngle = (t - 360) - 180;
if (sweepAngle < -360) {
sweepAngle += 360;
}
float r1 = 32f;
float r2 = 24f;
float angleToRot = 0.3f;
pathForTurn.moveTo(48, 48 + r1 + 8);
pathForTurn.lineTo(48, 48 + r1);
RectF r = new RectF(48 - r1, 48 - r1, 48 + r1, 48 + r1);
pathForTurn.arcTo(r, 90, sweepAngle);
float angleRad = (float) ((180 + sweepAngle)*Math.PI/180f);
pathForTurn.lineTo(48 + (r1 + 4) * FloatMath.sin(angleRad), 48 - (r1 + 4) * FloatMath.cos(angleRad));
pathForTurn.lineTo(48 + (r1 + 6) * FloatMath.sin(angleRad + angleToRot/2), 48 - (r1 + 6) * FloatMath.cos(angleRad + angleToRot/2));
pathForTurn.lineTo(48 + (r1 + 12) * FloatMath.sin(angleRad - angleToRot/2), 48 - (r1 + 12) * FloatMath.cos(angleRad - angleToRot/2));
pathForTurn.lineTo(48 + (r1 + 6) * FloatMath.sin(angleRad - 3*angleToRot/2), 48 - (r1 + 6) * FloatMath.cos(angleRad - 3*angleToRot/2));
pathForTurn.lineTo(48 + (r1 + 4) * FloatMath.sin(angleRad - angleToRot), 48 - (r1 + 4) * FloatMath.cos(angleRad - angleToRot));
pathForTurn.lineTo(48 + r2 * FloatMath.sin(angleRad - angleToRot), 48 - r2 * FloatMath.cos(angleRad - angleToRot));
r.set(48 - r2, 48 - r2, 48 + r2, 48 + r2);
pathForTurn.arcTo(r, 360 + sweepAngle + 90, -sweepAngle);
pathForTurn.lineTo(40, 48 + r2);
pathForTurn.lineTo(40, 48 + r1 + 8);
pathForTurn.close();
}
pathForTurn.close();
if(transform != null){
pathForTurn.transform(transform);
}
}
public static class RouteDrawable extends Drawable {
Paint paintRouteDirection;
Path p = new Path();
Path dp = new Path();
public RouteDrawable(){
paintRouteDirection = new Paint();
paintRouteDirection.setStyle(Style.FILL_AND_STROKE);
paintRouteDirection.setColor(Color.rgb(100, 0, 255));
paintRouteDirection.setAntiAlias(true);
}
@Override
protected void onBoundsChange(Rect bounds) {
Matrix m = new Matrix();
m.setScale(bounds.width()/96f, bounds.height()/96f);
p.transform(m, dp);
}
public void setRouteType(TurnType t){
TurnPathHelper.calcTurnPath(p, t, null);
onBoundsChange(getBounds());
}
@Override
public void draw(Canvas canvas) {
canvas.drawPath(dp, paintRouteDirection);
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
paintRouteDirection.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paintRouteDirection.setColorFilter(cf);
}
}
}