2017-06-01 128 views
0

我想在view上繪製polyline。我不想在MapView上繪製它,因爲我只想要沒有任何背景的polyline在視圖上繪製折線時座標縮放不正確

我有polyline座標,我也有它的邊界(東北和西南座標)。

想法是創建一個自定義view並在那裏繪製路徑。我相信我遇到的問題是規模。我可以將LatLng座標轉換爲xy座標,但view上顯示的折線太小。 view的寬度和高度設置爲64dp

下面是我在做什麼:

public PolylineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    polylineSize = (int) context.getResources().getDimension(R.dimen.polyline_size); 
    setupAttributes(attrs); 
} 

private void setupAttributes(AttributeSet attrs) { 
    // Obtain a typed array of attributes 
    TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PolylineView, 0, 0); 
    // Extract custom attributes into member variables 
    try { 
     polylineColor = a.getColor(R.styleable.PolylineView_polylineColor, Color.BLACK); 

    } finally { 
     // TypedArray objects are shared and must be recycled. 
     a.recycle(); 
    } 

    polyline = new Paint(Paint.ANTI_ALIAS_FLAG); 
    polyline.setAntiAlias(true); 
    polyline.setStyle(Paint.Style.STROKE); 
    polyline.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics())); 
    polyline.setStrokeCap(Paint.Cap.ROUND); 
    polyline.setColor(polylineColor); 

    path = new Path(); 
    smp = new SphericalMercatorProjection(polylineSize); 
} 

@Override protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    point = smp.toPoint(polylineCoordinates.get(0)); 

    path.moveTo((float) (point.x * scale), (float) (point.y * scale)); 

    for (int i = 1; i < polylineCoordinates.size(); i++) { 
     point = smp.toPoint(polylineCoordinates.get(i)); 

     path.lineTo((float) (point.x * scale), (float) (point.y * scale)); 
    } 

    canvas.drawPath(path, polyline); 
} 

public void setPolyline(List<LatLng> polylineCoordinates, RealmLatLngBounds polylineBounds) { 
    this.polylineBounds = polylineBounds; 
    this.polylineCoordinates = polylineCoordinates; 

    //Find the scale 
    Point northeast = smp.toPoint(polylineBounds.getNortheast()); 
    Point southwest = smp.toPoint(polylineBounds.getSouthwest()); 
    scale = polylineSize/Math.max(Math.max(northeast.x, southwest.x), Math.max(northeast.y, southwest.y)); 

    invalidate(); 
    requestLayout(); 
} 

我以後可以改變polyline座標,以便使用view的全尺寸?

編輯:

其中之一,我可以看到轉換爲xy時的問題,值是兩個親密的(精度) enter image description here

+0

@pskink我做了這個'scale = Math.max(northeast.x/southwest.x,southwest.y/northeast.y);'但仍然沒有成功 – Favolas

+0

沒有。仍然是同樣的問題。看到我附上的圖片。可能與精確度有關。 – Favolas

+0

@pskink謝謝。這非常有用。我仍然有問題,因爲物品在回收站內,但會找到答案。 – Favolas

回答

0

隨着@pskink的幫助下,我已經成功地實現這一

private int polylineSize; 
private Paint polyline; 
private SphericalMercatorProjection smp; 


PointF northeast; 
PointF[] points; 
PointF southwest; 

Path originalPath; 
Path transformedPath; 


public PolylineView(Context context) { 
    super(context); 
} 

public PolylineView(Context context, @Nullable AttributeSet attrs) { 
    super(context, attrs); 
    polylineSize = (int) context.getResources().getDimension(R.dimen.polyline_size); 
    setupAttributes(attrs); 
} 

public PolylineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    polylineSize = (int) context.getResources().getDimension(R.dimen.polyline_size); 
    setupAttributes(attrs); 
} 

private void setupAttributes(AttributeSet attrs) { 
    // Obtain a typed array of attributes 
    TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PolylineView, 0, 0); 
    // Extract custom attributes into member variables 
    int polylineColor; 
    try { 
     polylineColor = a.getColor(R.styleable.PolylineView_polylineColor, Color.BLACK); 

    } finally { 
     // TypedArray objects are shared and must be recycled. 
     a.recycle(); 
    } 

    polyline = new Paint(Paint.ANTI_ALIAS_FLAG); 
    polyline.setAntiAlias(true); 
    polyline.setStyle(Paint.Style.STROKE); 
    polyline.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics())); 
    polyline.setStrokeCap(Paint.Cap.ROUND); 
    polyline.setColor(polylineColor); 

    smp = new SphericalMercatorProjection(polylineSize); 

} 

public void setPolylineData(List<LatLng> polylineCoordinates, RealmLatLngBounds polylineBounds) { 

    originalPath = new Path(); 
    transformedPath = new Path(); 

    Point point = smp.toPoint(polylineBounds.getNortheast()); 
    northeast = new PointF((float) point.x, (float) point.y); 

    point = smp.toPoint(polylineBounds.getSouthwest()); 
    southwest = new PointF((float) point.x, (float) point.y); 

    points = new PointF[polylineCoordinates.size()]; 

    for (int i = 0; i < polylineCoordinates.size(); i++) { 
     point = smp.toPoint(polylineCoordinates.get(i)); 
     points[i] = new PointF((float) point.x, (float) point.y); 
    } 

    originalPath.moveTo(points[0].x, points[0].y); 

    for (PointF p : points) { 
     originalPath.lineTo(p.x, p.y); 
    } 

    RectF src = new RectF(southwest.x, northeast.y, northeast.x, southwest.y); 
    RectF dst = new RectF(0, 0, polylineSize, polylineSize); 
    Matrix matrix = new Matrix(); 
    matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER); 
    originalPath.transform(matrix, transformedPath); 

    invalidate(); 
    requestLayout(); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.drawPath(transformedPath, polyline); 
} 

該視圖用於在RecyclerView並且數據被設定在onBindViewHolder

+1

如果你想使用'PointF []點臨時數組';那麼不要使用'originalPath.transform()',而應該使用'float [] points;'點數組(大小爲「polylineCoordinates.size()* 2」),並簡單地調用'matrix.mapPoints(points)',然後使用這個轉換後的點來構建你的'Path' - 這樣就不需要兩個'Path' – pskink